Django模型类__init__内的KeyError
这是我写的一个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 个回答
我觉得这里根本不需要用到 __init__
。
每次创建这个类的时候,你都在计算 link 的值。这就意味着你不管数据库里存了什么。既然这样,那还用模型字段干嘛呢?不如把 link 设成一个属性,用一个获取器来调用 _generate_link
里的代码。
@property
def link(self):
....
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: ...
)。这样,你传入构造函数的链接就不会被覆盖了。
其实没有必要为Django模型类自己写一个__init__
方法。这样做其实会让你更开心。
你在__init__
里想做的几乎所有事情,都可以在save
方法里做得更好。