Django Forms - Set username field equal to email field - django

I've got a Django Model Form and I am trying to set the username field equal to the email field.
Here's my form
class UserForm(forms.ModelForm):
email = forms.EmailField()
username = forms.CharField(widget=forms.HiddenInput())
class Meta:
model = User
fields = ('email', 'username')
I am currently using some JavaScript to copy the new email value to the username hidden input before the user submits the form but I would like to do this server side.
I've tried to set it by doing the following UserForm['username'] = email before saving the form and got the following error object does not support item assignment.
Any tips would be appreciated.

I did not test this, I think it would work. If not check out overriding the save method which definitely works. Django Model Field Default Based Off Another Field in Same Model
class UserForm(forms.ModelForm):
email = forms.EmailField()
username = forms.CharField(default=email)
class Meta:
model = User
fields = ('email', 'username')

Maybe it will be useful
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import User
more info
enter link description here
class UserForm(UserCreationForm):
class Meta:
model = User
fields = ('email', 'username')
email = forms.EmailInput(attrs={'placeholder': "Email"})
def save(self, commit=True):
user = super(UserForm, self).save(commit=False)
user.username = user.email
if commit:
user.save()
return user

Related

Why does my user have the email attribute that I added to the user model but not any of the other attributes that I added?

When adding on to Django's contrib User model in the forms.py file of my user app, the email field that I copied from a tutorial works perfectly but the other attributes that I added do not seem to exist.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
gradClass = forms.IntegerField(required=False)
major = forms.CharField(max_length=30)
dorm = forms.CharField(max_length=30)
hometown = forms.CharField(max_length=30)
interests = forms.CharField(max_length=100)
bio = forms.CharField(max_length=300)
class Meta:
model = User
fields = ['username', 'password1', 'password2', 'email',
'gradClass', 'major', 'dorm', 'hometown', 'interests',
'bio',
]
When I request to see a user email in the shell, it shows me their email, but when I request gradClass for example, it tells me that the user does not have any attribute called gradClass. How do I fix this? Is there something I might be missing in my other files?

UserCreationForm extension not making fields in the model

I have extended the Usercreationform as follows:
//forms.py
class UserCreationForm(UserCreationForm):
email = EmailField(label=_("Email address"), required=True,
help_text=_("Required."))
city= forms.CharField(label= _("City"),max_length=20, required=True)
state= forms.CharField(label= _("State"),max_length=20, required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2","city","state")
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
user.city = self.cleaned_data["city"]
user.state = self.cleaned_data["state"]
if commit:
user.save()
return user
This works fine till the form part. the template shows all these fields but there is a problem here. the fields that i added like city,state,etc are showing on the form but when i query like User.city or anything except the inbuilt, it gives me that User has no attribute city...this means that the fields are not being created in the in-built User model...So how do i do it?
It's a common problem. Ok do you have a complete form to your user, but your model (user) are complete? So wath you need to implement is an extension of your user model (to add your custom fields). How to Extend Django User Model will help you..

django admin form won't be modify

from django import forms
from .models import SignUp
class forml(forms.ModelForm):
class Meta:
model = SignUp
fields = ['Email', 'Name']
# exclude =['sam']
def clean_email(self):
email = self.cleaned_data.get('Email')
email_base, ext = email.split("#")
exname, domain = ext.split(".")
if not domain == "gov":
raise forms.ValidationError("plz write .gov")
return email
here i'm trying to force the user to sign up with .gov email but for a reason that i can't know it's doing the work !
Your problem is with the uppercase field names.
have you tried calling def clean_Email(self): ???
Also, consider having all your fields lowercase. In python, only class name should be Camelcase.
Hope it helps.

Accessing field from OneToOne field in ModelForm

I am trying to extend Djangos authentication system and have a problem when trying to create the modelForm for it. As you can see below I have referenced the authentication backend via the suggested OneToOnefield however when I am creating the ModelForm if I try to reference the fields such as 'username', 'password' etc. it spits an error saying they are unknown fields. The form I am creating is a registration from. What am I doing wrong here? Cheers
Model -
class StudentModel(models.Model):
user = models.OneToOneField(User, unique=True)
birth_date = models.DateField()
contact_number = models.IntegerField()
referral = models.CharField(max_length=100, choices=referral_choices)
ModelForm -
from django import forms
from opus_login.models import StudentModel, EmployerModel
class StudentForm(forms.ModelForm):
class Meta:
model = StudentModel
fields = ['username', 'first_name']
Error -
django.core.exceptions.FieldError: Unknown field(s) (username, first_name) specified for StudentModel
A common solution when you need to extend the User model with another model is use two ModelForms: one for User and another for extending model (Student in your case). In the first you access the needed fields of the User model, in the second those of the Student model.
class UserForm(forms.ModelForm):
password = forms.CharField(label='Password',widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password',widget=forms.PasswordInput)
class Meta:
model = User
fields = ('username', 'first_name')
def clean_password2(self):
.......
return password2
class StudentForm(forms.ModelForm):
class Meta:
model = StudentModel
fields = ['birthdate', 'contact_number']
Then, in the view, you work with two forms instead of one. For example:
def register(request):
if request.method == 'POST':
user_form = UserForm(request.POST)
student_form = StudentForm(request.POST)
if user_form.is_valid() and student_form.is_valid():
user_form.save()
student_form.save()
And in your template you combine both forms in one:
<form action="." method="post">
{{ user_form.as_p }}
{{ student_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Register"></p>
</form>
You can't directly access One2One fields like this. You need to first create a object of User and add to One2One relation. You can try like this:
from django import forms
from opus_login.models import StudentModel, EmployerModel
class StudentForm(forms.ModelForm):
username = forms.CharField()
first_name = forms.CharField()
class Meta:
model = StudentModel
fields = ['__all__']
def save(self, **kwargs):
student = super().save(commit=False)
user = User.objects.create(username=self.cleaned_data['username'], first_name=self.cleaned_data['first_name'])
user.set_password(self.cleaned_data['password']) #if there is a password field
student.user = user
student.save(commit=True)
return student

Django related models and UpdateView fields

I created a model (UserSettings) to extend django's User model through a OneToOneField (as recommended by the documentation):
class UserSettings(models.Model):
user = models.OneToOneField(User, primary_key=True)
subscribeToMails = models.BooleanField(default=True)
[...]
I wish to offer my users a way to edit some of their profile data, some of which is stored in the User model (the email address), and the rest in the UserSettings model. How may I do that?
I thought of two ways: adding another OneToOneField in the UserSettings model for the email address field; or overriding the UpdateView get_queryset() method (but I'm not sure how). Is there a best or recommended way to do it? So far here's how my view look:
class EditUser(UpdateView):
model = UserSettings
fields = ('emailVisible', 'subscribeToMails', 'mpPopupNotif',
'mpEmailNotif', 'avatar', 'quote', 'website')
template_name = 'user/edit.html'
def get_object(self):
return UserSettings.objects.get(user_id=self.request.user)
def get_success_url(self):
return reverse_lazy('user:edit')
Thanks for the replies! However, since I couldn't figure out how to make this work and thought using two tables eventually resulted in too much clutter to my taste, I finally went with the easier route and subclassed AbstractUser:
# models.py
class ForumUser(AbstractUser):
subscribeToMails = models.BooleanField(default=True)
[...]
# views.py
class EditUser(LoginRequiredMixin, UpdateView):
model = ForumUser
fields = ('email', 'emailVisible', 'subscribeToMails', 'mpPopupNotif',
'mpEmailNotif', 'avatar', 'quote', 'website')
template_name = 'user/edit.html'
success_url = reverse_lazy('forum:welcome')
def get_object(self):
return ForumUser.objects.get(username=self.request.user)
I only had to change my registration form:
# forms.py
class RegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = ForumUser
fields = ('username', 'email', 'password1', 'password2')
def clean_email(self):
"Ensure registered emails are unique."
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if email and ForumUser.objects.filter(email=email).exclude(
username=username).count():
raise forms.ValidationError('Email address already in use.')
return email
def clean_username(self):
"""
UserCreationForm method where mentions of the User model are replaced
by the custom AbstractUser model (here, ForumUser).
https://code.djangoproject.com/ticket/19353#no1
and https://docs.djangoproject.com/en/1.7/_modules/django/contrib/
auth/forms/#UserCreationForm
"""
username = self.cleaned_data["username"]
try:
ForumUser.objects.get(username=username)
except ForumUser.DoesNotExist:
return username
raise forms.ValidationError(
self.error_messages['duplicate_username'],
code='duplicate_username',
)
Use this solution:
mix both User and UserSettings in a form like this:
class EmployeeEditForm(forms.ModelForm):
#fields from User model that you want to edit
first_name = forms.CharField(required=False, label=_('First Name'))
last_name = forms.CharField(required=False, label=_('Last Name'))
class Meta:
model = UserSettings
fields = ('first_name', 'last_name', 'subscribeToMails')
You can access to User and UserSettings object in views.py like this:
user = request.user
usersettings = user.usersettings
Now you can edit User object like this:
user.first_name = request.POST['first_name']
user.last_name = request.POST['last_name']
user.save()
And edit UserSettings like this:
usersettings.subscribeToMails = request.POST['subscribeToMails']
usersettings.save()
Formsets is the best way to go about it.
https://docs.djangoproject.com/en/dev/topics/forms/formsets/