How to inherit fields from User in Django admin using custom user? - python

I want to add my settings.AUTH_USER_MODEL to my admin insted of User model.
I register it with the snippet I found in the docs:
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', 'bdate')
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('bdate', 'website', 'location')}),
)
# 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')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
In fieldsets Personal info I added all my custom info. Now I also want to display all inherited fields like first_name, username, etc. I can add them one by one to fieldsets, but I am not sure if that's the right way.
Is there a way just to inherit them from User model without specifying explicitly?

You could make use of ModelAdmin.get_fieldsets():
class UserAdmin(BaseUserAdmin):
def get_fieldsets(self, request, obj=None):
fieldsets = list(super(UserAdmin, self).get_fieldsets(request, obj))
# update the `fieldsets` with your specific fields
fieldsets.append(
('Personal info', {'fields': ('bdate', 'website', 'location')}))
return fieldsets

Related

Displaying the correct django authentication framework information in custom admin page

I am trying to display the password in the Admin backend table in the following way, containing the algorithm, iterations, salt and hash:
However, my current page looks like the following:
As you can see it is just the hashed password, not displaying any of the information unlike the above. Can anyone see where I am going wrong?
Please find my code below:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from hobbies.models import extendedUser, User, Hobby
from .forms import LoginForm, SignUpForm
from django.forms import ModelForm
from django.contrib.auth.forms import ReadOnlyPasswordHashField
#admin.site.register(User,UserAdmin)
class CustomUserAdmin(UserAdmin):
add_form = SignUpForm
form = LoginForm
model = extendedUser
readonly_fields = ["password"]
list_display = ('email', 'is_staff', 'is_active',)
list_filter = ('email', 'is_staff', 'is_active',)
fieldsets = (
(None, {'fields': ('email', 'password', 'city')}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password', 'is_staff', 'is_active')}
),
)
search_fields = ('email',)
ordering = ('email',)
admin.site.register(User, CustomUserAdmin)
Thank you for your time,
Alex
I think they use display using this function:
get_session_auth_hash() which is a part of the base abstract user in django.contrib.auth.base_user

How to use django-select2 widgets in django admin site?

In my django app I have modified the User entity to include a worker field (OneToOneField). But from the django admin site that field yiels so many result , so it is difficult for the logged user to select a worker. Is there any way to use the select2 (ModelSelect2Widget) widgets from the django admin site?
For any regular form I have define the widgets in the following way:
from django_select2.forms import ModelSelect2Widget
class ProcessForm(forms.ModelForm):
class Meta:
model = ProcessModel
exclude = ('id',)
widgets = {
'name':forms.TextInput(attrs={'class': 'form-control'}),
'code':forms.TextInput(attrs={'class': 'form-control'}),
'description':forms.Textarea(attrs={'class': 'form-control'}),
'geom': LeafletWidget(),
'product': ModelSelect2Widget(model=ProductModel, queryset=ProductModel.objects.filter(),
search_fields=['name__icontains'],
attrs={'style': 'width: 100%;'}),
}
Is there any way to use the ModelSelect2Widget for the worker field in the admin site form?
Here is my code:
class User(AbstractUser):
worker = models.OneToOneField(WorkerModel, on_delete=models.CASCADE,
related_name="user", verbose_name=_("Trabajador"), null=True, blank=True)
class Meta:
default_permissions = ()
verbose_name="Usuario"
verbose_name_plural="Usuarios"
permissions = (
("secretario", "Secretario(a)"),
("director", "Director"),
)
from django.contrib.auth.admin import UserAdmin
class UserAdminInherited(UserAdmin):
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Worker info'), {'fields': ('worker',)}),
(_('Permissions'), {
'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
admin.site.register(User, UserAdminInherited)
Since Django 2.0., we can use autocomplete_fields.
autocomplete_fields is a list of ForeignKey and/or ManyToManyField
fields you would like to change to Select2 autocomplete inputs.
ModelAdmin(is parent of UserAdmin) has the property autocomplete_fields (Django Docs):
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth import get_user_model
User = get_user_model()
class UserAdminInherited(UserAdmin):
autocomplete_fields = ['worker']
...
admin.site.register(User, UserAdminInherited)
You must define search_fields on the related object’s ModelAdmin
because the autocomplete search uses it.
from django.contrib import admin
#admin.register(WorkerModel)
class WorkerModelAdmin(admin.ModelAdmin):
search_fields = ['model_field']

Django UserAdmin's add_fieldsets?

I'm following a tutorial on making a custom User for authentication purposes. The tutorial used a certain property add_fieldsets within UserAdmin. What does this mean? I can't seem to find any documentation on this.
Here is the snippet:
class UserAdmin(UserAdmin):
"""Define admin model for custom User model with no email field."""
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name', 'last_name')}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
('Important dates', {'fields': ('last_login', 'date_joined')}),
('Contact info', {'fields': ('contact_no',)}),)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),}),)
list_display = ('email', 'first_name', 'last_name', 'is_staff')
search_fields = ('email', 'first_name', 'last_name')
ordering = ('email',)
Here is the tutorial I was following: How to use email as username for Django authentication (removing the username)
The add_fieldsets class variable is used to define the fields that will be displayed on the create user page.
Unfortunately it's not well documented, and the closest thing I found to documentation was a comment in the code example on https://docs.djangoproject.com/en/2.1/topics/auth/customizing/ (search page for add_fieldsets).
The classes key sets any custom CSS classes we want to apply to the form section.
The fields key sets the fields you wish to display in your form.
In your example, the create page will allow you to set an email, password1 and password2.
The add_fieldsets field works similar to fieldsets field and allows to control the layout of the admin pages but specifically the create object page whereas fieldsets field is used to control change object page.
And using add_fieldsets field you can decide which all fields should be displayed on the create object page, add description ,etc.
In your example it will create a section with no name (as set to None), set a specific width to all the fields by using classes key set and display fields email,password1 and password2
by using key set fields
I hope I cleared your doubt!!
use the BaseUserAdmin class, it enables some functionalities like add_form and add_fieldsets
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserAdmin(BaseUserAdmin):
"""Define admin model for custom User model with no email field."""
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Personal info', {'fields': ('first_name', 'last_name')}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
('Important dates', {'fields': ('last_login', 'date_joined')}),
('Contact info', {'fields': ('contact_no',)}),)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),}),)
list_display = ('email', 'first_name', 'last_name', 'is_staff')
search_fields = ('email', 'first_name', 'last_name')
ordering = ('email',)
From the Django documentation (see the Note):
If you are using a custom ModelAdmin which is a subclass of django.contrib.auth.admin.UserAdmin, then you need to add your custom fields to fieldsets (for fields to be used in editing users) and to add_fieldsets (for fields to be used when creating a user).
So it's basically the same as fieldsets, but for creating users and only needed when you're extending UserAdmin. The only difference between fieldsets and add_fieldsets is that you have to treat password fields a little different ("password1" and "password2", instead of "password").
The documentation offers a full example of implementing a custom user here: https://docs.djangoproject.com/en/4.1/topics/auth/customizing/#custom-users-admin-full-example

django sign up user in admin site with generated password

The problem:
I would like to use django admin site User model to register new users. The default option offers you to register new username with password and password confirmation, which are required fields.
My idea is to make few changes. I would like to keep username field and add email-field, however delete password and password confirmation. The principal idea is, I would register a user and he would receive an email with generated password. He would then be able to login with generated password and change the password.
I am facing huge problems with templates, errors and most of all overriding the classes.
I have spent many many hours checking django documentation, goolge and the best I could do so far is:
admin.py
from django.contrib import admin
from django.contrib.auth import admin as upstream
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import Group, User
from django.utils.translation import ugettext, ugettext_lazy as _
class UserAdmin(upstream.UserAdmin):
fieldsets = (
(None, {'fields': ('username', 'password','email')}),
(_('Personal info'), {'fields': ('first_name', 'last_name')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username','email')}
),
)
form = UserChangeForm
add_form = UserCreationForm
try:
admin.site.unregister(User)
except NotRegistered:
pass
admin.site.register(User, UserAdmin)
This is a code I have found on stackoverflow. Within add_fieldsets I removed password1, and password2. If I go to admin page, everything looks great, however I can not register a user.
I think it is because of UserCreationForm, which insists of creating an password, but perhaps I could be wrong. Can anyone please let me know how to override UsercreationForm, so passwords wouldn't be mandatory anymore and errors from UserCreationForm would not be seen on the site.
Customizing Django auth can be very difficult and that's why I would recommend looking into 3rd party apps to help you achieve your goals. One you might want to check out is: https://github.com/bee-keeper/django-invitations
even though it is an old question and no real answer, one way to do most of the stuff (without knowing how to act on the "send password") would be:
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.contrib.auth.forms import UserCreationForm as DjangoUserCreationForm
class UserCreationForm(DjangoUserCreationForm):
password1 = None
password2 = None
def clean(self):
password = get_random_string() # here you want to maybe send a signal which can be picked up or something
self.cleaned_data['password1'] = password
self.cleaned_data['password2'] = password
return super().clean()
class UserAdmin(DjangoUserAdmin):
add_form = UserCreationForm
fieldsets = (
(None, {'fields': ('username',)}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'email'),
}),
)
list_filter = tuple()
list_display = ('username', 'email', 'first_name', 'last_name')
admin.site.register(User, UserAdmin)

Django create custom UserCreationForm

I enabled the user auth module in Django, however when I use UserCreationForm it only asks for username and the two password/password confirmation fields. I also want email and fullname fields, all set as required fields.
I've done this:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
class RegisterForm(UserCreationForm):
email = forms.EmailField(label = "Email")
fullname = forms.CharField(label = "Full name")
class Meta:
model = User
fields = ("username", "fullname", "email", )
Now the form shows the new fields but it doesn't save them to the database.
How can I fix this?
There is no such field called fullname in the User model.
If you wish to store the name using the original model then you have to store it separately as a first name and last name.
Edit: If you want just one field in the form and still use the original User model use the following:
You can do something like this:
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
class RegisterForm(UserCreationForm):
email = forms.EmailField(label = "Email")
fullname = forms.CharField(label = "First name")
class Meta:
model = User
fields = ("username", "fullname", "email", )
Now you have to do what manji has said and override the save method, however since the User model does not have a fullname field it should look like this:
def save(self, commit=True):
user = super(RegisterForm, self).save(commit=False)
first_name, last_name = self.cleaned_data["fullname"].split()
user.first_name = first_name
user.last_name = last_name
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
Note: You should add a clean method for the fullname field that will ensure that the fullname entered contains only two parts, the first name and last name, and that it has otherwise valid characters.
Reference Source Code for the User Model:
http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/models.py#L201
You have to override UserCreationForm.save() method:
def save(self, commit=True):
user = super(RegisterForm, self).save(commit=False)
user.fullname = self.cleaned_data["fullname"]
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/forms.py#L10
In django 1.10 this is what I wrote in admin.py to add first_name, email and last_name to the default django user creation form
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib import admin
from django.contrib.auth.models import Group, User
# first unregister the existing useradmin...
admin.site.unregister(User)
class UserAdmin(BaseUserAdmin):
# The forms to add and change user instances
# 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 = ('username', 'email', 'first_name', 'last_name', 'is_staff')
fieldsets = (
(None, {'fields': ('username', 'password')}),
('Personal info', {'fields': ('first_name', 'last_name', 'email',)}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
('Important dates', {'fields': ('last_login', 'date_joined')}),)
# 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': ('username', 'email', 'first_name', 'last_name', 'password1', 'password2')}),)
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('username', 'first_name', 'last_name', 'email')
ordering = ('username',)
filter_horizontal = ('groups', 'user_permissions',)
# Now register the new UserAdmin...
admin.site.register(User, UserAdmin)

Categories

Resources