簡體   English   中英

迭代字典時動態設置類屬性(模型字段)

[英]Dynamically set class attributes (model fields) while iterating a dictionary

我正在嘗試根據字典中包含的鍵,值對動態定義模型的字段。

我嘗試了兩種方法:

字典是:

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'

有可能做我想做的事嗎? 我確定是的!

定義類之后,您需要設置這些額外的屬性:

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結構知道您添加的其他字段。

你可以使用類裝飾器:

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'

感謝答案中的建議,但有一個關鍵缺失的概念。

必須做兩件事:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM