I'm trying to create a custom form where the user can also enter his name for instance but I am facing an issue, when the registration is done the name is not saved and I can't show it on the template.
here is the code
views.py
def register_user(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/user/')
else:
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/user/')
context = {}
context.update(csrf(request))
context['form'] = MyRegistrationForm()
return render(request, 'register.html', context)
forms.py
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
name = forms.CharField(required=True)
class Meta:
model = User
fields = {'name', 'username', 'password1', 'password2', 'email'}
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.name = self.cleaned_data['name']
if commit:
user.save()
return user
register.html
<form action="/user/register/" method="post" id="register" autocomplete="off">
{% csrf_token %}
<div class="fieldWrapper">
{{ form.name.errors }}
{{ form.name.label_tag }}
{{ form.name }}
</div>
[... other form fields ...]
</div>
<input type="submit" value="Register"/>
</form>
So when I submit the form, everything works but when I try to show {{ user.name }} in the template, nothing is shown, why is that? (it works for the email field)
The default User object doesn't have a name field (so you are actually just saving the content of your name field to the object, and not the database). It has a first_name and last_name so you can either use those fields instead or you can customize the User model to have a separate name field
Edit
Also, just so you know, if you use the first_name and last_name fields instead, the User model has a get_full_name() method built-in which might be useful
The User does not have a "name" field. Try:
{{ user.username }}
Related
I am new to Django and was following a tutorial on how to build a register view. I did exactly the same but my form does not pass form.is_valid().
Here is what I did:
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
user = form.save()
return HttpResponseRedirect('/accounts/register_success')
form = MyRegistrationForm()
return render(request, 'register.html', {'form':form})
def register_success(request):
return render(request, 'register_success.html')
register.html
{% extends "base.html" %}
{% block content %}
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="Register" />
</form>
{% endblock %}
When I tried to register new users on the webpage, none of them passed. Even when I used username: testuser email: testuser#example.com password:testuser123, it failed. So what is wrong?
Thanks in advance!
You should follow the correct view pattern. Put the line form = MyRegistrationForm() inside an else block, then the page itself will tell you why the form is not valid.
I used {{ form }} as seen here
template.html
<h4>Change your details</h4><br>
<form id="edit_form" method='post'>
{% csrf_token %}
{{ form }}
<div class='section group'>
<input id="update_details_button" type='submit' class='btn btn-primary wide' value='Change'/>
</div>
</form>
views.py
def user_view(request, is_admin):
user = request.user
form = myForm()
if request.method == 'POST' and is_admin:
form = myForm(request.POST)
if form.is_valid():
data = form.cleaned_data
user.name = data['name']
user.country = data['country']
user.save()
messages.success(request, 'You have successfully updated your details.')
return render(request, 'mysite/user.html', {
'user': user,
'is_admin': is_admin,
'form': form,
})
My form is as followed
class myForm(forms.Form):
name = forms.CharField(
label="Name",
widget=forms.TextInput(attrs={'placeholder': 'Name'}))
country = CountryField(blank_label='(select country)')
def __init__(self, *args, **kwargs):
super(myForm, self).__init__(*args, **kwargs)
The name field displayed fine on the page but there's no sign of the CountryField, could someone point out the error? The code compiled fine and gives no error while server is running.
CountryField is a model field, not a form field. You're supposed to add it to your user model, in which case a modelform based on that model will automatically generate a country field. Since it looks like you have actually added a field called country to the User model, that's where you should be using CountryField.
However, for reference, to do it manually on a non-model form is slightly more complicated:
from django_countries import widgets, countries
class myForm(forms.Form):
country = forms.ChoiceField(widget=CountrySelectWidget, choices=countries)
In fact it's simpler: https://pypi.org/project/django-countries/#custom-forms
from django_countries.fields import CountryField
class MyForm(forms.Form):
country = CountryField(blank=True).formfield()
If you have installed django_country and it added in installed app than no need to make it from just use like this
{% load countries %}
<select name="country">
{% countries %}
<option value="{{ code }}">{{ name }}</option>
{% endcountries %}
</select>
I'm trying to write a small Django system. After logging into the system, a user can edit and save his/her own profile information. The fields involved are: username, email, first name, last name, website and picture.
The problem: The picture cannot be updated (After selecting an image and clicking "update" button, it shows "No file selected". The profile picture displayed on the page is still the old one). But the other fields are all OK.
Here are my codes:
models.py:
class UserProfile(models.Model):
user = models.OneToOneField(User)
website = models.URLField(blank=True)
picture = models.ImageField(upload_to="profile_images", blank=True)
def __str__(self):
return self.user.username
forms.py:
class UserForm2(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('website', 'picture')
views.py:
#login_required
def update_user(request):
try:
user_profile = UserProfile.objects.get(user=request.user)
except UserProfile.DoesNotExist:
return HttpResponse("invalid user_profile!")
if request.method == "POST":
update_user_form = UserForm2(data=request.POST, instance=request.user)
update_profile_form = UserProfileForm(data=request.POST, instance=user_profile)
if update_user_form.is_valid() and update_profile_form.is_valid():
user = update_user_form.save()
profile = update_profile_form.save(commit=False)
profile.user = user
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
profile.save()
else:
print(update_user_form.errors, update_profile_form.errors)
else:
update_user_form = UserForm2(instance=request.user)
update_profile_form = UserProfileForm(instance=user_profile)
return render(request,
'userprofile/update_user.html',
{'update_user_form': update_user_form, 'update_profile_form': update_profile_form}
)
update_user.html:
<form id="update_user_form" method="POST" action="/userprofile/update_user/">
{% csrf_token %}
{{ update_user_form.as_p }}
{{ update_profile_form.as_p }}
<img src="{{ update_profile_form.instance.picture.url }}" />
<br />
<input type="SUBMIT" name="submit" value="Update"/>
</form>
How can I make it work properly?
To upload the file you should add the enctype attribute to the <form> tag:
<form id="update_user_form" method="POST" action="/userprofile/update_user/"
enctype="multipart/form-data">
In my application, I used email and password for user authentication, which works fine. However, I want to offer the user the option of adding other information to their account like first names, last names, and dates of birth.
I have a change form in myapp.forms.py
class MyChangeForm(forms.ModelForm):
"""
Form for editing an account.
"""
first_name = forms.CharField(widget=forms.TextInput, label="First name")
last_name = forms.CharField(widget=forms.TextInput, label="Last name")
date_of_birth = forms.DateField(widget=forms.DateField, label="Date of birth")
class Meta:
model = MyUser
fields = ['first_name', 'last_name', 'date_of_birth']
def save(self, commit=True):
user = super(MyChangeForm, self).save(commit=False)
if commit:
user.save()
return user
in my views.py, I have the following method for updating
#login_required(login_url='/')
def update_user(request):
if request.method == 'POST':
form = MyChangeForm(request.POST, instance=request.user)
if form.is_valid():
user = form.save(commit=False)
user.save()
return HttpResponseRedirect('/')
else:
form = MyChangeForm(instance=request.user)
return render_to_response('update_user.html', context_instance=RequestContext(request))
and my update_user.html is as follows
{% extends 'user_base.html' %}
{% block content %}
<div class="col-sm-3 col-sm-offset-5">
<h1> Update User</h1>
<form method='POST' action='/update_user/'> {% csrf_token %}
<ul>
{{ form.as_table }}
</ul>
<input type='Submit' class='btn btn-primary btn-block'>
</form>
</div>
{% endblock %}
However, when I serve the file I see this:
As seen here, there's no way to enter my fields!
How can I fix this? It's probably easy, but I'm getting tunnel vision.
erip
Add form to the context, for example like this:
render('update_user.html', {'form': form})
I am getting a valid response back when requesting my form, but I am getting no form fields with the response. It is loading the Submit button only, but no form fields.
Goal: get form fields to load and be able to submit form.
I have a views.py:
def Registration(request):
form = NewUserRegistrationForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
return HttpResponseRedirect("/Login/")
else:
form = NewUserRegistrationForm()
return render(request, 'VA/reuse/register.html', {
'form': form
})
forms.py
class NewUserRegistrationForm(UserCreationForm):
username = forms.CharField(required=True,max_length=30,validators=[RegexValidator('^[A-Za-z0-9]{1,30}$','e.g. must be 30 characters or less','Invalid Entry')])
email = forms.EmailField(required=True, max_length=75)
password = forms.PasswordInput()
class Meta:
model = User
fields = ("username", "email", "password1","password2")
def save(self, commit=True):
user = super(NewUserRegistrationForm, self).save(commit=False)
user.username = self.cleaned_data["username"]
user.email = self.cleaned_data["email"]
user.password = self.cleaned_data["password1"]
if commit:
user.save()
return user
a template
<div id="register_bubble">
<form method="post" id="userRegistration">
{% csrf_token %}
{{ NewUserRegForm.as_p }}
<input type="submit" value="Submit" />
</form> <!-- /RegistrationForm (FORM) -->
</div>
What am I doing wrong here? I'm getting no error while in debug mode locally either.
Thank you!
You have two mistakes.
Firstly, you're passing the form class into the template context, not the form instance: the class is NewUserRegistrationForm, but you've instantiated it as NewUserRegForm, and that's what you should be passing as the value in the form context.
To make it more complicated, the key name you've given to that value is also NewUserRegistrationForm - but you're still referring to NewUserRegForm in the template, even though that doesn't exist there.
This would be much more obvious if you used PEP8 compliant names. Instances should be lower case with underscore: eg new_user_registration_form. However, in this case you could just call it form, since there's only one.
return render(request, 'mysite/reuse/register.html', {
'NewUserRegForm': NewUserRegForm
})
or, better:
form = NewUserRegistrationForm(request.POST or None)
...
return render(request, 'mysite/reuse/register.html', {
'form': form
})
You're passing the form instance to the context as 'form', but calling it in the template as {{ NewUserRegForm.as_p }}.
You should use {{ form.as_p }} instead.