我试图根据字典中包含的键,值对动态定义模型的字段。
我尝试过两种方式:
字典是:
NOTIFICATION_TYPES = {
'friend_request_received': 0,
'friend_request_accepted': 1,
# eccetera
}
非常错误(因为未定义self而生成异常):
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'
我可以做我想做的事情吗?我确定是的!
答案 0 :(得分: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 :(得分: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'
答案 2 :(得分:0)
感谢答案中的建议,但有一个关键缺失的概念。
必须做两件事:
setattr(myclass, key, field)
myclass.add_to_class(key, field)
这里有一个有效的解决方案: