Django unique_together跨模型

时间:2015-10-14 14:08:42

标签: django django-models django-registration django-users

所以,我有这两个模型:

class User(AbstractBaseUser):
"""
Custom user class
"""
    email = models.EmailField(verbose_name = 'email address', unique = True, db_index = True)
    joined = models.DateTimeField(auto_now_add = True)
    is_active = models.BooleanField(default = True)
    is_admin = models.BooleanField(default = False)
    user_type = models.CharField(max_length = 30)
    group = models.ManyToManyField(Group, related_name = 'users')
    permission = models.ManyToManyField(Permission, related_name = 'users')

    USERNAME_FIELD = 'email'  # Mapping between our model's email field to Django's User model's username

class Subscription(models.Model):

    project_name = models.CharField(max_length = 40) # A subscription can only be for one project (one to one), e.g. you cannot buy a subscription for two projects.  You have to buy two different subscriptions
    user = models.ManyToManyField(User, related_name = 'subscriptions', blank = True) # One user can have many different subscriptions (e.g. for different projects), and one subscription is good for many users
    date = models.DateTimeField(auto_now_add = True) # Keeping track of when a subscription is entered
    mop = models.CharField(max_length = 20, choices = PAYMENT_CHOICES)
    payment_term = models.CharField(max_length = 30, choices = PAYMENT_TERMS)
    package = models.CharField(max_length = 50, choices = PACKAGES)

因此,用户和订阅之间存在多对多关系,例如一个用户可以拥有多个订阅,一个订阅对许多用户都有好处。

当用户注册时,应允许用户使用相同的电子邮件地址注册不同的项目。但是,它不会这样做,因为设置了unique = True。我尝试删除unique = True,但显然它抱怨Django需要USERNAME ='email'的唯一字段。

我理想地想要的是电子邮件(用户模型)和项目(订阅模型)的唯一= True,例如虽然用户不能多次注册项目,但用户可以拥有多个项目。我怎么做?似乎project_name字段属于订阅模型而不属于用户模型,因为如果它在用户模型中,由于多对多关系,这意味着订阅可能有许多不正确的项目(即订阅总是针对一个项目。)

一方面,我希望登录页面允许用户只使用他们的电子邮件地址登录(因此我需要在电子邮件上使用unique = True进行登录)。另一方面,我希望注册允许相同的电子邮件注册到不同的项目,而不是抱怨这个电子邮件已经存在(因此,我不需要在电子邮件上使用unique = True进行注册)。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

嗯,我解决它的方法是捕获异常。当它在调用is_valid()之后抛出异常说用户已经存在时,我确保我只是注册该项目。