I am using UserCreationForm for registration of the user. Added one address filed as mandatory in the code. however whenever the user is registering on the html page the address input is present.In the admin panel for users the address is not present.
form.py
class RegistrationForm(UserCreationForm):
email=forms.EmailField(required=True)
address=forms.CharField(max_length=250,required=True)
class Meta:
model=User
fields=(
'username',
'first_name',
'last_name',
'email',
'address',
'password1',
'password2'
)
def save(self,commit=True):
user=super(RegistrationForm,self).save(commit=False)
user.first_name=self.cleaned_data['first_name']
user.last_name=self.cleaned_data['last_name']
user.email=self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register(request):
print("inside views")
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('./login.html')
else:
form = RegistrationForm()
args = {'form': form}
return render(request,'./reg_form.html',args)
else:
form = RegistrationForm()
args = {'form': form}
return render(request,'./reg_form.html',args)
In the user model all the fields are seen in the admin page,just address is not present. However while registering the user, address input is accepted.
I think you need to add this code in your models.py this field you input is required, they are added by default.
Email & Password & last_name & first_name are required by default.
REQUIRED_FIELDS = ['Address', 'SomethingElse']
and then in your admin.py
admin.py
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserAdminCreationForm, UserAdminChangeForm
from .models import User
name of your class and your Object you want to add in admin page.
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserAdminChangeForm
add_form = UserAdminCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'admin', 'first_name', 'address')
list_filter = ('admin', 'staff', 'active')
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name', 'address')}),
('Permissions', {'fields': ('admin', 'staff', 'active')}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'first_name', 'address', 'active', 'staff', 'admin')}
),
)
search_fields = ('email')
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
# Remove Group Model from admin. We're not using it.
admin.site.unregister(Group)
finally, you can check how I add address field into my project
by this link in Viva-ecommerce-models.py and Follow the Class Address
Related
I created a custom model extending AbstractUser in order to authenticate users by email instad of by username (but not wanting to drop the username, because it will also be used).
This was the first thing I made before running the first migration, everything worked correctly except in the Django admin, when I create a new user, I want these fields to be filled
username
email
password
And the admin only ask me for the username and password. How could I add the email too? Here's my codes
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifier for
authentication instead of username.
"""
def create_user(self, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError(_('The Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(email, password, **extra_fields)
class User(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User as CustomUser
class CustomUserAdmin(UserAdmin):
model = CustomUser
list_display = ('email', 'is_staff', 'is_active',)
list_filter = ('eamil', 'is_staff', 'is_active',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('email',)
admin.site.register(CustomUser, UserAdmin)
What I have to do? It seems that everything is correct, but the required email field is missing. Notice that this only happens when I use the Add User feature in the admin. When I create a superuser or when I login to the admin, everything is working as expected.
UPDATE:
Here's the content of my forms.py
from django.contrib.auth.forms import UserCreationForm
# the user model was customized it should be invoked
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms
from .models import User as CustomUser
class UserChangeForm(auth_forms.UserChangeForm):
class Meta(auth_forms.UserChangeForm.Meta):
model = CustomUser
class UserCreationForm(auth_forms.UserCreationForm):
class Meta(auth_forms.UserCreationForm.Meta):
model = CustomUser
fields = ("username", "email")
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
# the user model was customized it should be invoked
model = get_user_model()
fields = UserCreationForm.Meta.fields + ("email",)
And here the content (updated) of my admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User as CustomUser
from .forms import UserChangeForm, UserCreationForm
class CustomUserAdmin(UserAdmin):
model = CustomUser
list_display = ('email', 'username', 'is_staff', 'is_active',)
list_filter = ('eamil', 'username', 'is_staff', 'is_active',)
form = UserChangeForm
add_form = UserCreationForm
fieldsets = (
(None, {'fields': ('email', 'username', 'password')}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'username', 'password1', 'password2', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('email',)
admin.site.register(CustomUser, UserAdmin)
But I still have the same problem, I still can't add an email field in /admin/users/user/add/
The UserAdmin class has the attributes form and add_form which point to form classes to be used to edit and create the user respectively. You need to override these form classes and also set these attributes yourself as these two forms are created for the default user model.
Firstly define these custom forms:
from django.contrib.auth import forms as auth_forms
from .models import User as CustomUser
class UserChangeForm(auth_forms.UserChangeForm):
class Meta(auth_forms.UserChangeForm.Meta):
model = CustomUser
class UserCreationForm(auth_forms.UserCreationForm):
class Meta(auth_forms.UserCreationForm.Meta):
model = CustomUser
fields = ("username", "email")
Next set these in your CustomUserAdmin:
from .forms import UserChangeForm, UserCreationForm
class CustomUserAdmin(UserAdmin):
# Your other attributes here
form = UserChangeForm
add_form = UserCreationForm
In your code, I see
admin.site.register(CustomUser, UserAdmin)
but you have to register through your CustomUserAdmin.
Change your admin.py code to
admin.site.register(CustomUser, CustomUserAdmin)
My forms.py file
class CreateUserForm(UserCreationForm):
phone=PhoneNumberField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2', 'phone']
widgets={
'username':forms.TextInput(attrs={'placeholder':"Username"}),
'email':forms.TextInput(attrs={'placeholder':"Email Address"}),
'password1': forms.PasswordInput(attrs={'placeholder': 'Your Password'}),
'password2': forms.PasswordInput(attrs={'placeholder': 'Confirm Password'}),
'phone':PhoneNumberField(),
}
My models.py file
class CustomerReg(models.Model):
user=models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name=models.CharField(max_length=200, null=True)
email=models.EmailField(max_length=254)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile=CustomerReg.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
My views.py file
def registerPage(request):
if request.user.is_authenticated:
return redirect('form')
else:
form=CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if(form.is_valid()):
form.save()
user=form.cleaned_data.get['username']
user=User.objects.get(username=user)
phone=form.cleaned_data.get['phone']
user.phone_number=phone
user.save()
return redirect('login')
context = {'form': form}
return render(request, 'customer/register.html', context)
Upon clicking the register page an error is displayed
AttributeError at /register/
'str' object has no attribute 'User'
So is there no way I can save the data from my form and hence I would have to make new Custom User Model to save phone number of a user on register page?
My admin.py
from django.contrib import admin
from .models import *
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .forms import UserChangeForm,UserCreationForm
# Register your models here.
admin.site.register(Customer)
class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('email', 'phone')
admin.site.register(User, UserAdmin)
If your model is created correctly, the mistake you are making is your variable user is not a User object. The error informs you that user variable represents a string (from the form's input), which does not have User as its attribute. In this case, you might have to do something like
user = User.objects.get(username=user)
in order to assign the User object to variable user.
Now that user is a User object, then, you can do
user.phone_number = phone
user.save()
Please try this:
def registerPage(request):
if request.user.is_authenticated:
return redirect('form')
else:
form=CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
username=form.cleaned_data['username']
user=User.objects.get(username=username)
phone=form.cleaned_data['phone']
user.phone=phone
user.save()
return redirect('login')
context = {'form': form}
return render(request, 'customer/register.html', context)
Are you display phone field for admin then,
admin.py
from .forms import UserChangeForm,UserCreationForm
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('email', 'phone') # You can add field to display field here..
list_filter = ('name')
fieldsets = (
(None, {'fields': ('email')}),
('Personal info', {'fields': ('name','phone')}),
('Permissions', {'fields': ('name',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('name' ,'user','email','email', 'phone')
}),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(User, UserAdmin)
I created a custom user model with country in it:
models.py
class CustomUser(AbstractUser):
country = models.CharField(max_length=50, default="None")
Then added custom forms with form field country which is a ChoiceField and shows all the countries:
forms.py
class CustomUserCreationForm(UserCreationForm):
country = forms.ChoiceField(choices=sorted(COUNTRIES.items()), label="Country")
class Meta(UserCreationForm):
model = CustomUser
fields = '__all__'
class CustomUserChangeForm(UserChangeForm):
country = forms.ChoiceField(choices=sorted(COUNTRIES.items()), label="Country")
class Meta(UserChangeForm):
model = CustomUser
fields = '__all__'
Then I registered it in the admin with:
admin.py
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username', 'is_staff',]
admin.site.register(CustomUser, CustomUserAdmin)
It registered and everything is working fine, I am able to save the model with Django shell and programmatically, but I am not able to display it in the admin console. When I try to try to create a new user from the admin, I just see three fields - username, password and password confirmation.
Do I have to extend the admin template for this new field to show up?
To do this you will have to add_fieldsets under CustomUserAdmin in admin.py:
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username', 'is_staff',]
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2', 'country'),
}),
)
admin.site.register(CustomUser, CustomUserAdmin)
In Django 4.1+, the add_form option on a ModelAdmin has been removed. You should instead use the get_form() argument, like follows:
···python
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
def get_form(self, request, obj=None, change=False, **kwargs):
if not change and not obj:
self.form = self.add_form
return super().get_form(request, obj, **kwargs)
···
I've successfully created my own extension for the User model based on this tutorial:
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#custom-users-and-permissions
I also need to add a ForeignKey to a Company model, so that each user is assigned to a company. But this isn't showing in the admin at all, neither in the initial admin view or the edit view.
I've added the ForeignKey reference in the MyUser class like so:
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
company = models.ForeignKey('Company', on_delete=models.CASCADE, default=1)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
...
admin.py
from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from myapp.models import Company, Camera, MyUser
class UserCreationForm(forms.ModelForm):
"""A form for creating new users. Includes all the required
fields, plus a repeated password."""
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
class Meta:
model = MyUser
fields = ('email', 'date_of_birth', 'company')
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.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["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
"""
password = ReadOnlyPasswordHashField()
class Meta:
model = MyUser
fields = ('email', 'password', 'date_of_birth', 'company', 'is_active', 'is_admin')
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
form = UserChangeForm
add_form = UserCreationForm
# The fields to be used in displaying the User model.
# These override the definitions on the base UserAdmin
# that reference specific fields on auth.User.
list_display = ('email', 'date_of_birth', 'company', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('date_of_birth',)}),
('Company info', {'fields': ('company',)}),
('Permissions', {'fields': ('is_admin',)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'date_of_birth', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
admin.site.register(MyUser, UserAdmin)
admin.site.register(Company)
admin.site.register(Camera)
admin.site.unregister(Group)
If you add a foreign key to a custom user model, you need just to specify it on the fieldsets attribute.
For example with this custom user in models.py:
class CustomUser(AbstractUser):
company = models.ForeignKey('Company', on_delete=models.CASCADE)
You need this in the admin.py:
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm
from myapp.models import CustomUser
class MyUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = CustomUser
class MyUserAdmin(UserAdmin):
form = MyUserChangeForm
fieldsets = UserAdmin.fieldsets + (
(None, {'fields': ('company')}),
)
admin.site.register(CustomUser, MyUserAdmin)
Now you can select the user's company in the admin.
After looking for the best way to extend user, I followed the way described here (https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model). Now I am looking for a way to let the user edit some of their fields from User (eg. first_name, last_name and email) and from the new class extended. It would be nice if this could be done on the same screen, but I am not sure if this is possible (I don't want to let the permissions editable for non superuser).
So, I have first tried this code in admin, but it not works:
#admin.py
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class MyUserAdmin(UserAdmin):
def get_fieldsets(self, request, obj=None):
if request.user.is_superuser:
fieldsets = super(MyUserAdmin, self).get_fieldsets(request, obj)
else:
fieldsets = (
(None, {
'fields': ('username', 'first_name', 'last_name', 'email', 'password', 'last_login', 'date_joined',)
}),)
return fieldsets
# If not superuser, do not show some fields
def get_readonly_fields(self, request, obj=None):
ro_fields = super(MyUserAdmin, self).get_readonly_fields(request, obj)
if not request.user.is_superuser:
ro_fields = list(ro_fields) + ['username', 'last_login', 'date_joined',]
return ro_fields
admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
Here is a piece of my model:
class Investigator(models.Model):
user = models.OneToOneField(User, verbose_name=_('User'))
force_password_change = models.BooleanField(_('Force password change'), default=True)
...
I got no error, but the changes are not saved. What I have to do to let the users edit some specific fields?
You need set up permission for the user to edit User model