Django模型类__init__内的KeyError

1 投票
4 回答
3762 浏览
提问于 2025-04-15 11:36

这是我写的一个Django模型类。当我从Django调用 get_object_or_404 时,它会出现一个键错误(keyerror)。我猜这个错误是因为在调用get函数时,没有把任何关键字参数(kwargs)传递给 __init__,而所有的参数都是位置参数。奇怪的是,当我在控制台调用 get_object_or_404 时却没有出现错误。

我想知道这是为什么,以及下面的代码是否是构建这个类的正确方式(也就是说,是否可以用 init 来填充链接字段)。

class Link(models.Model)

    event_type = models.IntegerField(choices=EVENT_TYPES)
    user = models.ForeignKey(User)
    created_on = models.DateTimeField(auto_now_add = True)
    link = models.CharField(max_length=30)
    isActive = models.BooleanField(default=True)

    def _generate_link(self):
        prelink = str(self.user.id)+str(self.event_type)+str(self.created_on)
        m = md5.new()
        m.update(prelink)
        return m.hexdigest()

    def __init__(self, *args, **kwargs):
        self.user = kwargs['user'].pop()
        self.event_type = kwargs['event_type'].pop()
        self.link = self._generate_link()
        super(Link,self).__init__(*args,**kwargs)

4 个回答

2

我觉得这里根本不需要用到 __init__

每次创建这个类的时候,你都在计算 link 的值。这就意味着你不管数据库里存了什么。既然这样,那还用模型字段干嘛呢?不如把 link 设成一个属性,用一个获取器来调用 _generate_link 里的代码。

@property
def link(self): 
    ....
7
self.user = kwargs['user'].pop()
self.event_type = kwargs['event_type'].pop()

你想从字典里取出一个条目,然后调用它的 pop 方法。如果你想从字典中删除并返回一个对象,可以使用 dict.pop() 方法:

self.user = kwargs.pop('user')

当然,如果 "user" 不在 kwargs 里,这样做会出错,出现 KeyError。你需要给 pop 方法提供一个默认值:

self.user = kwargs.pop('user', None)

这意味着“如果 "user" 在字典里,就删除并返回它。否则,返回 None”。

关于其他两行代码:

self.link = self._generate_link()
super(Link,self).__init__(*args,**kwargs)

super().__init__() 会把 link 设置为某个值,可能是 None。我建议把这两行代码的顺序调换,像这样:

super(Link,self).__init__(*args,**kwargs)
self.link = self._generate_link()

你可能想在设置 link 之前加个检查,看看它是否已经存在(if self.link is not None: ...)。这样,你传入构造函数的链接就不会被覆盖了。

2

其实没有必要为Django模型类自己写一个__init__方法。这样做其实会让你更开心。

你在__init__里想做的几乎所有事情,都可以在save方法里做得更好。

撰写回答