2016-08-24 92 views
0

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_CHOICESUserProfile不覆蓋PRIVACY_CHOICESAbstractProfile。如何解決?在未來可能是其他機型,其中也應該有自己的PRIVACY_CHOICES

我使用Django 1.10

+0

不是在抽象中定義隱私字段,而是爲什麼不把它移動到CompanyProfile而不是在抽象中定義它? –

+0

你的意思是根據需要在許多課程中重複相同的字段?不是乾的方式:) – TitanFighter

+0

我看到兩個模型和兩個定義。看起來不像我。而且,DRY是重要的,但通常運營解決方案更重要。我想這是最好的另一個場地的討論。 –

回答

0

找到解決方案。

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',) 

未修改的形式從抽象類需要選擇。現在不需要在不同的類中重複相同的字段。如果所有類都有自己的選擇版本,那麼方法可以通過適當的修改(至少改變類名)複製到這些類,甚至可以作爲一個單獨的函數,但這是另一回事。