Джанго Модель отношений рефакторинг помочь? - PullRequest
2 голосов
/ 19 августа 2010

У меня, скорее, брейнфарт с django / db.

Словом, я пытаюсь найти лучший способ представления объектов Address в моем проекте.У меня есть 5 или 6 разных моделей, которые имеют одну или несколько ассоциаций с адресом (выставление счетов / доставка / и т. Д.), И мне нужно разрешить создание / изменение / удаление этих адресов.Моей первой мыслью было использовать администратора для этого, поскольку это выглядит как естественное соответствие.

Однако я не могу понять, как сказать администратору ограничить видимый набор адресов конкретной моделью.под вопросом (Аккаунт / Партнер / Счет).Я нашел действительно неприятный, нежизнеспособный и ужасный способ поддерживать это, что я покажу ниже.

Как я могу сделать это эффективно (желательно в Admin)? Я открыт для перехода на отношения m2m, которые кажутся мне более естественными, и использую пользовательский вид / форму, но я хотел посмотреть, не пропустил ли я какой-то трюк администратора, прежде чем идти по этому пути.Если я пойду по этому пути, я думаю, что мне нужно будет использовать GenericRelation, чтобы у меня не было тонны справочных таблиц (по одной для каждой отдельной сущности).

РЕДАКТИРОВАТЬ: Один и тот же адрес может использоваться для разных моделей и для разных экземпляров конкретной модели: НО если адрес используется повторно, мы должны отслеживать, кто что использует для поддержания независимости между моделями и / или экземплярами.Или, другими словами, в отношении m2m мы можем отслеживать, кто что использует, с помощью промежуточной таблицы.Если мы не используем таблицу поиска, нам нужно всегда копировать экземпляр Address, чтобы оба объекта имели свою собственную копию.(Если есть правка, мы должны убедиться, что мы не меняем ранее существовавшие отношения кого-либо еще. Другими словами, правки фактически создают и переназначают в случае m2m.)

Вот пример, который долженв значительной степени работает как пустой проект, который показывает, как я хочу, чтобы адреса были изолированы во время добавления / редактирования / удаления, но также показывает, насколько ужасным является решение.

models.py

from django.db import models

class Account(models.Model):
    name = models.CharField(max_length=200,blank=True)
    #...
    def __unicode__(self):
        return u"%s - (%s)" %(self.name, self.address_set.all())

class Partner(models.Model):
    name = models.CharField(max_length=200,blank=True) 
    discount = models.DecimalField(max_digits= 3, decimal_places=1, default=0)
    #...
    def __unicode__(self):
        return u"%s - (%s)" %(self.name, self.address_set.all())

class Invoice(models.Model):
    invoice_number = models.IntegerField(default=1)
    #...
    def __unicode__(self):
        return u"%s - (%s)" %(self.invoice_number, self.address_set.all())

class Address(models.Model):
    street = models.CharField(max_length=200,blank=True)
    zip = models.CharField(max_length=10, verbose_name='Zip Code')
    account = models.ForeignKey(Account, blank=True, null=True)
    partner = models.ForeignKey(Partner, blank=True, null=True)
    invoice = models.ForeignKey(Invoice, blank=True, null=True)
    type = models.CharField(max_length=25, choices=(('B','Billing'),('S','Shipping')))

    class Meta:
        unique_together = (('type', 'account' ),
                           ('type', 'partner' ),
                           ('type', 'invoice' ),)

    def __unicode__(self):
        return "(%s) - %s %s" %(self.get_type_display(), self.street, self.zip)

admin.py

from django.contrib import admin
from relationships.rels.models import Partner, Account, Address, Invoice

class AcctAddrInline(admin.TabularInline):
    model = Address
    extra = 1
    max_num =3
    exclude = ('partner', 'invoice')

class PartAddrInline(admin.TabularInline):
    model = Address
    extra = 1
    max_num =3
    exclude = ('account', 'invoice')

class InvAddrInline(admin.TabularInline):
    model = Address
    extra = 1
    max_num =2
    exclude = ('account', 'partner')        

class AccountAdmin(admin.ModelAdmin):
    inlines = [AcctAddrInline,]

class PartnerAdmin(admin.ModelAdmin):
    inlines = [PartAddrInline,]

class InvoiceAdmin(admin.ModelAdmin):
    inlines = [InvAddrInline,]

admin.site.register(Invoice, InvoiceAdmin)         
admin.site.register(Partner, PartnerAdmin)
admin.site.register(Account, AccountAdmin)
admin.site.register(Address)

Ответы [ 2 ]

1 голос
/ 19 августа 2010

РЕДАКТИРОВАТЬ : один и тот же адрес может использоваться для разных моделей и для разных экземпляров конкретной модели, НО если адрес используется повторно, мы должны отслеживать, кто что использует поддерживать независимость между моделями и / или экземплярами

Похоже, вы хотите использовать шаблон COW для адресов, но я не думаю, что он хорошо подходит для всей идеи целостности базы данных.

Если вы просто хотите отделить адреса учетных записей от адресов счетов-фактур, я бы предложил использовать Наследование нескольких таблиц модели . Таким образом, вы будете иметь несколько наборов адресов и сможете одновременно просматривать все адреса.

Вот пример.

models.py

from django.db import models

class Account(models.Model):
    name = models.CharField(max_length=200, blank=True)

    def __unicode__(self):
        return u"%s - (%s)" % (self.name, self.address_set.all())

class Partner(models.Model):
    name = models.CharField(max_length=200, blank=True) 
    discount = models.DecimalField(max_digits= 3, decimal_places=1, default=0)

    def __unicode__(self):
        return u"%s - (%s)" % (self.name, self.address_set.all())

class Invoice(models.Model):
    invoice_number = models.IntegerField(default=1)

    def __unicode__(self):
        return u"%s - (%s)" % (self.invoice_number, self.address_set.all())

class Address(models.Model):
    street = models.CharField(max_length=200, blank=True)
    zip = models.CharField(max_length=10, verbose_name='Zip Code')

    def __unicode__(self):
        return "%s %s" % (self.street, self.zip)

class AccountAddress(Address):
    account = models.ForeignKey(Account, related_name='address_set')

class InvoiceAddress(Address):
    invoice = models.ForeignKey(Invoice, related_name='address_set')

class PartnerAddress(Address):
    partner = models.ForeignKey(Partner, related_name='address_set')

admin.py

from django.contrib import admin
# Wildcard import used for brevity
from relationships.rels.models *

class AccountAddressInline(admin.TabularInline):
    model = AccountAddress
    extra = 1
    max_num = 3

class PartnerAddressInline(admin.TabularInline):
    model = PartnerAddress
    extra = 1
    max_num = 3

class InvoiceAddressInline(admin.TabularInline):
    model = InvoiceAddress
    extra = 1
    max_num = 3

class AccountAdmin(admin.ModelAdmin):
    inlines = [AccountAddressInline,]

class PartnerAdmin(admin.ModelAdmin):
    inlines = [PartnerAddressInline,]

class InvoiceAdmin(admin.ModelAdmin):
    inlines = [InvoiceAddressInline,]

admin.site.register(Account, AccountAdmin)
admin.site.register(Partner, PartnerAdmin)
admin.site.register(Invoice, InvoiceAdmin)

admin.site.register(AccountAddress)
admin.site.register(InvoiceAddress)
admin.site.register(PartnerAddress)

# Uncomment if you want to browse all addresses available at once
# admin.site.register(PartnerAddress)

Обратите внимание на related_name='address_set' взломать. Я не знаю почему, но это единственный способ встроенного редактирования при использовании внешнего ключа от унаследованной модели. Кажется, что это ошибка в Django, похожая на (но скорее с обратным вариантом использования) # 11120 и # 11121 .

0 голосов
/ 19 августа 2010

Лично я бы добавил внешние ключи к вашей модели адреса в Учетную запись, Партнера и Счет-фактуру вместо того, чтобы Адрес знал, к какому адресу это относится.Это, МОЖЕТ, решить вашу проблему.

...