2016-08-24 7 views
0

나는 미리 정의 된 PRIVACY_CHOICESAbstractProfile 모델이 있습니다추상 클래스의 선택을 어떻게 무시할 수 있습니까?

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) 

UserProfileAbstractProfile에서 필드를해야한다,하지만 PRIVACY_CHOICES 그 자체로. 현재 실현시 PRIVACY_CHOICESUserProfile 인 경우 PRIVACY_CHOICESAbstractProfile으로 대체되지 않습니다. 어떻게 해결할 수 있습니까? 미래는 자신의 PRIVACY_CHOICES

나는

+0

추상에 해당 개인 정보 필드를 정의하는 대신 CompanyProfile로 이동하고 추상으로 정의하지 않는 이유는 무엇입니까? –

+0

필요에 따라 여러 필드에서 동일한 필드를 반복 하시겠습니까? DRY 방식이 아닙니다 :) – TitanFighter

+0

두 모델과 두 가지 정의를 봅니다. 나 한테는 그렇게 보이지 않아. 그리고 DRY는 중요하지만 일반적으로 운영 솔루션을 갖는 것이 더 중요합니다. 나는 이것이 다른 장소에서 가장 좋은 토론이라고 생각합니다. –

답변

0

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

수정되지 않은 형태는 추상 클래스에서 선택을합니다. 이제는 다른 클래스에서 동일한 필드를 반복 할 필요가 없습니다. 모든 클래스에 자체 버전의 선택 항목이있는 경우 메소드를 적절한 수정 (최소한 클래스 이름 변경)을 통해 해당 클래스에 복사하거나 별도의 함수로 만들 수도 있지만 다른 이야기입니다.