Django模型的保留字段

时间:2020-11-02 09:36:41

标签: python django django-models

我想要一个带有保留字段的Django模型,这样没人能直接设置它,但是它的值是在节省时间生成的。例如,这对于生成用户令牌很有用,并且我想防止开发人员直接为令牌密钥设置值。同时,我希望能够像对待其他字段一样对待该字段,因此可以使用__进行查询中的字段查找,或者将令牌检索为:

token = Token.objects.get(key='c331054c00494f6a22f0ebde7a32bf9d4619b988')

所以在我看来,做这样的事情:

Token.key = 'my-token-key'

应该失败,甚至实例化也应该失败:

token = Token(key='my-token-key')

到目前为止,我想出了这个解决方案,但是我有点担心我的更改可能会破坏某些Django工作流程,因为我不确定我的更改会影响什么:

import binascii
import datetime
import os

from django.contrib.auth import get_user_model
from django.db import models


class Token(models.Model):
    """
    An access token that is associated with a user.
    """
    id = models.AutoField(primary_key=True)

    # By default `get_attname` returns the field `name`,
    # but in my case the attribute name is different
    _key = models.CharField(max_length=40, unique=True, name='key', db_column='key')
    _key.get_attname = lambda: '_key'

    name = models.CharField(max_length=255)
    user = models.ForeignKey(get_user_model(), related_name='tokens')
    created = models.DateTimeField(auto_now_add=True)
    last_access_time = models.DateTimeField(null=True, blank=True)
    expires = models.DateField(
        null=True,
        blank=True,
        help_text="Leave empty for non-expiring tokens. "
                  "Once the token has expired you can not extend its validity.",
    )

    @property
    def key(self):
        return self._key

    @key.setter
    def key(self, value):
        raise ValueError("Can not set key directly. It is automatically generated when saving the model.")

    def save(self, *args, **kwargs):
        if not self._key:
            self._key = self._generate_key()
        super(Token, self).save(*args, **kwargs)

    @staticmethod
    def _generate_key():
        return binascii.hexlify(os.urandom(20)).decode()

    @property
    def expired(self):
        return bool(self.expires and self.expires < datetime.date.today())

    def __str__(self):
        return '{} - {}'.format(self.user, self.name)

    class Meta:
        verbose_name = "User Token"
        verbose_name_plural = "User Tokens"
        unique_together = (('name', 'user'),)

如您所见,我尝试覆盖键字段的get_attname方法(之所以需要,是因为字段名称和属性相同,这会导致加载表单时出错)。这似乎很好,但是我想知道这是否会导致运行查询的问题。

也许有一种更简单的方法可以做到这一点,但我找不到更好的方法。

P.S .:我在Django 1.11上使用python2

非常感谢大家!

0 个答案:

没有答案