I'm sorta having a django / db brainfart.
In words I'm trying to come up with a better way to represent Address objects in my project. I have 5 or 6 different models that have one or more associations to an Address (Billing / Shipping / etc) and I need to allow these addresses to be created/modified/deleted. My first thought was to use the Admin for this since it seems like a natural fit.
However, I can't seem to figure out how to tell the Admin to restrict the visible set of addresses to the specific model in question(Account/Partner/Invoice). I found a really nasty, not viable, and incredibility horrible to maintain way to do it, which I will show below.
How can I do this efficiently (preferably in the Admin)? I am open to going to a m2m relationship which feels much more natural to me, and using a custom view/form, but I wanted to see if I was missing some Admin trick before I went that route. If I go that route I'm thinking I will need to use a GenericRelation so that I don't end up with a ton of lookup tables (one for each different entity).
EDIT: The same address may be used for different models, and for different instances of a particular model, BUT if an address is reused we must track who is using what to maintain independence between models and/or instances. Or in other words in a m2m relationship we can track who is using what with the intermediate table. If we aren't using a lookup table then we need to always copy the Address instance so that both objects have their own copy. (If there is an edit we need to make sure we aren't changing the preexisting relationships of anyone else. In other words edits are actually creates and reassigns in the m2m case.)
Here is an example that should pretty much work as an empty project that sorta shows how I want the address(es) isolated during add/edit/delete, but it also shows how horrible the solution is.
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)