在Django中为两种类型的用户子类化AbstractUser

时间:2013-05-22 01:23:21

标签: django django-models django-users django-1.5 django-inheritance

我正在开发Django 1.5中的学校数据库系统,并计划拥有许多不同的用户类型(学生,员工,父),它们是AbstractUser的子类(实际上是AbstractUser的另一个抽象子类)。我只是试图在我的系统中添加一个外部开发的应用程序,它在一些ForeignKey中使用User用于某些模型,但是,由于我的用户类型不是“用户”实例,因此失败了。我不能将应用程序模型设置为使用AbstractUser,因为不能使用外键的抽象类。我当时正在考虑添加到我的settings.py AUTH_USER_MODEL = 'myapp.MyUser'并使用settings.AUTH_USER_MODEL代替应用中的ForeignKey的User。但是,我有3种不同的用户类型,所以也不能这样做。

早期的原型使用Django 1.4,它不支持自定义用户模型,因此引用了用户,但这需要为每个查询提供额外的连接,这导致了非常复杂的查询。这是我可以继续推进的唯一方法,还是有另一种解决方案?

1 个答案:

答案 0 :(得分:3)

我已成功使用以下解决方案:
1.在models.py中创建SchoolUser类 - 这将是您的AUTH_USER_MODEL

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

2。创建users.py文件并将整个用户逻辑放在那里。有一个所有其他人继承的抽象类,它将实现工厂方法:

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

示例子类(也转到users.py文件):

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

观点是神奇发生的地方;)

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

这样您就不需要知道它是哪种类型的用户,只需实现您的逻辑 如果不让我知道,我希望这很清楚!