I am learning an authentication in Django. Today I am stuck with this problem and I am not able to figure out how can I solve it. I want to make a form for password change. but the change form link is not active and I don't know how to fix it.
here is my views.py
#login_required
def user_change(request):
current_user = request.user
form = UserProfileChange(instance = current_user)
if request.method == 'POST':
form = UserProfileChange(request.POST,instance = current_user)
if form.is_valid():
form.save()
form = UserProfileChange(instance = current_user)
form = UserProfileChange(instance = current_user)
return render(request, 'App_Login/change_profile.html', context={'form':form})
#login_required
def pass_change(request):
current_user = request.user
form = PasswordChangeForm(current_user)
if request.method == 'POST':
form = PasswordChangeForm(current_user, data = request.POST)
if form.is_valid():
form.save()
return render(request, 'App_login/pass_change.html', context = {'form':form})
here is urls.py file
from django.urls import path
from . import views
app_name = 'App_Login'
urlpatterns = [
path('signup/', views.signup, name = "signup"),
path('signin/', views.login_page, name = 'signin'),
path('logout/' , views.logout_user, name = "logout" ),
path('profile/' , views.profile, name = "profile" ),
path('change-profile/' , views.user_change, name = "user_change" ),
path('password/' , views.pass_change, name = "pass_change" ),
]
here is change_profile.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %} change User profile {% endblock %}
{% block body_block %}
<h2>Change Profile</h2>
<form method="post">
{% csrf_token %}
{{form|crispy}}
<input type="submit" value="Change" class = "btn btn-primary btn-sm">
</form>
{% endblock %}
here is forms.py file
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
class SignupForm(UserCreationForm):
email = forms.EmailField(label = "Email Address", required=True)
class Meta:
model = User
fields = ('username','email', 'password1', 'password2')
class UserProfileChange(UserChangeForm):
class Meta:
model = User
fields = ('username','email','first_name', 'last_name', 'password')
Django has an inbuilt functionality to do that in your urls file modify it to according your needs
from django.contrib.auth import views as auth_views
urlpatterns = [
#
# Rest Of Your Code
#
path('password/',auth_views.PasswordChangeView.as_view(
template_name='template to render here',
success_url = 'page to redirect after password is changed'),name='password')
]
Related
I am quite new to Django and followed a tutorial to create a website. I'm not able to log in to an account. When I log in with any details (correct or incorrect), my 'login' page just reloads and nothing else happens (The expected result is that I go into a different page when I log in correctly)
I am getting "POST /login/ HTTP/1.1" 200 3689 in the terminal.
Here's part of the code:
(views.py)
def loginpage(request):
error = ""
page = ""
if request.method == 'POST':
u = request.POST['email']
p = request.POST['password']
user = authenticate(request,username=u,password=p)
try:
if user is not None:
login(request,user)
error = "no"
g = request.user.groups.all()[0].name
if g == 'Doctor':
page = 'doctor'
d = {'error': error, 'page':page}
return render(request,'doctorhome.html',d)
elif g == 'Receptionist':
page = 'reception'
d = {'error': error, 'page':page}
return render(request,'receptionhome.html',d)
elif g == 'Patient':
page = 'patient'
d = {'error': error, 'page':page}
return render(request,'patienthome.html',d)
else:
error = "yes"
except Exception as e:
error = "yes"
#print(e)
#raise e
return render(request,'login.html')
Creating an account:
def createaccountpage(request):
error = ""
user="none"
if request.method == 'POST':
name = request.POST['name']
email = request.POST['email']
password = request.POST['password']
repeatpassword = request.POST['repeatpassword']
gender = request.POST['gender']
phonenumber = request.POST['phonenumber']
address = request.POST['address']
birthdate = request.POST['dateofbirth']
bloodgroup = request.POST['bloodgroup']
try:
if password == repeatpassword:
Patient.objects.create(name=name,email=email,password=password,gender=gender,phonenumber=phonenumber,address=address,birthdate=birthdate,bloodgroup=bloodgroup)
user = User.objects.create_user(name=name,email=email,password=password,username=email)
pat_group = Group.objects.get(name='Patient')
pat_group.user.set.add(user)
user.save()
error = "no"
else:
error = "yes"
except Exception as e:
error = "yes"
print("Erorr:",e)
d = {'error' : error}
#print(error)
return render(request,'createaccount.html',d)
#return render(request,'createaccount.html')
I have an issue with creating an account as well. Whenever I create an account, the data isn't saved anywhere on the database for some reason. So instead, I manually added my details to the DB and tried logging in with those details but still it's not letting me log in.
I also thought the issue could be related to the DB itself (like certain data fields might be missing, I don't think the tutorial said all the data in the DB). Hence, I tried adding some data to it to see if permissions or something would affect anything and help me log in but it did not.
I'm now completely stuck and not sure how to proceed. I don't know if it will help but I have added a picture of the Database here
I appreciate any kind of advice on how I can fix my issue of not being able to log in correctly.
You can Create a User like this. Django uses hashing technique to store users' passwords with some salt. If You are creating a user you have to call set_password method to store the password.
from django.contrib.auth.models import User
user = User()
user.username = request.POST.get('username')
user.set_password(request.POST.get('password'))
user.save()
First of all, there is no better tutorial than the original one, it will help you understand many concepts that are not quite well explained in most. No better place to start and to continue growing by further exploring the documentation.
I must say, there are many flaws in your code and project design. Lets start with the database schema you shared. I can see that you don't have a custom user model, instead you have four user models, three of them to represent groups.
In your views, use the 'snake_case' name convention, it is a good practice. Also, to handle input data and validation Django Forms are the way to do it. Lastly, it is not necessary to have three different templates to render based on the group.
To the code...It is all inside an app called 'core'
edit: updated views.py with login required decorator
First, Create the Custom User Model:
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
# Create your models here.
GENDER_CHOICES = [
('F', 'Female'),
('M', 'Male'),
]
BLOOD_GROUP_CHOICES = [
('A', 'A'),
('B', 'B'),
('O', 'O'),
('AB', 'AB'),
]
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **kwargs):
if not email:
raise ValueError('Users must have an email address')
user = self.model(email=self.normalize_email(email), **kwargs)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None):
user = self.create_user(email, password=password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
email = models.CharField(max_length=128, unique=True)
name = models.CharField(max_length=128)
gender = models.CharField(max_length=10, choices=GENDER_CHOICES)
phone_number = models.CharField(max_length=128, blank=True)
address = models.CharField(max_length=128)
birth_date = models.DateField()
blood_group = models.CharField(max_length=2, choices=BLOOD_GROUP_CHOICES)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=True)
objects = UserManager()
USERNAME_FIELD = 'email'
remember to add the model in settings.py:
AUTH_USER_MODEL = 'core.User'
forms.py
from django import forms
from django.core.exceptions import ValidationError
from datetime import datetime
from django.contrib.auth import get_user_model
GENDER_CHOICES = [
('F', 'Female'),
('M', 'Male'),
]
BLOOD_GROUP_CHOICES = [
('A', 'A'),
('B', 'B'),
('O', 'O'),
('AB', 'AB'),
]
class UserRegisterForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password_confirmation = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = get_user_model()
fields = ('email', 'name', 'gender', 'phone_number', 'address', 'birth_date', 'blood_group')
def clean_password_confirmation(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password")
password2 = self.cleaned_data.get("password_confirmation")
if password1 and password2 and password1 != password2:
raise ValidationError("Passwords don't match")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.set_password(self.cleaned_data["password"])
user.last_login = datetime.now()
if commit:
user.save()
return user
class UserSignInForm(forms.Form):
email = forms.EmailField(required=True)
password = forms.CharField(widget=forms.PasswordInput())
def save(self, commit=True):
# Save the provided password in hashed format
user = super().save(commit=False)
user.last_login = datetime.now()
if commit:
user.save()
return user
Create the views using forms and setup the URLs:
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from core.forms import UserRegisterForm, UserSignInForm
# Create your views here.
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Successful registration')
return redirect('/user/index/')
else:
messages.error(request, 'Please fill the fields correctly')
else:
form = UserRegisterForm()
context = {
'form': form
}
return render(request, 'register.html', context)
def user_login(request):
if request.method == 'POST':
form = UserSignInForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
qs = user.groups.values_list('name',flat = True)
groups = l_as_list = list(qs)
messages.success(request, 'Successfull login')
return render(request, 'index.html', {'groups': groups})
else:
messages.error(request, 'User not found')
else:
form = UserSignInForm()
context = {
'form': form
}
return render(request, 'login.html', context)
def user_logout(request):
logout(request)
return redirect('/user/login/')
#login_required(login_url='/user/login/')
def index(request):
return render(request, 'index.html', {})
urls.py
from django.urls import path
from core import views
app_name = 'core'
urlpatterns = [
path('index/', views.index, name='index'),
path('register/', views.register, name='user-register'),
path('login/', views.user_login, name='user-login'),
path('logout/', views.user_logout, name='user-logout'),
]
Create templates using forms and messages:
login.html
{% extends 'base.html' %}
{% block content %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<form method="POST" action="{% url 'core:user-login' %}">
{% csrf_token %}
<table>
{{ form }}
</table>
<input type="submit" value="Submit">
</form>
{% endblock %}
register.html
{% extends 'base.html' %}
{% block content %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<form method="post" action="{% url 'core:user-register' %}">
{% csrf_token %}
<table>
{{ form }}
</table>
<button type="submit">Register</button>
</form>
{% endblock %}
index.html
{% extends 'base.html' %}
{% block content %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% if 'doctor' in groups %}
<p>I am a doctor</p>
{% elif 'patient' in groups %}
<p>I am a patient</p>
{% elif 'receptionist' in groups %}
<p>I am a recepcionist</p>
{% endif %}
Logout
{% endblock %}
I have a problem with the image uploading from form (when i upload image from admin panel it works). Image just dont uploading, without any feedback and log. Help me pls
My view.py:
def class_article_create(request, URLcodenumber):
print(URLcodenumber)
if request.method == 'POST':
model = Article()
form = ArticleForm(
request.POST,
instance=model
)
print(request.method)
new_article = form.save(commit=False)
new_article.codenumber = Classes.objects.filter(
codenumber=URLcodenumber
)[0]
new_article.pub_date = date.today()
print(new_article.id)
if form.is_valid():
new_article.save()
return HttpResponseRedirect(f'/class/{URLcodenumber}')
return render(
request,
'blogpage\\create_article.html',
{
'clsName': f'Параллель {URLcodenumber}',
'codenumber': URLcodenumber,
'form': ArticleForm()
}
)
My models.py:
class Article(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False
)
headline = models.CharField(
max_length=50,
default='Нет заголовка'
)
text = models.TextField(
max_length=600,
)
image = models.ImageField(
upload_to='images/',
blank=True
)
pub_date = models.DateField()
codenumber = models.ForeignKey(
'Classes',
on_delete=models.CASCADE
)
create_article.html
{% extends "blogpage\layout\base.html" %}
{% load static %}
{% block title %}
Добавление ответа
{% endblock title %}
{% block nav %}
<div class="classname-div">
<p class="cls-name" align="center">{{clsName}}</p>
</div>
<a href='{% url "classpage_articles_preview" URLcodenumber=codenumber %}'>
<button class="btn-to-page">Перейти к ответам</button>
</a>
{% endblock nav %}
{% block content %}
<form method="post" class="model-form" enctype="multipart/form-data">
{% csrf_token %}
{{form.headline}}
{{form.text}}
{{form.image}}
<button class="model-form-submit" type="submit">
Добавить
</button>
</form>
{% endblock content %}
early, there wasnt the enctype="multipart/form-data", and the problem was same
media root and url in settings.py:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
urls.py:
from django.contrib import admin
from django.urls import path
from django.urls import re_path
from django.conf import settings
from django.conf.urls.static import static
from help_page.helppage_views import help_page
from start_page import startpage_views
from help_page import helppage_views
from class_page import classpage_views
urlpatterns = [
path('admin/', admin.site.urls),
path(
'',
startpage_views.start_page,
name='startpage'
),
path(
'help/<numpage>/',
helppage_views.help_page,
name='helppage'
),
path(
'class/<URLcodenumber>/',
classpage_views.class_article_preview,
name='classpage_articles_preview'
),
path(
'create/<URLcodenumber>',
classpage_views.class_article_create,
name='classpage_articles_create'
),
path(
'view/<URLcodenumber>/<uuid:uuid>',
classpage_views.class_article_view,
name='classpage_article_view'
),
path(
'createclass',
classpage_views.create_class,
name='create_class'
)
] + static(
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT
)
proj_dir => media => images is directory for the images
Thanks for any help! :)
You need to pass both request.POST and request.FILES to the form:
from django.shortcuts import get_object_or_404
def class_article_create(request, URLcodenumber):
if request.method == 'POST':
code_number = get_object_or_404(Classes, codenumber=URLcodenumber)
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
form.instance.codenumber = code_number
form.instance.pub_date = date.today()
form.save()
return HttpResponseRedirect(f'/class/{URLcodenumber}')
else:
form = ArticleForm()
return render(
request,
'blogpage/create_article.html',
{
'clsName': f'Параллель {URLcodenumber}',
'codenumber': URLcodenumber,
'form': form,
},
)
Note: Django's DateTimeField [Django-doc]
has a auto_now_add=… parameter [Django-doc]
to work with timestamps. This will automatically assign the current datetime
when creating the object, and mark it as non-editable (editable=False), such
that it does not appear in ModelForms by default.
I am working on CS50W project 2 - commerce and I've been working on the Create Listing point. I have a route /create where I have to get data and save it in models. I'll leave the code snippets below . I tried to use the ModelForm class , then validate the data and save() but it doesn't save data . I also ran queries in shell on the models to see if data is there but nothing. In the code snippets I'll leave only the useful parts to look cleaner. I checked and the imports ( importing models to views , other modules , etc) are fine. I think I made a mistake somewhere else , but I just can't see it. How to solve this?
the ModelForm
class AuctionsForm(forms.ModelForm):
class Meta:
model = Auctions
fields = ['title' , 'description' , 'category' , 'image']
views.py
#login_required
def create(request):
if request.method == "POST":
form = AuctionsForm(request.POST)
if form.is_valid():
form.save()
else:
form = AuctionsForm()
return render(request, "auctions/create.html" , {"form" : AuctionsForm()} )
models.py
class Auctions(models.Model):
CATEGORY = [
("No Category" , "No Category"),
("Fashion" , "Fashion"),
("Home" , "Home"),
("Toys" , "Toys"),
("Technology" , "Technology"),
]
title = models.CharField(max_length= 50)
description = models.TextField(max_length=150)
category = models.CharField(max_length = 40 , choices= CATEGORY , default="None")
image = models.URLField(default="" , blank=True)
is_active = models.BooleanField(default=True)
date = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey('auctions.User' , on_delete=models.CASCADE , related_name='user_auctions')
watchlist = models.ForeignKey('auctions.User' , on_delete=models.CASCADE , related_name='watchlist_auctions')
def __str__(self):
return self.title
create.html
{% extends "auctions/layout.html" %}
{% block body %}
<h1>Create Listing Here</h1>
<form method="POST" action="{% url 'index' %}">
{% csrf_token %}
{{form}}
<input type="submit" value="Create Listing">
</form>
{% endblock %}
index.html
{% extends "auctions/layout.html" %}
{% block body %}
<h2>Active Listings</h2>
{% for i in show%}
<p>{{i.title}}</p>
<p>{{i.description}}</p>
{% endfor%}
{% endblock %}
forms.py
class AuctionsForm(forms.ModelForm):
class Meta:
model = models.Auction
fields = ['title', 'description', 'category', 'image']
views.py
def create_auction(request):
if request.method == 'POST':
form = AuctionsForm(request.POST)
if form.is_valid():
auction = form.save(commit=False)
# do something if you but in the end
auction.save()
# do want you want here, or return in to creation page dunno
return render(request, "success?idk/", {"auction": auction})
else:
# maybe you want to render the errors?
# https://stackoverflow.com/questions/14647723/django-forms-if-not-valid-show-form-with-error-message
return render(request, "auctions/create.html", {"form": form})
form = AuctionForm()
return render(request, "auction/create.html", {"form":form})
# maybe you had listing view here
use Auction instead of Auctions, Django pluralize(s) it
if i upload the image through my admin dashboard, the image will be successfully uploaded, it will appear in media folder in my project directory i specified in settings.py. but if i upload an image through form.py as a user, every other field is saved except for the image field. I've tried most of the solutions on stackoverflow, dont know why mine ain't working.
while debugging i made mainimage a required field, so it threw this error: ValueError: The view products.views.products didn't return an HttpResponse object. It returned None instead.
form.py
from django import forms
from django.utils.translation import gettext_lazy as _
from .models import Product
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ['name', 'mainimage', 'category', 'preview_text',
'detail_text', 'price','Quantity']
labels = {
'name': _('Product name'),
}
help_texts = {
'name': _('be specific eg Tomatoes, Rice'),
}
error_messages = {
'name': {
'max_length': _("This writer's name is too long."),
},
}
views.py
from django.shortcuts import render, redirect
from .form import ProductForm
from .models import Product
# Create your views here.
def products(request):
if request.method == 'GET':
form = ProductForm()
return render(request, 'products/add_product.html',{'forms':form})
else:
# imagefield is different from other
# fields and it needs to be handles properly
# data fetched from imagefield would be stored
# in request.FILES object.
if request.method == 'POST':
form = ProductForm(request.POST or None, request.FILES or None)
if form.is_valid():
name = form.cleaned_data.get('name')
mainimage = form.cleaned_data.get('mainimage')
category = form.cleaned_data.get('category')
preview_text = form.cleaned_data.get('preview_text')
detail_text = form.cleaned_data.get('detail_text')
price = form.cleaned_data.get('price')
Quantity = form.cleaned_data.get('Quantity')
obj = Product.objects.create(
name = name,
mainimage = mainimage,
category = category,
preview_text = preview_text,
detail_text = detail_text,
price = price,
Quantity = Quantity
)
obj.save()
# form.save()
return redirect('/products/')
else:
form = ProductForm()
return render(request, 'add_product.html', {'form': form})
add_product
{% extends "plugs/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<h4>Add a Product</h4>
<form action="#" method="post" autocomplete="off" enctype="multipart/form-data">
{% csrf_token %}
<!-- {{form_store.store_name|as_crispy_field}}-->
<div class="col-md-3">
{{ forms.name|as_crispy_field }}
</div>
<div class="row">
<div class="col-md-4" >
{{ forms.mainimage|as_crispy_field }}
</div>
<div class="col-md-3">
{{ forms.category|as_crispy_field }}
</div>
</div>
<div class="col-md-5">
{{ forms.preview_text|as_crispy_field }}
{{ forms.detail_text|as_crispy_field }}
<!-- {{ forms.price|as_crispy_field }}-->
{{ forms.Quantity|as_crispy_field }}
</div>
<button type="submit" class="btn btn-success"><i class="fas fa-database"></i>Submit</button>
</form>
{% endblock %}
settings.py
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, '/static/media/')
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
MEDIA_URL = '/media/'
models.py
from django.db import models
# Create your models here.
class Category(models.Model):
title = models.CharField(max_length= 300)
primaryCategory = models.BooleanField(default=False)
def __str__(self):
return self.title
class Product(models.Model):
mainimage = models.ImageField(upload_to='products/', blank=True)
name = models.CharField(max_length=300)
slug = models.SlugField(blank = True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
preview_text = models.TextField(max_length = 200, verbose_name='Preview Text')
detail_text = models.TextField(max_length= 1000, verbose_name='Detail text')
price = models.FloatField()
Quantity = models.CharField(max_length=150, default='1 quantity')
def __str__(self):
return self.name
project/urls.py
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('plugs.urls')),
path('products/', include('products.urls')),
path('home/', include('cart.urls')),
# path('products/', include('products.urls')),
]
urlpatterns += staticfiles_urlpatterns()
if settings.DEBUG:
urlpatterns +=static(settings.MEDIA_URL,
document_root = settings.MEDIA_ROOT)
ok better change your view to
if request.method == 'POST':
form = ProductForm(request.POST or None, request.FILES or None)
if form.is_valid():
instance = form.save(commit=False)
instance.name = form.cleaned_data['name']
instance.mainimage = form.cleaned_data['mainimage']
instance.category = form.cleaned_data['category']
instance.preview_text = form.cleaned_data['preview_text']
instance.detail_text = form.cleaned_data.get['detail_text']
instance.price = form.cleaned_data['price']
instance.Quantity = form.cleaned_data['Quantity']
instance.save()
Is your MEDIA_DIR set in your settings.py?
MEDIA_DIR = os.path.join(BASE_DIR, '/static/media/')
ValueError: The view products.views.products didn't return an HttpResponse object. It returned None instead. Means your somewhere in your views you are not returning an Http response. Try indenting last line of your view to at same level as else. It may resolve
why I can not upload the images??
The urls.py:
see the
url(r'^things,,,
from django.conf.urls import include, url
from django.contrib import admin
from collection import views
from django.views.generic import TemplateView
from django.views.generic import (TemplateView,RedirectView,)
from collection.backends import MyRegistrationView
from django.contrib.sitemaps.views import sitemap
from collection.sitemap import (
ThingSitemap,
StaticSitemap,
HomepageSitemap,
)
sitemaps = {
'things': ThingSitemap,
'static': StaticSitemap,
'homepage': HomepageSitemap,
}
from django.contrib.auth.views import (
password_reset,
password_reset_done,
password_reset_confirm,
password_reset_complete,
)
urlpatterns = [
url(r'^$', views.index, name='home'),
url(r'^about/$',TemplateView.as_view(template_name='about.html'),name='about'),
url(r'^contact/$',views.contact, name='contact'),
url(r'^things/$', RedirectView.as_view(pattern_name='browse', permanent=True)),
url(r'^things/(?P<slug>[-\w]+)/$', views.thing_detail,name='thing_detail'),
url(r'^things/(?P<slug>[-\w]+)/edit/$', views.edit_thing,name='edit_thing'),
url(r'^things/(?P<slug>[-\w]+)/edit/images/$', views.edit_thing_uploads,name='edit_thing_uploads'),
url(r'^browse/$', RedirectView.as_view(pattern_name='browse', permanent=True)),
url(r'^browse/name/$',views.browse_by_name, name='browse'),
url(r'^browse/name/(?P<initial>[-\w]+)/$',views.browse_by_name, name='browse_by_name'),
url(r'^accounts/password/reset/$', password_reset,{'template_name':'registration/password_reset_form.html'},name="password_reset"),
url(r'^accounts/password/reset/done/$', password_reset_done,{'template_name':'registration/password_reset_done.html'},name="password_reset_done"),
url(r'^accounts/password/reset/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', password_reset_confirm,{'template_name':'registration/password_reset_confirm.html'},name="password_reset_confirm"),
url(r'^accounts/password/done/$', password_reset_complete,{'template_name':'registration/password_reset_complete.html'},name="password_reset_complete"),
url(r'^accounts/register/$',MyRegistrationView.as_view(),name='registration_register'),
url(r'^accounts/create_thing/$',views.create_thing,name='registration_register'),
url(r'^accounts/', include('registration.backends.simple.urls')),
url(r'^sitemap\.xml$', sitemap, {'sitemaps':sitemaps},name='django.contrib.sitemaps.views.sitemap'),
url(r'^admin/', include(admin.site.urls)),
]
from django.conf import settings
if settings.DEBUG:
urlpatterns += [
url(r'^media/(?P<path>.*)$','django.views.static.serve',{'document_root': settings.MEDIA_ROOT,}),
]
the views.py:
See the def edit_thing_uploads
from django.shortcuts import render,redirect
from django.contrib.auth.decorators import login_required
from django.http import Http404
from collection.forms import ThingForm,ContactForm,ThingUploadForm
from collection.models import Thing,Upload
from django.template.loader import get_template
from django.core.mail import EmailMessage
from django.template import Context
def index(request):
things = Thing.objects.all()
return render(request, 'index.html', {
'things':things,
})
def thing_detail(request, slug):
thing = Thing.objects.get(slug=slug)
social_accounts = thing.social_accounts.all()
uploads = thing.uploads.all()
return render(request, 'things/thing_detail.html',{
'thing':thing,
'social_accounts': social_accounts,
'uploads': uploads,
})
#login_required
def edit_thing(request, slug):
thing = Thing.objects.get(slug=slug)
if thing.user != request.user:
raise Http404
form_class = ThingForm
if request.method == 'POST':
form = form_class(data=request.POST, instance=thing)
if form.is_valid():
form.save()
return redirect('thing_detail', slug=thing.slug)
else:
form = form_class(instance=thing)
return render(request, 'things/edit_thing.html',{'thing':thing,'form':form,})
#login_required
def edit_thing_uploads(request, slug):
thing = Thing.objects.get(slug=slug)
if thing.user != request.user:
raise Http404
form_class = ThingUploadForm
if request.method == 'POST':
form = form_class(data=request.POST,files=request.FILES, instance=thing)
if form.is_valid():
Upload.objects.create(
image=form.cleaned_data['image'],
thing=thing,
)
return redirect('edit_thing_uploads', slug=thing.slug)
else:
form = form_class(instance=thing)
uploads = thing.uploads.all()
return render(request, 'things/edit_thing_uploads.html', {
'thing': thing,
'form': form,
'uploads': uploads,
})
def create_thing(request):
form_class = ThingForm
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
thing = form.save(commit=False)
thing.user = request.user
thing.slug = slugify(thing.name)
thing.save()
return redirect('thing_detail', slug=thing.slug)
else:
form = form_class()
return render(request, 'things/create_thing.html', {'form':form,})
def browse_by_name(request, initial=None):
if initial:
things = Thing.objects.filter(name__istartswith=initial)
things = things.order_by('name')
else:
things = Thing.objects.all().order_by('name')
return render(request, 'search/search.html', {'things':things,'initial':initial,})
def contact(request):
form_class = ContactForm
if request.method == 'POST':
form = form_class(data=request.POST)
if form.is_valid():
contact_name = form.cleaned_data['contact_name']
contact_email = form.cleaned_data['contact_email']
form_content = form.cleaned_data['content']
template = get_template('contact_template.txt')
context = Context({
'contact_name':contact_name,
'contact_email':contact_email,
'form_content':form_content,
})
content = template.render(context)
email = EmailMessage(
'New contact form submission',content,
'Your website <hi#weddinglovely.com>',['fnt437#gmail.com'],
headers = {'Reply-To':contact_email }
)
email.send()
return redirect('contact')
return render(request, 'contact.html', {'form': form_class, })
The forms.py:
from django import forms
class ThingForm(ModelForm):
class Meta:
model = Thing
fields = ('name','description',)
class ContactForm(forms.Form):
contact_name = forms.CharField(required=True)
contact_email = forms.EmailField(required=True)
content = forms.CharField(
required=True,
widget=forms.Textarea
)
def __init__(self, *args, **kwargs):
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Your name:"
self.fields['contact_email'].label = "Your email:"
self.fields['content'].label = "What do you want to say?"
class ThingUploadForm(ModelForm):
class Meta:
model = Upload
fields = ('image',)
the edit_thing.html:
{% extends 'layouts/base.html' %}
{% block title %}
Edit {{ thing.name }} - {{ block.super }}
{% endblock %}
{% block content %}
<h1>Edit "{{ thing.name }}"</h1>
Edit images
<form role="form" action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock %}
the edit_thing_uploads.html:
{% extends 'layouts/base.html' %}
{% block title %}
Edit {{ thing.name }}'s Images - {{ block.super }}
{% endblock %}
{% block content %}
<h1>Edit {{ thing.name }}'s Images</h1>
<h2>Uploaded images</h2>
{% for upload in uploads %}
<img src="{{ uploads.image.url }}" alt="" />
{% endfor %}
<h2>Uploads a new image</h2>
<form role="form" action="" method="post" enctype="multipart/form\-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" />
</form>
{% endblock %}
the diirectory tree:
when I click in http://127.0.0.1:8000/things/another-things/edit/ is ok
however when I click the Edit images link to submit upload images it said no file has been choice?? I can not upload the images
You have to check the file permissions of
edit_thing_uploads.html
, make sure the file is accessible. because the path has been correct. and Django can't see it.
I got to know why ,,because I typos <form role="form" action="" method="post" enctype="multipart/form-data"> ---> <form role="form" action="" method="post" enctype="multipart/form\-data"> in edit_thing_uploads.html