Django基于ForeignKey创建删除食谱食材表单出现AttributeError如何解决
问题分析
你的实现思路是正确的,动态接收外部参数筛选ModelChoiceField的查询集是Django表单实现关联数据筛选的标准方案。
报错的直接原因是表单类初始化调用父类构造方法时没有对参数解包:你在forms.py中写的是super(RemoveIngredientForm, self).__init__(args, kwargs),直接把args元组作为第一个参数传给了父类的构造方法,父类Form默认第一个参数是表单数据,后续处理时会调用数据的get()方法,而元组没有get属性,就触发了对应报错。
其他需要修正的问题
- 表单
__init__中没有提前把自定义参数recipe_pk从kwargs中取出,直接传入父类会触发参数不识别的错误 - 视图中实例化表单的传参逻辑错误,POST和GET场景的参数传递都不符合要求
- 表单字段名是
to_remove,但POST处理时取的是picked,字段名不匹配会取不到值 - 模板没有加CSRF令牌,POST请求会被Django安全拦截
修正后的完整代码
forms.py
class RemoveIngredientForm(forms.Form): to_remove = forms.ModelChoiceField(queryset=Ingredient.objects.all()) def __init__(self, *args, **kwargs): # 先把自定义参数从kwargs里弹出,避免传给父类报错 recipe_pk = kwargs.pop('recipe_pk') super().__init__(*args, **kwargs) recipe = Recipe.objects.get(pk=recipe_pk) self.fields['to_remove'].queryset = Ingredient.objects.filter(recipe=recipe)
views.py
def remove_ingredients(request, **kwargs): recipe_pk = kwargs['recipe_pk'] recipe = Recipe.objects.get(pk=recipe_pk) if request.method == 'POST': # 按参数要求传入表单数据和自定义参数 form = RemoveIngredientForm(request.POST, recipe_pk=recipe_pk) if form.is_valid(): to_remove = form.cleaned_data.get('to_remove') to_remove.delete() # 这里可以替换为你自己的食谱详情页路由名 return redirect('recipe_detail', pk=recipe_pk) else: # GET请求仅传入自定义筛选参数 form = RemoveIngredientForm(recipe_pk=recipe_pk) context = { 'recipe': recipe, 'form': form } return render(request, 'food/remove_ingredients.html', context=context)
food/remove_ingredients.html
<h1>Removing ingredients from {{recipe.name}}</h1> <form method='POST'> {% csrf_token %} {{ form.as_p }} <input type='submit' value='提交删除'> </form>
内容的提问来源于stack exchange,提问作者AstronautCharlie
相关产品推荐
相关产品推荐

