【发布时间】:2017-09-26 01:20:44
【问题描述】:
我遵循了 Vitor Freitas 的精彩教程 How to Implement CRUD Using Ajax and Json。对于我的项目,我有一个与用户具有多对一关系的对象,我希望用户能够添加和更新。我可以添加对象,但是当我尝试更新它时会抛出一个
ValueError: Cannot query "Case object": Must be "User" instance.
views.py
def case_update(request, pk):
case = get_object_or_404(Case, pk=pk)
if request.method == 'POST':
form = CaseForm(request.POST, instance=case)
else:
form = CaseForm(instance=case)
return save_case_form(request, form, 'cases/includes/partial_case_update.html')
当我尝试保存编辑时它会中断,但我正在努力寻找解决方法。要编辑此案例,我需要将表单作为此特定案例的一个实例,因为用户可能有很多案例。当我将实例设置为用户时,什么都没有发生,当我完全删除实例时,它显然只是复制了一个案例,所以我有两个相同的案例。
如有必要,我可以发布更多代码。谢谢
编辑
我只使用 inlineformset 重构了我的代码,它正在工作......有点。我现在可以编辑案例,但我仍然无法编辑单个案例。当我尝试使用 inlineformset 执行case = get_object_or_404(Case, pk=pk) 的实例时,我继续收到ValueError: Cannot query "Case object": Must be "User" instance。当我将其更改为用户实例时,它会显示该特定用户的所有案例,但它会正确保存。
def save_case_form(request, case_formset, template_name):
data = dict()
if request.method == 'POST':
if case_formset.is_valid():
case_formset.save()
data['form_is_valid'] = True
cases = Case.objects.all()
data['html_case_list'] = render_to_string('cases/includes/partial_case_list.html', {
'cases': cases
})
else:
data['form_is_valid'] = False
context = {'case_formset' : case_formset}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
def case_create(request):
if request.method == 'POST':
case_formset = CaseFormset(request.POST, instance = request.user)
else:
case_formset = CaseFormset()
return save_case_form(request, case_formset, 'cases/includes/partial_case_create.html')
def case_update(request, pk):
case = get_object_or_404(Case, pk=pk)
if request.method == 'POST':
case_formset = CaseFormset(request.POST, instance=request.user)
else:
case_formset = CaseFormset(instance=request.user)
return save_case_form(request, case_formset, 'cases/includes/partial_case_update.html')
forms.py
class CaseForm(forms.ModelForm):
class Meta:
model = Case
fields = ('title', 'publication_date', 'author', 'price', 'pages', 'case_type', )
CaseFormset = inlineformset_factory(User,Case,
fields = ('title', 'publication_date',
'author', 'price',
'pages', 'case_type', ),
can_delete = False,
extra = 1)
编辑
有效的非 DRY 实现:
forms.py
class CaseForm(forms.ModelForm):
class Meta:
model = Case
fields = ('title', 'publication_date', 'author', 'price', 'pages', 'case_type', )
CaseFormset = inlineformset_factory(User,Case,
fields = ('title', 'publication_date',
'author', 'price',
'pages', 'case_type', ),
can_delete = False,
extra = 1)
CaseFormsetUpdate = inlineformset_factory(User,Case,
fields = ('title', 'publication_date',
'author', 'price',
'pages', 'case_type', ),
can_delete = False,
extra = 0)
views.py
def save_case_form(request, case_formset, template_name):
data = dict()
if request.method == 'POST':
if case_formset.is_valid():
case_formset.save()
data['form_is_valid'] = True
cases = Case.objects.all()
data['html_case_list'] = render_to_string('cases/includes/partial_case_list.html', {
'cases': cases
})
else:
data['form_is_valid'] = False
context = {'case_formset' : case_formset}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
def case_create(request):
if request.method == 'POST':
case_formset = CaseFormset(request.POST, instance = request.user)
else:
case_formset = CaseFormset()
return save_case_form(request, case_formset, 'cases/includes/partial_case_create.html')
def case_update(request, pk):
case = get_object_or_404(Case, pk=pk)
if request.method == 'POST':
case_formset = CaseFormsetUpdate(request.POST, instance=request.user)
else:
case_formset = CaseFormsetUpdate(instance=request.user, queryset = Case.objects.filter(pk=pk))
return save_case_form(request, case_formset, 'cases/includes/partial_case_update.html')
当在视图中实例化内联表单集时,我无法找到更改额外参数的方法。所以我只是做了第二个,额外设置为 0 并将其添加到我的更新案例视图中。我仍然对更好的方法感兴趣。
【问题讨论】:
-
您能告诉我们您的表单代码吗?另外,你在哪里打电话给实际的
.save()? -
@The_Cthulhu_Kid 代码按要求。还有一个 .js 文件,其中表单被序列化为 json,但在此之前它会中断
-
干杯我今天早上去看看。
-
为什么要拆分保存视图?
-
@The_Cthulhu_Kid 感谢您的观看!在我完成教程之前,我什至不知道这可以完成,但它是为了减少代码。有一个案例创建和案例更新视图。他们基本上做同样的事情,所以拆分这部分允许我为两个视图重用这部分代码