2013-03-17 81 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'