Если я правильно понял; все модели Contact
, Organization
и UserProfile
должны иметь поля для Address
и Phone
. Более того, каждый из них может иметь более одного адреса / телефона.
Разумно ли это? Мне так кажется.
Как вы могли бы заняться настройкой моделей? Родовые отношения возникают у меня на уме.
Рассмотрим только Contact
и Address
на данный момент. Ваша вторая попытка верна: у нас есть отношение Много-к-одному (один контакт, много адресов), поэтому нам нужно сделать Contact
полем ForeignKey в модели Address
, например, так:
class Address(models.Model):
<other_fields>
contact = models.ForeignKey('Contact', on_delete=models.CASCADE)
Это позволяет назначать несколько адресов каждому контакту.
Продолжая, вы, по сути, хотите, чтобы ваша модель Address
имела несколько внешних ключей: Contact, Organization и UserProfile. Одним из способов достижения этого является использование общих отношений. Это использует встроенную в Django структуру «contenttypes» и позволяет вам создавать GenericForeignKey
полей, которые указывают на более чем одну модель. Я рекомендую вам прочитать связанные документы, поскольку родовые отношения не так тривиальны. В итоге у вас будет что-то вроде:
class Address(models.Model):
label = models.CharField(max_length=50, blank=True)
street_1 = models.CharField(max_length=125, blank=True)
street_2 = models.CharField(max_length=125, blank=True)
etc...
models_with_address = models.Q(app_label='app_name', model='contact') | \
models.Q(app_label='app_name', model='organization') | \
models.Q(app_label='app_name', model='userprofile')
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, limit_choices_to=models_with_address)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey()
При этом вы можете создать несколько адресов для каждой из моделей, указанных в запросе models_with_address
. Чтобы иметь возможность запрашивать адреса для данного контакта / организации / и т. Д., Вам потребуется обратное родовое отношение . Настройка включает добавление строки address = GenericRelation(Address)
к соответствующим моделям.
Для дальнейшего обобщения вы можете создать ContactableModel
(или любой другой) класс:
class ContactableModel(models.Model):
address = GenericRelation('Address')
phone = GenericRelation('Phone')
Любая модель с адресом и номером телефона (контакт, организация и т. Д.) Может наследовать это, чтобы вам не приходилось многократно включать эти два поля. Вы также можете улучшить предел models_with_address
, чтобы у нас было что-то вроде limit_choices_to=<subclasses_of_ContactableModel>
.
Надеюсь, это поможет!