如何覆盖抽象类的选择?
问题描述:
我AbstractProfile
模型预定义PRIVACY_CHOICES
:如何覆盖抽象类的选择?
class AbstractProfile(models.Model):
PRIVACY_CHOICES = (
(1, _('all')),
(2, _('no one')),
)
title = models.CharField(_('title'), max_length=30)
info = models.TextField(_('information'), max_length=500, blank=True)
info_privacy = models.IntegerField(_('show information to'), default=1, choices=PRIVACY_CHOICES)
city = models.CharField(_('location'), max_length=30, blank=True)
city_privacy = models.IntegerField(_('show location to'), default=1, choices=PRIVACY_CHOICES)
address = models.CharField(_('address'), max_length=30, blank=True)
address_privacy = models.IntegerField(_('show address to'), default=1, choices=PRIVACY_CHOICES)
class Meta:
abstract = True
class UserProfile(AbstractProfile):
PRIVACY_CHOICES = (
(1, _('all')),
(2, _('friends')),
(3, _('friends of friends')),
(4, _('only me')),
)
title = None
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
names_privacy = models.IntegerField(_('show names to'), default=1, choices=PRIVACY_CHOICES)
birth_date = models.DateField(_('birth date'), null=True, blank=True)
birth_date_privacy = models.IntegerField(_('show birth date to'), default=1, choices=PRIVACY_CHOICES)
avatar = models.ImageField(upload_to='users/avatar', null=True, blank=True)
UserProfile
应该从场AbstractProfile
,但有自己的PRIVACY_CHOICES
。在当前实现PRIVACY_CHOICES
的UserProfile
不覆盖PRIVACY_CHOICES
的AbstractProfile
。如何解决?在未来可能是其他机型,其中也应该有自己的PRIVACY_CHOICES
我使用Django 1.10
答
找到解决方案。
models.py:
class AbstractProfile(models.Model):
PRIVACY_CHOICES = (
(1, _('all')),
(2, _('no one')),
)
title = models.CharField(_('title'), max_length=30)
info = models.TextField(_('information'), max_length=500, blank=True)
info_privacy = models.IntegerField(_('show information to'), default=1, choices=PRIVACY_CHOICES)
city = models.CharField(_('location'), max_length=30, blank=True)
city_privacy = models.IntegerField(_('show location to'), default=1, choices=PRIVACY_CHOICES)
address = models.CharField(_('address'), max_length=30, blank=True)
address_privacy = models.IntegerField(_('show address to'), default=1, choices=PRIVACY_CHOICES)
class Meta:
abstract = True
class UserProfile(AbstractProfile):
PRIVACY_CHOICES = (
(1, _('all')),
(2, _('friends')),
(3, _('friends of friends')),
(4, _('only me')),
)
# NEW PIECE OF CODE
def __init__(self, *args, **kwargs):
def get_class_attrs(cls):
return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__'])
super(UserProfile, self).__init__(*args, **kwargs)
all_fields = get_class_attrs(UserProfile)
for each_field in all_fields:
# all fields with '_privacy' in the name have 'choice' option
if '_privacy' in each_field:
self._meta.get_field(each_field).choices = self.PRIVACY_CHOICES
default_privacy_choice = self.PRIVACY_CHOICES[0][0]
if self._meta.get_field(each_field).default != default_privacy_choice:
self._meta.get_field(each_field).default = default_privacy_choice
# END OF NEW PIECE OF CODE
title = None
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
names_privacy = models.IntegerField(_('show names to'), default=1, choices=PRIVACY_CHOICES)
birth_date = models.DateField(_('birth date'), null=True, blank=True)
birth_date_privacy = models.IntegerField(_('show birth date to'), default=1, choices=PRIVACY_CHOICES)
avatar = models.ImageField(upload_to='users/avatar', null=True, blank=True)
class CompanyProfile(AbstractProfile):
pass
class OneMoreClass(AbstractProfile):
pass
而且是有必要修改forms.py:
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile() # old_version was: model = UserProfile
fields = ('title',
'first_name', 'last_name', 'names_privacy',
'birth_date', 'birth_date_privacy',
'info', 'info_privacy',
'city', 'city_privacy', 'address', 'address_privacy',
'avatar',)
未修改的形式从抽象类需要选择。现在不需要在不同的类中重复相同的字段。如果所有类都有自己的选择版本,那么方法可以通过适当的修改(至少改变类名)复制到这些类,甚至可以作为一个单独的函数,但这是另一回事。
不是在抽象中定义隐私字段,而是为什么不把它移动到CompanyProfile而不是在抽象中定义它? –
你的意思是根据需要在许多课程中重复相同的字段?不是干的方式:) – TitanFighter
我看到两个模型和两个定义。看起来不像我。而且,DRY是重要的,但通常运营解决方案更重要。我想这是最好的另一个场地的讨论。 –