article

Saturday, May 30, 2020

Django How to Add User Profile To Admin


Django How to Add User Profile To Admin

You want to store a few more data related to User. This is how to extend the the default Django User model User Profile admin

Database Table
CREATE TABLE myapp_profile (
id INTEGER PRIMARY KEY,
user_id INTEGER,
location STRING (200),
birthdate DATE,
role INTEGER

);


models.py
 
#models.py
from django.db import models

from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    STUDENT = 1
    TEACHER = 2
    SUPERVISOR = 3
    ROLE_CHOICES = (
        (STUDENT, 'Student'),
        (TEACHER, 'Teacher'),
        (SUPERVISOR, 'Supervisor'),
    )
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    location = models.CharField(max_length=30, blank=True)
    birthdate = models.DateField(null=True, blank=True)
    role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True)

    def __str__(self):  # __unicode__ for Python 2
        return self.user.username
  
    class Meta:  
        db_table = "myapp_profile"

@receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()
admins.py
 
#admin.py
from django.contrib import admin

from myapp.models import Profile
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

class ProfileInline(admin.StackedInline): #StackedInline normally is used for formsets
    model = Profile
    can_delete = False
    verbose_name_plural = 'Profile'
    fk_name = 'user'
 
class CustomUserAdmin(UserAdmin):
    inlines = (ProfileInline, )
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'get_location') #Add Profile Fields to List View
    list_select_related = ('profile', )

    def get_location(self, instance):
        return instance.profile.location
    get_location.short_description = 'Location'
 
    def get_inline_instances(self, request, obj=None): #get_inline_instances display the inlines only in the edit form
        if not obj:
            return list()
        return super(CustomUserAdmin, self).get_inline_instances(request, obj)


admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)

Related Post