2013-03-17 97 views
0

我試圖根據字典中包含的鍵值對動態地定義字段。迭代字典時動態設置類屬性(模型字段)

我已經嘗試兩種方式:

字典是:

NOTIFICATION_TYPES = { 
    'friend_request_received': 0, 
    'friend_request_accepted': 1, 
    # eccetera 
} 

非常錯誤的(產生一個例外,因爲自己沒有定義):

class EmailNotification(models.Model): 
    """ 
    User Email Notification Model 
    Takes care of tracking the user's email notification preferences 
    """ 
    user = models.OneToOneField(User, verbose_name=_('user')) 

    for key, value in NOTIFICATION_TYPES.items(): 
     setattr(self, key, models.BooleanField(_('notify new matches'), default=True)) 

    class Meta: 
     db_table = 'profile_email_notification' 

顯然少錯誤但不創建模型字段:

class EmailNotification(models.Model): 
    """ 
    User Email Notification Model 
    Takes care of tracking the user's email notification preferences 
    """ 
    user = models.OneToOneField(User, verbose_name=_('user')) 

    def __init__(self, *args, **kwargs): 

     for key, value in NOTIFICATION_TYPES.items(): 
      setattr(self.__class__, key, models.BooleanField(_(key), default=True)) 

     super(EmailNotification, self).__init__(*args, **kwargs) 

    class Meta: 
     db_table = 'profile_email_notification' 

是否有可能做我想做的事情?我確定它是!

回答

1

你需要後設置這些額外的屬性定義的類:

class EmailNotification(models.Model): 
    """ 
    User Email Notification Model 
    Takes care of tracking the user's email notification preferences 
    """ 
    user = models.OneToOneField(User, verbose_name=_('user')) 

    class Meta: 
     db_table = 'profile_email_notification' 


for key, value in NOTIFICATION_TYPES.items(): 
    setattr(EmailNotification, key, models.BooleanField(_('notify new matches'), default=True)) 

你可以使用一個class decorator包for循環進應用於類的函數:

def add_notification(cls): 
    for key, value in NOTIFICATION_TYPES.items(): 
     setattr(cls, key, models.BooleanField(_('notify new matches'), default=True)) 
    return cls 

@add_notification 
class EmailNotification: 
    # ... 

我有些擔心Django元類處理想要處理這些字段,但您可能需要添加其他調用以使EmailNotification._meta結構知道其他字段你已經添加了。

1

你可以使用一個類裝飾:

def add_notification(cls): 
    for key in NOTIFICATION_TYPES: 
     setattr(cls, key, models.BooleanField(_('notify new matches'), default=True)) 
    return cls 

@add_notification 
class EmailNotification(models.Model): 
    """ 
    User Email Notification Model 
    Takes care of tracking the user's email notification preferences 
    """ 
    user = models.OneToOneField(User, verbose_name=_('user')) 

    class Meta: 
     db_table = 'profile_email_notification'