UserCreationForm extension not making fields in the model - django

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..

Related

Removing username from UserCreationForm and auto generating username for user based on email, first name and last name

I am trying to auto generate username for users as they sign up, however, I do not know where to set the username. I do not want to user signals, so therefore I want to set the username for users when the user signs up.
In my UserCreationForm I have remove the username by:
users = None
and inside the SingUpForm(UserCreationForm) method I have:
class SignUpForm(UserCreationForm):
class Meta:
fields = (
"first_name",
"last_name",
"email",
)
However, I do not know how to set the username for the user, should I set the username for user inside the signup view?
user = form.save(commit=False)
user.username = generate_username(user.first_name, user.last_name, user.email)
user.save()
Or should I have the generate_username() method inside my custom creation form?
Or should I have the generate_username() method inside my custom creation form?
That is probably more appropriate, since the form normally should be responsible to create a valid Userobject, you thus an override the def save method:
class SignUpForm(UserCreationForm):
class Meta:
fields = (
'first_name',
'last_name',
'email',
)
def save(self, *args, **kwargs):
user = self.cleaned_data
self.instance.username = generate_username(
user['first_name'],
user['last_name'],
user['email']
)
return super().save(*args, **kwargs)
then in the view, it is simply:
user = form.save()

Overwrite maxlength/minlength of username by Django User model in the ModelForm

Try to overwrite User models by the following code, but somehow I cannot overwrite the max_length and min_length of username.
More specifically, when I check by python manage.py shell, I do overwrite them. But it seems has no effect on the html which was rendered(username maxlength is still 150).
Don't know which parts get wrong, please help.
from django import forms
from django.contrib.auth.models import User
class RegistrationForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(RegistrationForm, self).__init__(*args, **kwargs)
email = self.fields['email']
username = self.fields['username']
email.required = True
email.label_suffix = ' '
username.label_suffix = ' '
######### this is not work!!!###############
username.min_length = 6
username.max_length = 30
############################################
class Meta:
model = User
fields = ('username', 'email')
labels = {
'username': '帳號',
}
help_texts = {
'username': '',
}
Instead of modifying the form, you should modify/override the model.
I recommend using django-auth-tools for building your own custom user model. It supplies basic models, views and forms which can be easily extended.
If you are trying to override just the model form field, you could do something like this
class RegistrationForm(forms.ModelForm):
username = forms.CharField(required=True, min_length=6, max_length=30)
class Meta:
model = User
fields = ('username', 'email')
or
class RegistrationForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(RegistrationForm, self).__init__(*args, **kwargs)
self.fields['username'] = forms.CharField(required=True, min_length=6, max_length=30)
class Meta:
model = User
fields = ('username', 'email')
But I would recommend creating a Custom User Model inherited from AbstractBaseUser to override the username or email field as documented in https://docs.djangoproject.com/en/1.10/topics/auth/customizing/

How to make UserCreationForm email field required

I am a newbie in Django.
I would like the email field in the subclassed UserCreationForm to be required.
I have tried the commented methods but none has worked so far. I have tried the solution from this but to no avail. Any help would be appreciated.
class MyRegistrationForm(UserCreationForm):
captcha = NoReCaptchaField()
#email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'class': 'mdl-textfield__input'}))
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'email', 'password')
#email = {
# 'required': True
#}
widgets = {
'first_name': forms.TextInput(attrs={'class': 'mdl-textfield__input'}),
'last_name': forms.TextInput(attrs={'class': 'mdl-textfield__input'}),
'username': forms.TextInput(attrs={'class': 'mdl-textfield__input'}),
#'email': forms.TextInput(attrs={'class': 'mdl-textfield__input'})
}
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
user.username = self.cleaned_data["username"]
user.email = self.cleaned_data["email"]
#user.user_level = self.cleaned_data["user_level"]
if commit:
user.save()
return user
def __init__(self, *args, **kwargs):
super(MyRegistrationForm, self).__init__(*args, **kwargs)
self.fields['password1'].widget.attrs['class'] = 'mdl-textfield__input'
self.fields['password2'].widget.attrs['class'] = 'mdl-textfield__input'
#self.fields['email'].required=True
This solved the problem: email = forms.CharField(required=True, widget=forms.EmailInput(attrs={'class': 'validate',}))
I checked Django's User model and it has required=False. So, I think you cannot achieve what you are looking for with the default User model based on note section of "Overriding the default fields" in the django documentation. I have inluded the snippet
ModelForm is a regular Form which can automatically generate certain
fields. The fields that are automatically generated depend on the
content of the Meta class and on which fields have already been
defined declaratively. Basically, ModelForm will only generate fields
that are missing from the form, or in other words, fields that weren’t
defined declaratively.
Fields defined declaratively are left as-is, therefore any
customizations made to Meta attributes such as widgets, labels,
help_texts, or error_messages are ignored; these only apply to fields
that are generated automatically.
Similarly, fields defined declaratively do not draw their attributes
like max_length or required from the corresponding model. If you want
to maintain the behavior specified in the model, you must set the
relevant arguments explicitly when declaring the form field.
For example, if the Article model looks like this:
class Article(models.Model):
headline = models.CharField(
max_length=200,
null=True,
blank=True,
help_text='Use puns liberally',
)
content = models.TextField() and you want to do some custom validation for headline, while keeping the blank and help_text values
as specified, you might define ArticleForm like this:
class ArticleForm(ModelForm):
headline = MyFormField(
max_length=200,
required=False,
help_text='Use puns liberally',
)
class Meta:
model = Article
fields = ['headline', 'content'] You must ensure that the type of the form field can be used to set the contents of the corresponding
model field. When they are not compatible, you will get a ValueError
as no implicit conversion takes place.
So try this,
from django.forms import EmailField
from django.core.validators import EMPTY_VALUES
# I used django [emailfield code][2] as reference for the code of MyEmailField
# Also, following comment in django [custom form fields document][2]:
# If the built-in Field classes don’t meet your needs, you can easily create custom Field classes. To do this, just create a subclass of django.forms.Field. Its only requirements are that it implement a clean() method and that its __init__() method accept the core arguments mentioned above (required, label, initial, widget, help_text).
# You can also customize how a field will be accessed by overriding get_bound_field().
class MyEmailField(forms.EmailField):
def __init__(self, *args, **kwargs):
super(MyEmailField, self).__init__(*args, strip=True, **kwargs)
# Clean would be called when checking is_clean
def clean(self,value):
if value in EMPTY_VALUES:
raise Exception('Email required')
value = self.value.strip()
return super(MyEmailField, self).clean(value)
class MyRegistrationForm(UserCreationForm):
captcha = NoReCaptchaField()
# All available arguments listed in django [core fields argument document][2]. Currently they are required, label, label_suffix, initial, widget, help_text, error_messages, validators, localize, disabled
email = MyEmailField(required=True)
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'email', 'password')
# other part of your code
PS: I have not tested this code but based on the documentation I think this should take you in a good direction.
Few more references:
Django auth.user with unique email
How to make email field unique in model User from contrib.auth in Django
https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html
Add this to your forms.py file:
class Userform(UserCreationForm):
email = forms.EmailField(required=True)
class meta:
model = User
fields = ('name','email')

Django Forms - Set username field equal to email field

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

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/