уникальные ограничения в Джанго - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть база данных в django, которая содержит людей и роли.человек имеет отношение «один ко многим» к ролям.Проблема в том, что у ролей нет уникального ограничения, например, персонажи adam и david могут быть художниками в ролях, но django создает две одинаковые записи исполнителей, но я хочу одну и ту же запись, т.е. adam и david должны указывать на одну запись.Если я добавлю уникальное поле своей роли, тогда django скажет, что это должно быть один к одному.Любые идеи?

часть model.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',)

изменен admin.py для ответа ниже:

from django.contrib import admin
from .models import Role,Alias,Address,Date,Person,Name

from django.conf.urls import url, include

# Register your models here.

admin.site.register(Role)
admin.site.register(Address)
admin.site.register(Date)
admin.site.register(Name)
admin.site.register(Alias)
admin.site.register(Person)

class AliasInline(admin.TabularInline):

#    model=Role.person.through
    model=Alias
    extra=2

class RoleInline(admin.TabularInline):

#    model=Role.person.through
    model=Role
    extra=2

class NameInline(admin.TabularInline): # nested inlines doesn't work

#class NameInline(admin.ModelAdmin): # nested inlines doesn't work

    model=Name
    extra=3

class PersonInline(admin.ModelAdmin):

    fieldsets=[
        (None,{'fields': ['mail','firstName','lastName','phoneNumber','streetAdress','zipcode','city','country']}),
    ]
    inlines = [RoleInline]
    search_fields = ['firstName']

1 Ответ

0 голосов
/ 27 февраля 2019

Короче говоря : я думаю, что ограничение уникальности должно быть наложено на атрибут role модели Role, чтобы предотвратить создание нескольких Role с одним и тем же атрибутом role.

Моделирование этого отношения многие ко многим

Мне кажется, вы хотите использовать отношение многие ко многим здесь, поскольку это означает, что Person может иметь много Role с, а Role может быть связано с многими Person с.

Вам, вероятно, следует сделать поле role (хотя, возможно, name здесь лучше) уникально , так что один не может создать две роли с одинаковым именем:

class Role(models.Model):
    role = models.CharField(max_length=200<b>, unique=True</b>)
    <b>persons = models.ManyToManyField(Person, related_name='roles'</b>)

    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)

Name как - модель

Модель Name, которую вы определяете, похоже, работает как модель Through: она добавляет дополнительные данные в отношение.Например, у человека может быть два Name с: один как певец и один как кинозвезда.Обычно это вариант использования through модели [Django-doc] , где можно кодировать дополнительные данные в отношении, хотя, возможно, было бы лучше назвать это Alias (или, по крайней мере, более описательное имя).

Мы можем перемоделировать это как:

class Role(models.Model):
    role = models.CharField(max_length=200, unique=True)
    persons = models.ManyToManyField(Person<b>, through='Alias'</b>, related_name='roles')

    def __str__(self):
        return self.role

    class Meta:
        ordering = ('role',)

class <b>Alias</b>(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',)

Затем мы можем сделать два Person s adam и 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 имеет несколько Alias ses для одной и той же роли.

Заключительные замечания

Примечание : в соответствии с PEP 8 соглашение об именах состоит в том, что атрибуты являются строчными, а слова разделяются подчеркиванием.То есть это должно быть first_name вместо firstName.

...