Subclassing AbstractUser in Django for two types of users

▼魔方 西西 提交于 2019-12-06 16:54:14

问题


I'm developing a school database system in Django 1.5, and was planning on having a number of different user types (Student, Staff, Parent) which subclass AbstractUser (actually, another abstract subclass of AbstractUser). I was just attempting to add an externally developed app to my system, which uses User in a ForeignKey for some of its models, however, this fails as my user type is not a 'User' instance. I can't set the apps models to use AbstractUser as one can't use abstract classes for Foreign Keys. I was then considering adding to my settings.py AUTH_USER_MODEL = 'myapp.MyUser' and using settings.AUTH_USER_MODEL in place of User for the ForeignKey in the app. However, I have 3 different user types, so can't do this either.

An earlier prototype used Django 1.4, which did not support custom User models, hence had a reference to a User instead, but this required an extra join for every query, which was leading to quite complex queries. Is this the only way I can go forward with this, or is there another solution?


回答1:


I have successfully used the following solution:
1. Create SchoolUser class in models.py - this will be your AUTH_USER_MODEL class

TYPES = (('Student', 'Student'), ('Staff', 'Staff'), ('Parent', 'Parent'), )
class SchoolUser(AbstractUser):
    type = models.CharField(max_length=10, choices=TYPES, default='Student')

2. Create users.py file and put whole users logic there. Have one abstract class that all others inherit from and which will implement the factory method:

class UserManager(object):
    def __init__(self, user):
        self.user = user

    @classmethod
    def factory(cls, user):
        """
        Dynamically creates user object
        """
        if cls.__name__.startswith(user.type):  # Children class naming convention is important
            return cls(user)
        for sub_cls in cls.__subclasses__():
            result = sub_cls.factory(user)
            if result is not None:
                return result

Sample children classes (also go to users.py file):

class StudentUser(UserManager):
    def do_something(self):
        pass
class StaffUser(UserManager):
    def do_something(self):
        pass
class ParentUser(UserManager):
    def do_something(self):
        pass

Views is where the magic happens ;)

def my_view(request):
    school_user = UserManager.factory(request.user)
    if school_user.do_something:  # each class can have different behaviour

This way you don't need to know, which type of user it is, just implement your logic.
I hope this is clear enough, if not let me know!



来源:https://stackoverflow.com/questions/16682042/subclassing-abstractuser-in-django-for-two-types-of-users

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!