情况
使用 Django 1.5,我使用forms.ModelForm
s 让用户编辑数据库内容。但是我无法获取更新数据库的表单form.save()
。
我的每个模型都对应一个设置表单(该应用程序是桌面软件的直接移植,用户可以在其中存储多个设置)。我需要实现一个重置为默认功能,所以我想有一个默认对象(使用 Django 固定装置导入),我只会用它来重置第二个。用户只会与第二个模型交互。
pk=1
指基础对象pk=2
指的是自定义对象
我在同一页面上有几个表格(仅foobar
在这里),所以基本上这是我计划做的:
- 无更新数据
- 是否已找到来自
pk=1
orpk=2
的建筑形式pk=2
- 将表单呈现到模板
- 是否已找到来自
- AJAX 请求,带有 POST 数据
- 获取表单内容
- 检查用户是否有权编辑模型(校验和)
- 更新模型表单 POST 数据
- 返回 AJAX 响应
代码
我放了两个 debugprint
来说明我面临的问题。我获取的表格似乎没有绑定到我的模型。
# Response codes to use in the template
RESPONSES = {
200: {'code':'0xB16B00B5', 'message':'Success'},
400: {'code':'0x8BADF00D', 'message':'Form is not valid'},
403: {'code':'0xBAADF00D', 'message':'No permission to edit the database'},
501: {'code':'0xDEADC0DE', 'message':'POST datas not found'},
}
# Those are the setting labels
TYPES = {
'foobar': {'model':FooBar, 'form':FooBarForm },
}
def index(request):
# Handling form datas
if request.method == 'POST':
response = HttpResponse(simplejson.dumps({'code':RESPONSES[501]['code']}), 'application/json')
for label in TYPES:
# Filtering the right form to handle
if label in request.POST:
model = _fetch_setting(label, mode='model')
form = _fetch_setting(label, mode='form', post=request.POST)
checksum = model.checksum # Somehow, 'form.is_valid()' is altering 'model', need to backup the checksum
if form.is_valid():
# The user has permission to edit the model
if form.cleaned_data['checksum'] == checksum:
if form.has_changed():
print form.cleaned_data['foo'] # Outputs the form data, as expected
form.save()
print model.foo # Outputs the old data
model.checksum = str(uuid4()).replace('-', '')
model.save()
response = HttpResponse(simplejson.dumps({'code':RESPONSES[200]['code']}), 'application/json')
# This one does not
else:
response = HttpResponse(simplejson.dumps({'code':RESPONSES[403]['code']}), 'application/json')
break # We are still inside the label loop
# The form is not valid
else:
response = HttpResponse(simplejson.dumps({'code':RESPONSES[400]['code']}), 'application/json')
# Form not submitted yet, building the HTML forms
else:
forms = {}
label = 'foobar'
for label in TYPES:
forms[label] = _fetch_setting(label, mode='form')
context = {'errors':RESPONSES, 'forms':forms}
response = render(request, 'home/index.html', context)
return response
# Return a setting object (model or form) corresponding to the given label
def _fetch_setting(label, mode='model', post=None):
try:
result = None
default = TYPES[label]['model'].objects.get(pk=1)
try:
model = TYPES[label]['model'].objects.get(pk=2)
except TYPES[label]['model'].DoesNotExist:
model = TYPES[label]['model'].objects.create(
checksum = default.checksum,
foo = default.foo,
bar = default.bar,
)
if mode == 'model':
result = model
if mode == 'form':
print model
result = TYPES[label]['form'](data=post, instance=model) # The 'instance' attribute doesn't seem to be applied
except KeyError:
result = None
finally:
return result
更新
07.10
当我将实例传递给与 to 绑定时,它确实有效_fetch_setting
。所以我猜这个问题来自表单验证。
def _fetch_setting(label, mode='model', post=None, instance=None):
# ...
if mode == 'form':
if instance:
model = instance
result = TYPES[label]['form'](data=post, instance=model)
# ...
正如我在代码中评论的那样,form.is_valid()
似乎改变了对象。
如果没有人提供干净的解决方案,将标记为已回答。