我正尝试在 Django 1.6.4 中为我的客户编写应用程序
我对 Django 有丰富的经验,但这个案例对我来说很难解决。
我正在使用 Substituting a custom user model功能和我的 Member 类看起来像(这只是简单的代码片段):
class Member(AbstractBaseUser):
...
date_of_birth = models.DateField()
height = models.FloatField()
...
REQUIRED_FIELDS = ['date_of_birth', 'height']
My Member 可以定义多个不同国家的地址。每个国家都有自己特定的地址验证或额外的字段,所以我定义了主要的抽象地址和一些子地址:
class COUNTRIES(object):
POLAND = 'pl'
GERMANY = 'de'
@classmethod
def to_choices(cls):
return ((cls.POLAND, 'Poland'), (cls.GERMANY, 'Germany'))
class BaseAddress(models.Model):
class Meta:
abstract = True
member = models.ForeignKet(settings.AUTH_USER_MODEL, related_name='+')
country = models.CharField(max_length=2, choices=COUNTRIES.to_choices)
class AddressPL(BaseAddress):
street = models.CharField(max_length=80)
city = models.CharField(max_length=20)
postal_code = models.CharField(max_length=6, validators=[RegexValidator('^\d{2}-\d{3}$'),])
def save(self, *args, **kwargs):
self.country = COUNTRIES.POLAND
super(AddressPL, self).save(*args, **kwargs)
class AddressDE(BaseAddress):
street = models.CharField(max_length=80)
city = models.CharField(max_length=20)
postal_code = models.CharField(max_length=6, validators=[RegexValidator('^\d{5}$'),])
def save(self, *args, **kwargs):
self.country = COUNTRIES.GERMANY
super(AddressPL, self).save(*args, **kwargs)
如您所见,唯一的变化是 validators 部分的 postal_code 字段。唯一的问题是,在 Member 中,我需要添加如下内容:
class Member(AbstractBaseUser):
...
@property
def addresses(self):
from itertools import chain
addresses_pl = AddressPL.objects.filter(member=self)
addresses_de = AddressDE.objects.filter(member=self)
return list(chain(addresses_pl, addresses_de))
基于 431628-how to combine 2 or more querysets
我的问题是。你有什么其他的想法来设计这个吗? 我需要提供简单、可扩展的解决方案。 也许有使用代理的想法?
请您参考如下方法:
我认为concrete inheritance可能是您的问题的候选人:
class Member(AbstractBaseUser):
...
date_of_birth = models.DateField()
height = models.FloatField()
...
REQUIRED_FIELDS = ['date_of_birth', 'height']
class BaseAddress(models.Model):
# no abstract = True
member = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='adresses')
country = models.CharField(max_length=2, choices=COUNTRIES.to_choices)
class AddressPL(BaseAddress):
# your custom logic here
class AddressDE(BaseAddress):
# your custom logic here
然后,如果你想添加一些数据:
m = Member(yourargs)
m.save()
adress1 = AdressPL(yourargs)
adress1.member = m
adress1.save()
adress2 = AdressPL(yourargs)
adress2.member = m
adress2.save()
m = Member.objects.get(pk=m.pk)
m.adresses.all() # will output a list of BaseAdresse instances
这样,添加一种新的地址只是子类化 BaseAdress 的问题。无需更改您的用户模型。
具体继承的缺点是它会在继承模型的数据库查询中添加一个连接。
另外,如果你走这条路,看看django-polymorphic ,它是一个 Django 应用程序,提供了处理具体继承的有用方法。
