我有一些带有用户字段的模型。
为此,我想创建一个表单mixin,它将添加self.user
实例(在视图中提供给表单)。有可能吗?
这是示例
class UserFormMixin(object):
"""Removes user instance from kwargs and adding it to object"""
def __init__(self, *args, **kwargs):
super(UserFormMixin, self).__init__(*args, **kwargs)
self.user = kwargs.pop('user')
def save(self, **kwargs):
obj = super(UserFormMixin, self).save(commit=False)
obj.user = self.user
if kwargs['commit']:
return obj.save()
else:
return obj
我想要实现的目标:
class SomeFormWithUserField(UserFormMixin, ModelForm):
class Meta:
model = SomeModelWithUserField
fields = ['fields without user']
def save(self, **kwargs):
data = super(SomeFormWithUserField, sefl).save(commit=False)
#data already with user prepended
#do some other stuff with data
if kwargs['commit']:
return data.save()
else
return data
class SomeOtherFormWithUser(UserFormMixin, ModelForm):
class Meta:
model = SomeOtherModel
fields = ['some fields without user']
# no need to save here.. standard model form with user prepended on save()
问题是UserFormMixin不了解模型实例?或者我错在这里? 我遇到了一些问题..比如'commit'kwargs key error ..或者对象没有保存..
答案 0 :(得分:6)
你很接近,你只是有一些逻辑错误。首先,为了覆盖ModelForm
方法,您的mixin需要从ModelForm
继承。
class UserFormMixin(forms.ModelForm):
...
然后,从中继承的任何表单都会继承UserFormMixin
,而不是ModelForm
。
class SomeOtherFormWithUser(UserFormMixin):
...
其次,您的__init__
方法覆盖不正确。你需要接受传递给它的任何和所有的args和kwargs。
def __init__(self, *args, **kwargs):
...
最后,不要在子类中再次覆盖save
方法。我想它在技术上不会伤害任何东西,但是如果你要重复代码,那么继承的重点是什么呢?如果user
不可为空,则在将其添加到模型之前,您始终可以添加if块以检查self.user is not None
是否为user
。当然,如果self.user
不可为空,那么无论如何都不会在没有{{1}}的情况下保存您的模型。
答案 1 :(得分:1)
这个似乎工作得很好。谢谢克里斯! 如果这可以更好地编码,请告诉我。
class UserFormMixin(forms.ModelForm):
"""Removes user instance from kwargs and adding it to object"""
def __init__(self, *args, **kwargs):
super(UserFormMixin, self).__init__(*args, **kwargs)
self.user = kwargs.pop('user')
def save(self, commit=True):
obj = super(UserFormMixin, self).save(commit=False)
obj.user = self.user
if commit:
return obj.save()
else:
return obj
class SomeFormWithUserField(UserFormMixin):
class Meta:
model = SomeModelWithUserField
fields = ['fields without user']
def save(self, **kwargs):
data = super(SomeFormWithUserField, sefl).save(commit=False)
#data already with user prepended
#do some other stuff with data
# self.send_mail() f.e.
return data.save()
class SomeOtherFormWithUser(UserFormMixin):
class Meta:
model = SomeOtherModel
fields = ['some fields without user']
# this will work too