django中的唯一约束

时间:2019-02-26 21:12:30

标签: django database one-to-many

我在Django中有一个包含人员和角色的数据库。人与角色具有一对多的关系。问题在于角色没有唯一的约束,例如,人物adam和david可以担任角色的艺术家,但是django创建两个相同的艺术家条目,但我想要同一个条目,即adam和david应该指向一个条目。如果我向我的角色字段添加唯一性,则django表示应该一对一。有什么想法吗?

model.py的一部分:

Failures:

  1) Api::AirportsController show returns a JSON:API-compliant, serialized object representing the specified Airport
     Failure/Error: get :show

     ActionController::UrlGenerationError:
       No route matches {:action=>"show", :controller=>"api/airports"}
     # ./spec/api/airport_api_spec.rb:20:in `block (3 levels) in <main>'

修改admin.py以获得以下答案:

from django.db import models
from phonenumber_field.modelfields import PhoneNumberField

# Create your models here.
# possibillitas models here

class Person(models.Model):

    mail=models.EmailField(default='yourname@gmail.com')
    firstName=models.CharField(max_length=200,default='firstname')
    lastName=models.CharField(max_length=200,default='lastname')
    phoneNumber=PhoneNumberField()
    streetAdress=models.CharField(max_length=200,default='streetAdress')
    zipcode=models.CharField(max_length=200)
    city=models.CharField(max_length=200,default='Göteborg')
    country=models.CharField(max_length=200,default='Sweden')

    def __str__(self):
        return "%s %s" % (self.firstName,self.lastName)

    class Meta:
        ordering = ('firstName','lastName')

class Role(models.Model):

    role=models.CharField(max_length=200)
#    person=models.ManyToManyField(Person)
    person=models.ForeignKey(Person,on_delete=models.CASCADE)

    def __str__(self):
        return self.role

    class Meta:
        ordering = ('role',)

class Name(models.Model):

    name=models.CharField(max_length=200)
    role=models.ForeignKey(Role,on_delete=models.CASCADE)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('name',)

1 个答案:

答案 0 :(得分:1)

简而言之:我认为,应将唯一性约束放在role模型的Role属性上,以防止一个人使用以下内容创建多个Role相同的role属性。

将其建模为多对多关系

在我看来,您想在此处使用多对多关系,因为这意味着Person可以具有许多 {{ 1}}和一个Role可以与许多 Role s相关。

您可能应该使Person字段(尽管这里role更好)是唯一,这样一个不能创建两个角色名称相同:

name

接下来我们可以创建两个像艺术家一样的class Role(models.Model): role = models.CharField(max_length=200, unique=True) persons = models.ManyToManyField(Person, related_name='roles') def __str__(self): return self.role class Meta: ordering = ('role',)

Person

role_artist, __ = Role.objects.get_or_create(role='artist') adam = Person.objects.create(firstName='Adam') david = Person.objects.create(firstName='David') adam.roles.add(role_artist) david.roles.add(role_artist)作为 through 模型

您定义的Name模型似乎可以像Name模型一样工作:它为关系添加了额外的数据。例如,一个人可能有两个Through:一个是歌手,一个是电影明星。这通常是through model [Django-doc]的用例,其中可以对关系中的额外数据进行编码,尽管命名此Name(或至少是更具描述性的名称)可能会更好。

我们可以将其重塑为:

Alias

然后,我们可以制作两个class Role(models.Model): role = models.CharField(max_length=200, unique=True) persons = models.ManyToManyField(Person, through='Alias', related_name='roles') def __str__(self): return self.role class Meta: ordering = ('role',) class Alias(models.Model): name = models.CharField(max_length=200) role = models.ForeignKey(Role, on_delete=models.CASCADE) person = models.ForeignKey(Person, on_delete=models.CASCADE) def __str__(self): return self.name class Meta: ordering = ('name',)Personadam都是艺术家,并且每个都有其艺术家名称:

david

对于同一角色,role_artist, __ = Role.objects.get_or_create(role='artist') adam = Person.objects.create(firstName='Adam') david = Person.objects.create(firstName='David') Alias.objects.create(name='Adam the magician', role=role_artist, person=adam) Alias.objects.create(name='David the lion tamer', role=role_artist, person=david)甚至可能有多个Person个酶。

总结

  

注意:根据PEP 8的命名约定是属性为小写,单词之间用下划线分隔。因此,这意味着它应该是Alias而不是first_name