我有一个基本的模型/表单/视图:
models.py
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True)
forms.py
class TagForm(forms.ModelForm):
class Meta:
model = Tag
fields = '__all__'
views.py
class TagCreate(CreateView):
model = Tag
form_class = TagForm
success_url = reverse_lazy('view_somethin')
当使用 django-rest-frawework 或 Tag.objects.create(name="aagagaga"(时,"name"字段被传递给Tag
的__init__()
,我可以做所有我想做的黑客。
但是当使用基于类的视图时,当然会调用__init__()
,但不会将参数传递给。但是,在 save 方法中,我可以检查 name 属性是否已设置为良好值。
我的问题是,如果在基于类的视图的情况下,数据如何以及在何处传输到模型实例,则没有任何东西传递给__init__()
?我尝试挖掘源代码但没有成功,我怀疑某个经理之王
如果要重现该问题,以下是测试代码:
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True)
def __str__(self):
return f"Tag {self.name}"
def __init__(self, *args, **kwargs):
print(args)
print(kwargs)
super().__init__(*args, **kwargs)
print(self.__dict__)
def save(self, *args, **kwargs):
print(self.__dict__) # the filled attributes are here, but when were they filled ?
super().save(*args, **kwargs)
Tag.objects.create(name="aagagaga") # this call the __init__() with args as
# intended but when using the html view, nothing is passed
所以我找到了一种方法,我不完全是它在内部的工作方式,但我想 Django 会动态修改模型的属性。实际上,form
将模型实例的引用存储在self.instance
因此,如果您想像在模型__init__()
中那样添加/修改属性,您可以通过覆盖CreateView
form_valid
来实现:
class TagCreate(CreateView):
model = Tag
form_class = TagForm
success_url = reverse_lazy('view_somethin')
def form_valid(self, form):
form.instance.new_attribute = "new_thing"
return super().form_valid(form)
然后它出现在模型中。
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True)
def save(self, *args, **kwargs):
print(self.__dict__) # new_attribute appeared
self.name += self.new_attribute
super().save(*args, **kwargs)
当然,新属性并不意味着保存在数据库中,但可以是一个有用的修饰符,就像当前用户一样。