I use UserCreationForm to render registration form in Django.
class RegisterForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
fields = UserCreationForm.Meta.fields
The registration view is defined as follows:
def register(request):
form = RegisterForm()
if request.method == 'POST':
form = RegisterForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
return redirect('/')
else:
context = {'form': form}
return render(request, 'registration/register.html', context)
And the template for this:
{% if form.errors %}
<p>Some Errors occured</p>
{% endif %}
<form action="{% url 'register' %}" method="POST">
{% csrf_token %} {{ form.as_p }}
<input type="submit" value="Register">
</form>
When I submit invalid data, it does not show <p>Some Errors occured</p>, but throws
Exception Type: ValueError
Exception Value:
The view myapp.views.register didn't return an HttpResponse object. It returned None instead.
which means I have to return HttpResponsein the 2nd if/else statement. The other forms work fine and show form.error messages, except this one. What is the problem? Thanks.
form = RegisterForm(request.POST or None, request.FILES or None)
first of all you dont wanna an empty field in your register form so you dont wanna user or None . second you are using request.FILES while you have no FileField in your form . i fixed your form
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
return redirect('/')
else:
form = RegisterForm()
return render(request, 'registration/register.html',{'form': form})
You need to move the last line back one indent, so it is run both in the case that the request is not a POST and also when it is a POST but the form is not valid.
Related
How can I show errors like email or username is already taken in this page Aaccounts/sign-up.html because when try to to put a username and this username is already taken the page only refresh without any message.
Before:
After:
Code:
class SignUpView(CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'Aaccounts/sign-up.html'
def login (request) :
if request.method=='POST':
passwordtest=request.POST ['password']
usernametest=request.POST ['username']
user=auth.authenticate(username=usernametest,password=passwordtest)
if user is not None :
auth.login(request,user)
current_user = request.user
correctUSER = get_object_or_404(CustomUser, pk=current_user.id)
need_to_cheack=correctUSER.main_affilitee
kain=False
if need_to_cheack !="":
objs=CustomUser.objects.all()
for aleratwar in objs:
if kain==False:
if aleratwar.username==need_to_cheack and aleratwar.afilliteuser==True and aleratwar.username !=correctUSER.username :
kain=True
if kain== False:
correctUSER.main_affilitee=''
correctUSER.save()
return redirect('home')
else:
return render(request,'Aaccounts/login.html',{'eroor':True})
else:
return render(request,'Aaccounts/login.html')
This is the simple example of showing the message. In your view you can In this way
from django.contrib import messages
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
auth_login(request, user)
return redirect('index')
else:
messages.error(request,'username or password not correct')
return redirect('login')
else:
form = AuthenticationForm()
return render(request, 'todo/login.html', {'form': form})
{{ message }}
</div>
{% endfor %}
and In your template:
{% for message in messages %}
<div class="alert alert-success">
<a class="close" href="#" data-dismiss="alert">×</a>
{{ message }}
</div>
{% endfor %}
I created a profile form in models.py for and form.py to update it but all thing got updated except profile picture
views.py
views.py
#login_required
def update_profile(request):
if request.method == 'POST':
profile_form = ProfileForm(request.POST, request.FILES, instance=request.user.profile)
if profile_form.is_valid():
profile_form.save()
messages.success(request, "Your profile updated.")
else:
status_code = 400
message = 'Please correct the error below.'
messages.error(request, "Please use correct information")
else:
profile_form = ProfileForm(instance=request.user.profile)
return render(request, 'profile.html', {
'profile_form': profile_form
})
forms.py
models.py
First of, you need to include request.FILES where you initialize your form in the POST request like this:
profile_form = ProfileForm(request.POST, request.FILES, instance=request.user.profile)
Then in your html you need to add enctype="multipart/form-data" attribute to your form:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ profile_form.as_p }}
<button type="submit" value="Submit"></button>
</form>
try using forward slash at the end of upload_to path like this: upload_to='profile_pics/'
I have a registration form and am adding a user profile to add another field.
after the registration form is filled and submitted the form details are not submitted
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Assigned_Group = models.CharField(max_length=500)
def __str__(self):
return self.user.username
views.py
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
profile_form = UserProfileForm(request.POST)
if form.is_valid() and profile_form.is_valid():
user = form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('index')
else:
form = RegistrationForm()
profile_form = UserProfileForm()
context = {'form': form, 'profile_form':profile_form}
return render(request, 'registration/register.html', context )
def index(request):
if request.user.is_authenticated:
username = request.user.username
else:
username = 'not logged in'
context = {'username':username}
return render(request, 'index.html', context)
urls.py
path('Register/', views.register, name='register'),
in your html page in body you have to insert {% csrf_token %} like:
<html>
<body>
{% csrf_token %}
</body>
Inside your html form you will need to have inserted {% csrf_token %}.
See the django docs on CSRF for more information or if you are using AJAX.
For example your html will then look something like.
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit">
</form>
Side note from the django docs (which is important).
In the corresponding view functions, ensure that RequestContext is used to render the response so that {% csrf_token %} will work properly. If you’re using the render() function, generic views, or contrib apps, you are covered already since these all use RequestContext.
I would like to use a model form on the django.auth user, but I want to be able to pass in the PK to the model to manage other users, not the logged in user.
Is there a way to do this or do I need to create a regular form?
Django admin site is not appropriate for my use case.
Something like (which doesn't work of course...):
View
def edit_user(request,pk):
if request.method == 'POST':
user_form = UserEditForm(queryset=User.objects.get(pk=pk),
data=request.POST)
if user_form.is_valid():
user_form.save()
messages.success(request, 'User updated successfully')
else:
messages.error(request, 'Error updating your profile')
else:
user_form = UserEditForm(queryset=User.objects.get(pk=pk))
return render(request, 'edit_user.html', {'user_form': user_form })
UserEdit Form
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
Template:
% block content %}
<h1>Edit User:</h1>
<p> </p>
<form action="." method="post" enctype="multipart/form-data">
{{ user_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Save changes" class="btn btn-primary"> Manage</p>
</form>
{% endblock %}
Example URL: profile/edit-user/3/
I want the form populated with the PK of the user (the 3 in this case) NOT like my edit your own profile which passes in instance=request.user:
View for profile
def user_profile(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user,
data=request.POST)
profile_form = UserProfileEditForm(instance=request.user.profile,
data=request.POST,
files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Profile updated successfully')
else:
messages.error(request, 'Error updating your profile')
else:
user_form = UserEditForm(instance=request.user)
profile_form = UserProfileEditForm(instance=request.user.profile)
return render(request, 'profile_edit.html', {'user_form': user_form,
'profile_form': profile_form})
Still very new to django...
Thanks for your help.
BCBB
You just need to get the user you want and then pass it in to the form as the instance argument, exactly as you did with the logged in user.
def edit_user(request, pk):
user = User.objects.get(pk=pk)
if request.method == 'POST':
user_form = UserEditForm(instance=user,
data=request.POST)
...
else:
user_form = UserEditForm(instance=user)
...
This is my view:
def main_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
else:
form = RegistrationForm()
variables = {
'form': form
}
return render(request, 'main_page.html', variables)
and this is my main_page.html:
{% if form.errors %}
<p>NOT VALID</p>
{% for errors in form.errors %}
{{ errors }}
{% endfor %}
{% endif %}
<form method="post" action="/">{% csrf_token %}
<p><label for="id_username">Username:</label>{{ form.username }}</p>
<p><label for="id_email">Email Address:</label>{{ form.email }}</p>
<p><label for="id_password">Password:</label>{{ form.password1 }}</p>
<p><label for="id_retypePassword">Retype Password:</label>{{ form.password2 }}</p>
<input type="hidden" name="next" />
<input type="submit" value="Register" />
</form>
When I go to the url which uses the main_page view, it just displays the form. When I submit the form with errors (with blank fields and without a proper email address) it just redirects me to the same page and doesn't display any errors. It doesn't even say "NOT VALID".
When I change
{% if form.errors %}
to
{% if not form.is_valid %}
it always says "NOT VALID" (even if it is the first time going to the url and even if I didn't submit anything yet).
This is my RegistrationForm:
from django import forms
import re
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
class RegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=30)
email = forms.EmailField(label='Email')
password1 = forms.CharField(label='Password', widget=forms.PasswordInput())
password2 = forms.CharField(label='Password (Again)', widget=forms.PasswordInput())
def clean_password2(self):
if 'password1' in self.cleaned_data:
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 == password2:
return password2
raise forms.ValidationError('Passwords do not match.')
def clean_username(self):
username = self.cleaned_data['username']
if not re.search(r'^\w+$', username): #checks if all the characters in username are in the regex. If they aren't, it returns None
raise forms.ValidationError('Username can only contain alphanumeric characters and the underscore.')
try:
User.objects.get(username=username) #this raises an ObjectDoesNotExist exception if it doesn't find a user with that username
except ObjectDoesNotExist:
return username #if username doesn't exist, this is good. We can create the username
raise forms.ValidationError('Username is already taken.')
It is redirecting you because you always return HttpResponseRedirect if the method is POST, even if the form is not vaild. Try this:
def main_page(request):
form = RegistrationForm()
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
variables = {
'form': form
}
return render(request, 'main_page.html', variables)
That way, the form instance, on which is_valid was called, is passed to the template, and it has a chance to display the errors. Only if the form is valid, the user is redirected. If you want to be fancy, add a message using the messages framework before redirecting.
If you want it a little bit more concise:
def main_page(request):
form = RegistrationForm(request.POST or None)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
variables = {
'form': form
}
return render(request, 'main_page.html', variables)
Make your view something like this:
if form.is_valid():
pass
# actions
else:
# form instance will have errors so we pass it into template
return render(request, 'template.html', {'form': form})
And in the templates you can iterate over form.errors or simple:
{{ forms.as_p }}
You can reformat your view to display the form errors in the console as below
def main_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
else:
print(form.errors)
return HttpResponse("Form Validation Error")
return HttpResponseRedirect('/')
else:
form = RegistrationForm()
variables = {
'form': form
}
return render(request, 'main_page.html', variables)
As always, keep the indent as above. If the form has any error , it will display in the console like
<ul class="errorlist"><li>date<ul class="errorlist"><li>Enter a valid date.</li></ul></li></ul>
Hope it helps