Django方式:ForeignKey还是ManyToMany?

时间:2015-11-09 17:03:22

标签: django database django-models

我的搭档并不同意我关于django的常见案例。

我的观点(4个显式表,1个JOIN来获取角色):

class Guest(models.Model):
  creation_date = models.DateTimeField(auto_now_add=True)
  email         = models.EmailField(max_length=255)

class GuestRole(models.Model):
  TYPE_CHOICES = (
    (1, 'Administrator'),
    (2, 'Assistant'),
    (3, 'Technician'),
  )
  guest = models.ForeignKey('Guest', null=True, related_name='roles')
  type  = models.PositiveSmallIntegerField(null=True, choices=TYPE_CHOICES)


class User(models.Model):
  creation_date = models.DateTimeField(auto_now_add=True)
  email         = models.EmailField(max_length=255, unique=True)

class UserRole(models.Model):
  TYPE_CHOICES = (
    (1, 'Administrator'),
    (2, 'Assistant'),
    (3, 'Technician'),
  )

  user = models.ForeignKey('User', null=True, related_name='roles')
  type = models.PositiveSmallIntegerField(null=True, choices=TYPE_CHOICES)

他的观点(3个显式表+ 2个隐藏表,2个JOIN来获取角色):

class Guest(models.Model):
  creation_date = models.DateTimeField(auto_now_add=True)
  email         = models.EmailField(max_length=255)
  role          = models.ManyToMany('Role')

class User(models.Model):
  creation_date = models.DateTimeField(auto_now_add=True)
  email         = models.EmailField(max_length=255, unique=True)
  role          = models.ManyToMany('Role')

class Role(models.Model):
  label = models.CharField(max_length=20)

(如果用户接受邀请,则由用户邀请并成为用户)

无论如何,Django的方式是什么?

1 个答案:

答案 0 :(得分:0)

我有一个更好的主意:

class RoleInfo(models.Model):
  TYPE_CHOICES = (
    (1, 'Administrator'),
    (2, 'Assistant'),
    (3, 'Technician'),
  )
  type  = models.PositiveSmallIntegerField(null=True, choices=TYPE_CHOICES)
  creation_date = models.DateTimeField(auto_now_add=True)

  class Meta:
    abstract = True

class Guest(RoleInfo):
  email = models.EmailField(max_length=255)

class User(RoleInfo):
  email = models.EmailField(max_length=255, unique=True)

基本上,您的第一个示例是正常的,但您使用相同的代码两次。你的第二个例子就像我写的那样,但是因为你将在你的数据库中创建一个Role表并创建Role类的实例,这有点糟糕,这是你真正想要的吗?

如果要在许多模型中使用相同的代码,可以使用抽象类或代理类。由于您需要向GuestUser添加新字段,因此创建抽象模型是最佳选择。

More about abstract models.