Display custom form in Django admin - django

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)
···

Related

Custom Fields in Django not displayed in admin panel

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

Django AbstractUser doesn't show model

I'm a django beginner and i want to add a booleanfield to AbstractUser, but it's not showing the booleanfield in the admin.
models.py
class CustomUser(AbstractUser):
selected = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['selected',]
def __str__(self):
return self.username
admin.py
class MyUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = CustomUser
class UserAdmin(BaseUserAdmin):
form = MyUserChangeForm
list_display = ('username', 'first_name', 'last_name', 'email', 'is_staff', 'selected')
admin.site.register(CustomUser, UserAdmin)
settings.py
AUTH_USER_MODEL = 'football_app.CustomUser'
in admin.py file change
class UserAdmin(BaseUserAdmin): to class UserAdmin(CustomUser):
EDIT: update your class like this
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'first_name', 'last_name', 'email', 'is_staff', 'selected')
class Meta:
model = CustomUser
You need to unregister current User admin first.
admin.site.unregister(User)
admin.site.register(CustomUser, UserAdmin)

Django Custom User Model ForeignKey Addition Not Showing in Admin

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.

Django UpdateView disable some fields

I have made a class view inheriting UpdateView. I have specified the fields and models from which the forms should be built. Now say if i have a field email, then I want to disable it in the form. I have no clues as to how it can be done.
class UserUpdate(UpdateView):
model = Users
fields = ['email', 'first_name', 'last_name', 'birth_date']
template_name = 'users_update_form.html'
success_url = '/index/'
To hide it:
class UserUpdate(UpdateView):
model = Users
fields = ['first_name', 'last_name', 'birth_date']
template_name = 'users_update_form.html'
In this case there is no need to create a separate Form class - as this is handled by the UpdateView.
To make the fiel readonly:
class UserForm(forms.ModelForm):
class Meta:
model = Users
fields = ['email', 'first_name', 'last_name', 'birth_date']
email = forms.CharField(widget=forms.TextInput(attrs={'readonly':'readonly'}))
def clean_email(self):
return self.initial['email']
class UserUpdate(UpdateView):
model = Users
form_class = UserForm
Note for Django 1.9
Django 1.9 has a disabled option built in. Using this allows you to skip the additional clean method.
class UserForm(forms.ModelForm):
class Meta:
model = Users
fields = ['email', 'first_name', 'last_name', 'birth_date']
email = forms.CharField(disabled=True)
Define a UserForm with exclude fields which you don't want to show in the form
class UserForm(forms.ModelForm):
class Meta:
model = Users
exclude = ('email',) # add fields to disable it in the form
If you want to make field readonly in > django 1.9
use disabled
class UserForm(forms.ModelForm):
email = forms.CharField(disabled=True)
class Meta:
model = Users
fields = ['email', 'first_name', 'last_name', 'birth_date']
Then specify form in view.
class UserUpdate(UpdateView):
model = Users
form_class = UserForm
....

How to edit only some fields in django admin from an extend user model?

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