Tony
Tony

Reputation: 821

Using two database tables for one control in Django Admin

I am creating a small application to help our Training Department manage their cirriculum using Django. When we talk about students we have two type; Employee and Customer.

Since all of the employees will be in auth_user I would rather not have to populate another table with that data. The behavior that I want is when a Class is displayed in the Django Admin I would like one control to be filled with data from two tables for the student list. Is this even possible in Django. My suspicion is that it is not. This is what I am messing around with:

from django.db import models
from django.contrib.auth.models import User

class Student(models.Model):
    cell_phone = models.CharField(max_length=14)

    class Meta:
        abstract = True

class EmployeeStudent(models.Model, Student):
    user = models.OneToOneField(User)
    extension = models.CharField(max_length=4, null=True, blank=True, default=None)

class CustomerStudent(models.Model, Student):
    first_name = models.CharField(max_length=25)
    last_name = models.CharField(max_length=25)
    email = models.CharField(max_length=25)

However, just thinking about it does it make more sense to do:

from django.db import models
from django.contrib.auth.models import User

class Student(models.Model):
    user = models.ForeignKey(User, null=True, blank=True, default=None)
    first_name = models.CharField(max_length=25, null=True, blank=True, default=None)
    last_name = models.CharField(max_length=25, null=True, blank=True, default=None)
    email = models.CharField(max_length=25, null=True, blank=True, default=None)
    extension = models.CharField(max_length=4, null=True, blank=True, default=None)

I cringe at the thought of a blank record.

Any recommendations? Does it make sense to add everything to auth_user and leave the staff flag to false then just use a one to one field to map an auth_user to a Student? I do not really want to do that if I don't have to because I am not going to give anyone else access to the auth_user table so all additions to this table would need to be done by me.

Upvotes: 1

Views: 477

Answers (2)

arocks
arocks

Reputation: 2882

This is a fairly common use-case (i.e. different types of userprofiles) in Django. In your case, I think the approach below would suit your scenario:

from django.db import models
from django.contrib.auth.models import User

class Student(models.Model):
    STUDENT_TYPES = (
        ('E', 'EmployeeStudent'),
        ('C', 'CustomerStudent'),
    )
    user = models.OneToOneField(User, null=True, blank=True, default=None)
    user_type = models.CharField(max_length=1, choices=STUDENT_TYPES)

class EmployeeDetails(models.Model):
    student = models.OneToOneField(Student)
    extension = models.CharField(max_length=4, null=True, blank=True, default=None)


class StudentDetails(models.Model):
    student = models.OneToOneField(Student)
    # BTW: all the fields below are redundant since they are already in User
    first_name = models.CharField(max_length=25, null=True, blank=True, default=None)
    last_name = models.CharField(max_length=25, null=True, blank=True, default=None)
    email = models.CharField(max_length=25, null=True, blank=True, default=None)

This way, you can check the student.user_type and infer if you need to get EmployeeDetails or StudentDetails

NOTE:: Even though this is a recommended approach, it is not quite easy to enter data using the default admin interface in this manner. You might want to see how profile inlines are done to show the user profile fields in the admin as well.

Upvotes: 1

Ambroise
Ambroise

Reputation: 1659

You could try to use model inheritance (i.e User model inheritance : https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-user) for your Student model, or mixing Student(models.Model) with User in your EmployeeStudent and CustomerStudent models :

class Student(models.Model):
    cell_phone = models.CharField(max_length=14)

    class Meta:
        abstract = True

class EmployeeStudent(User, Student):
    user = models.OneToOneField(User)
    extension = models.CharField(max_length=4, null=True, blank=True, default=None)

class CustomerStudent(User, Student):
    first_name = models.CharField(max_length=25)
    last_name = models.CharField(max_length=25)
    email = models.CharField(max_length=25)

or :

class Student(User):
    cell_phone = models.CharField(max_length=14)

    class Meta:
        abstract = True

class EmployeeStudent(models.Model):
    user = models.OneToOneField(Student)
    extension = models.CharField(max_length=4, null=True, blank=True, default=None)

class CustomerStudent(models.Model):
    first_name = models.CharField(max_length=25)
    last_name = models.CharField(max_length=25)
    email = models.CharField(max_length=25)

If I understand correctly, you'd then want to display Customers as well as Employees in the same changelist in admin ? Using Student(User) with Employee / Customer as inlines might solve your problem.

Hope this helps,

Regards

Upvotes: 2

Related Questions