I'm using the django-import-export library with success to provide a data download option via the django admin for some of my defined models.
I'm having difficulty however providing the same export option via the User Admin.
For my other models I've done something like the following to my admin.py:
class OtherResource(resources.ModelResource):
class Meta:
model = Other
class OtherAdmin(ExportMixin, admin.ModelAdmin):
# Other admin definition here
My problem is providing the same Export functionality to pre-packaged Django models like User.
I tried the following...
class UserResource(resources.ModelResource):
class Meta:
model = User
class UserAdmin(ExportMixin, UserAdmin):
pass
But this has a couple problems,
It drops a bunch of the User model fields from the list display (like is_active and groups)
I can see that something is not fully connected because adding exclude's to the UserResource is not excluding those fields from the export
I could re-create the UserAdmin on my end, but I'm hoping (and guessing) that's unnecessary.
Any ideas?
So I was making a couple of mistakes.
I was being an idiot (I was importing the django UserAdmin rather than the UserAdmin I had created as an override a couple years ago in a dependency to this project -- this explains why fields were dropped when overriding the UserAdmin)
I was failing to manually link the OtherResource to the OtherAdmin as explained in the django-import-export docs
The solution to both of the above code samples is as follows:
For the Other model
class OtherResource(resources.ModelResource):
class Meta:
model = Other
class OtherAdmin(ExportMixin, admin.ModelAdmin):
resource_class = OtherResource
# Other admin definition here
and for the User model
class UserResource(resources.ModelResource):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class UserAdmin(ExportMixin, UserAdmin):
resource_class = UserResource
pass
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Viola.
Everything works as intended.
Other model is exported in full.
User model is exported as 3 columns (first name, last name, and email).
Imports required
from import_export import resources
from import_export.admin import ExportMixin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
if you want to import export in user models in Django then override this code in your application admin.py
from import_export import resources
from import_export.admin import ExportMixin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from import_export.admin import ImportExportModelAdmin
# Register your models here.
class UserResource(resources.ModelResource):
class Meta:
model = User
fields = ('id','username','first_name', 'last_name', 'email')
# class UserAdmin(ExportMixin, UserAdmin):
# resource_class = UserResource
# pass
class UserAdmin(ImportExportModelAdmin):
list_display = ('id','username','first_name', 'last_name', 'email')
# list_filter = ('created_at',)
resource_class = UserResource
pass
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Related
I have a custom user model which is subclassed by AbstractUser with an added custom field.
# model.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
ADM = 'admin'
MEMBER = 'member'
ROLE_CH = ((ADM, 'Administrator'), (MEMBER, 'Member'))
role = models.CharField(max_length=20, choices=ROLE_CH, blank=True)
This model is also registered as the default auth model in settings.py
# settings.py
AUTH_USER_MODEL = "main.CustomUser"
Then in admin.py as per the documentation, I create a custom form which extends UserCreationForm and then register it to the custom user.
# admin.py
from django.contrib import admin
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = UserCreationForm.Meta.fields + ('role',)
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
admin.site.register(CustomUser, CustomUserAdmin)
However, it does not work as expected. The Add User form remains the default one i.e. only username, password and password confirmation fields are present. The role field does not appear.
Use form attribute instead of add_form:
class CustomUserAdmin(ModelAdmin):
form = CustomUserCreationForm
admin.site.register(CustomUser, CustomUserAdmin)
UPD
First answer is correct only for ModelAdmin base class, since it doesn't have add_form attribute.
For UserAdmin you should update add_fieldsets attribute:
class CustomUserAdmin(UserAdmin):
add_fieldsets = UserAdmin.add_fieldsets + (
(None, {
'fields': ('role',),
}),
)
admin.site.register(CustomUser, CustomUserAdmin)
In this case you dont even required add_form.
What I aim to achieve in the end is to combine the list of all users (from auth.models) with a DateTimeField from another model (model.Model). What's the best way of doing this?
My code:
survey/models/response.py
from django.contrib.auth.models import User
from django.db import models
class Response(models.Model):
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, null=True, blank=True)
In admin.py, I can create a custom user class which lists all of the registered users' usernames like so:
survey/admin.py
from django.contrib.auth.models import User
admin.site.unregister(User)
class UserAdmin(admin.ModelAdmin):
list_display = ('username',)
admin.site.register(User, UserAdmin)
Essentially I want extend UserAdmin as list_display = ('username', 'created') - with username coming from auth.models and created coming from models.Model.
At the moment I can create a class in admin.py that shows me a list of all the users who have submitted a Response. The issue is that if you have 200 users, it is more useful to see who hasn't submitted from a list of all users than only listing the users who have submitted a Response.
You can write a function to fetch relevant data for you to show in the admin listing page.
In your admin.py
from django.contrib.auth.models import User
admin.site.unregister(User)
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'latest_response')
def latest_response(self, obj):
return obj.response_set.latest('created') # Or any other logic you want to apply here to return a string or boolean that can be shown on the admin
admin.site.register(User, UserAdmin)
I am trying to enable django import export on the django user model.
I have tried defining a model admin class, unregistering the user model and then registering the new user admin class. But it doesn't work.
my admin.py looks like this -
from django.contrib.auth.admin import UserAdmin as BaseAdmin
from import_export.admin import ImportExportModelAdmin
from import_export import resources
class UserResource(resources.ModelResource):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class UserAdmin(BaseAdmin, ImportExportModelAdmin):
resource_class = UserResource
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
I want to know how can I achieve this? Is there some other way I can apply django import export on the user model?
Your code is working. You just need to import the User model:
from django.contrib.auth.models import User
Django 1.10.2
Studying customization of the User model.
Trying to follow the documentaion https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#extending-the-existing-user-model
I wish to store that department and show it in the admin.
The problem is that department doesn't appear.
I played with fieldsets and list_display, but failed.
Could you help me understand how to show the department in the admin?
admin.py
from django.contrib.auth.models import User
from django.db import models
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.CharField(max_length=100)
# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class EmployeeInline(admin.StackedInline):
model = Employee
can_delete = False
verbose_name_plural = 'employee'
# Define a new User admin
class UserAdmin(BaseUserAdmin):
inlines = (EmployeeInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
My site makes use of Django's User Authentication User model and a custom UserProfile model to store some additional data (birthday, etc.). Is there a way to create a view in Django admin that weaves together fields from both the User and UserProfile models?
I suspect that this code snippet is not even close, but maybe it will help illustrate what I'm trying to do:
from django.contrib import admin
from django.contrib.auth.models import User
from userprofile.models import UserProfile
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('name', 'gender', 'User.email') #user.email creates the error - tried some variations here, but no luck.
admin.site.register(UserProfile, UserProfileAdmin)
Error message:
ImproperlyConfigured: UserProfileAdmin.list_display[2], 'User.email' is not a callable or an attribute of 'UserProfileAdmin' or found in the model 'UserProfile'.
Ultimately, I'm trying to create an admin view that has first & last name from UserProfile and email from User.
for displaying user email you need to have a method on UserProfile or UserProfileAdmin that returns the email
on UserProfile
def user_email(self):
return self.user.email
or on UserProfileAdmin
def user_email(self, instance):
return instance.user.email
then change your list_display to
list_display = ('name', 'gender', 'user_email')
Related docs: ModelAdmin.list_display
You could try using InlineModelAdmin to display both User and UserPofile forms in a admin view.
To display user profile information in change list you can create a new method that delegates the values from UserProfile to User model.
For example this should work more or less :)
from django.contrib import admin
from django.contrib.auth.models import User
from my_models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
fk_name = 'user'
class UserAdmin(admin.ModelAdmin):
list_display = ['get_userprofile_name', 'email']
list_select_related = True
inlines = [
UserProfileInline,
]
def get_userprofile_name(self, instance):
# instance is User instance
return instance.get_profile().name
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Using Ashoks top answer i made snippet that simplifies this process for large number of fields
class ColumnViewer(object):
pass
column_list = ('name', 'surname', )
for col in column_list:
setattr(ColumnViewer, col, lambda s,i : getattr(i, col))
#admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin, ColumnViewer):
list_display = column_list