我希望能够做到:
def update_profile(request, username):
user = Profile.objects.get(user__username=username)
# update subset of profile, eg value_to_company is set in request.POST
# but user (or an arbitrary number of other attributes) is not
profile = ProfileForm(request.POST, instance=user)
if not profile.is_valid():
print profile.errors #user is required
我遇到的问题是用户肯定存在并且是实例的一部分,我在文档中找不到任何建议实例数据不会进入绑定数据的内容。但我也找不到任何明确表示将。
的内容(剩下的就是我为什么按照自己的方式做事的理由,以及解决方案的想法,你可能不需要阅读它。)
如果你想知道为什么我要通过一个表格 - 这个问题不是必不可少的 - 那是因为我有这样的事情:
class Profile(models.Model):
user = models.ForeignKey(auth.models.User)
value_to_company = models.IntegerField()
class ValueField(forms.Field):
def to_python(self, value):
vals = {'high': 0,
'mid': 1}
return vals[value]
class ProfileForm(forms.ModelForm):
value_to_company = ValueField()
class Meta:
model = Profile
也就是说,我已经在我的表单中进行了类型api-to-internal-representation-cercion,我想继续使用它。
我可以重新实现forms.is_valid()循环,只需检查已经存在的表单上的字段,就像hacky那样:
# replaces `if not profile.is_valid()` above:
errors = []
for field in request.POST.iterkeys():
if field in profile.fields:
profile.fields[field].to_python()
if not profile.fields['field'].clean():
errors.append #something
(我实际上没有看过逻辑内部逻辑,所以我知道这是错的,但你明白了。)
答案 0 :(得分:0)
您可能只需要在表单中添加exclude = ('user',)
即可。表单实例主要确定初始值,如果您的表单包含用户字段,但该字段使用空白值发布,将尝试删除用户字段,从而导致错误。
答案 1 :(得分:0)
我在this solution中找到django-piston。
它会添加您在调用merge_from_initial
之前调用的其他表单方法is_valid
,并填充所给对象中缺少的字段。
我已经改变了一点并且正在使用:
class BaseModelForm(forms.ModelForm):
"""
Subclass of `forms.ModelForm` which makes sure that the instance values are present in the form
data, so you don't have to send all old values for the form to actually validate. Django does not
do this on its own.
"""
def merge_from_instance(self):
# Internals
self.data._mutable = True
fun = lambda v: v not in self.data.keys()
for field in filter(fun, self.fields.keys()):
if field not in self.initial:
continue
value = self.initial.get(field)
if isinstance(self.instance._meta.get_field(field), related.ManyToManyField):
self.data.setlist(field, value)
else:
self.data[field] = value