0

我试图根据字典中包含的键、值对动态定义模型的字段。

我尝试了两种方法:

字典是:

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'

有可能做我想做的事吗?我确定是!

4

3 回答 3

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

您可以使用类装饰器将 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结构知道您添加的其他字段。

于 2013-03-17T13:22:59.180 回答
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'
于 2013-03-17T13:24:50.723 回答
0

感谢答案中的建议,但缺少一个关键的概念。

必须做两件事:

setattr(myclass, key, field)
myclass.add_to_class(key, field)

这里的工作解决方案:

https://github.com/nemesisdesign/nodeshot/blob/7798f81d558791499039afab1c860483fe30dd77/nodeshot/community/notifications/models/user_settings.py#L6

于 2013-08-22T09:03:08.473 回答