从外键创建 Django 表单
Create Django Form from ForeignKey
我正在尝试创建一个简单的 Django 应用程序,允许用户创建和编辑包含成分的食谱。
models.py
class Recipe(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
class Ingredient(models.Model):
api_id = models.IntegerField(primary_key=True) # id in Spoonacular database
name = models.CharField(max_length=100) # human-readable name
units = models.CharField(max_length=10) # unit of measure (e.g. 'oz', 'lb'), includes '' for 'number of'
amt = models.PositiveIntegerField() # number of units
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
我有一个详细视图,显示给定食谱的成分,以及添加和删除成分的按钮。食谱的主键在 URL.
view of detail page with add/remove ingredient buttons
我正在努力做到这一点,以便当用户点击 'Remove Ingredients' 按钮时,它会将他们重定向到一个表单,在该表单中他们可以 select 他们想要的给定食谱中的哪些成分去掉。这是我无法开始工作的部分。据我所知,这需要一个带有查询集的 ModelChoiceField,其中成分的外键与配方的主键匹配 ('recipe_pk')。似乎我需要通过构造函数中的 **kwargs 将给定配方的主键传递到表单中,然后让表单 select 具有适当的成分。但是,当我尝试呈现模板时,这给了我一个 AttributeError
和描述 'tuple' object has no attribute 'get'
。这是一个截图:
AttributeError
这是创建此类表单的正确方法吗?如果是,知道哪里出了问题吗?
forms.py
# Trying to create a form where a user can select any number of Ingredients
# associated with the Model
class RemoveIngredientForm(forms.Form):
to_remove = forms.ModelChoiceField(queryset=Ingredient.objects.all())
def __init__(self, *args, **kwargs):
super(RemoveIngredientForm, self).__init__(args, kwargs)
recipe = Recipe.objects.get(pk=kwargs['recipe_pk'])
self.fields['to_remove'].queryset = Ingredient.objects.filter(recipe=recipe)
views.py
...
def remove_ingredients(request, **kwargs):
"""
GET: list of existing ingredients
POST: remove selected ingreident from model
"""
if request.method == 'POST':
form = RemoveIngredientForm(request.POST, kwargs=kwargs)
if form.is_valid():
picked = form.cleaned_data.get('picked')
return HttpResponse('How did I get here?') # Haven't gotten to this point yet
recipe = Recipe.objects.get(pk=kwargs['recipe_pk']) #'recipe_pk' is the primary key of the Recipe and lives in the URL
try:
ingredients = Ingredient.objects.filter(recipe=recipe)
except Ingredient.DoesNotExist:
ingredients = None
form = RemoveIngredientForm(**kwargs)
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'>
{{ form.as_p }}
<input type='submit' value='submit'>
</form>
选择域不起作用,因为它需要一个选择字典。您想要做的是显示特定食谱的成分列表视图,每个成分旁边都有一个删除按钮,该按钮调用该特定成分的删除视图。所以你用食谱的 pk 调用你的 deleteingredients url。然后在您的函数中,您将成分的查询集传递给该食谱 pk 到上下文中。然后在您的模板中使用一个按钮渲染每种成分,该按钮使用该成分的 pk 调用该特定成分的删除。所以根本不需要表格。您只需要另一个删除成分然后重定向到食谱的视图。
我正在尝试创建一个简单的 Django 应用程序,允许用户创建和编辑包含成分的食谱。
models.py
class Recipe(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
class Ingredient(models.Model):
api_id = models.IntegerField(primary_key=True) # id in Spoonacular database
name = models.CharField(max_length=100) # human-readable name
units = models.CharField(max_length=10) # unit of measure (e.g. 'oz', 'lb'), includes '' for 'number of'
amt = models.PositiveIntegerField() # number of units
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
我有一个详细视图,显示给定食谱的成分,以及添加和删除成分的按钮。食谱的主键在 URL.
view of detail page with add/remove ingredient buttons
我正在努力做到这一点,以便当用户点击 'Remove Ingredients' 按钮时,它会将他们重定向到一个表单,在该表单中他们可以 select 他们想要的给定食谱中的哪些成分去掉。这是我无法开始工作的部分。据我所知,这需要一个带有查询集的 ModelChoiceField,其中成分的外键与配方的主键匹配 ('recipe_pk')。似乎我需要通过构造函数中的 **kwargs 将给定配方的主键传递到表单中,然后让表单 select 具有适当的成分。但是,当我尝试呈现模板时,这给了我一个 AttributeError
和描述 'tuple' object has no attribute 'get'
。这是一个截图:
AttributeError
这是创建此类表单的正确方法吗?如果是,知道哪里出了问题吗?
forms.py
# Trying to create a form where a user can select any number of Ingredients
# associated with the Model
class RemoveIngredientForm(forms.Form):
to_remove = forms.ModelChoiceField(queryset=Ingredient.objects.all())
def __init__(self, *args, **kwargs):
super(RemoveIngredientForm, self).__init__(args, kwargs)
recipe = Recipe.objects.get(pk=kwargs['recipe_pk'])
self.fields['to_remove'].queryset = Ingredient.objects.filter(recipe=recipe)
views.py
...
def remove_ingredients(request, **kwargs):
"""
GET: list of existing ingredients
POST: remove selected ingreident from model
"""
if request.method == 'POST':
form = RemoveIngredientForm(request.POST, kwargs=kwargs)
if form.is_valid():
picked = form.cleaned_data.get('picked')
return HttpResponse('How did I get here?') # Haven't gotten to this point yet
recipe = Recipe.objects.get(pk=kwargs['recipe_pk']) #'recipe_pk' is the primary key of the Recipe and lives in the URL
try:
ingredients = Ingredient.objects.filter(recipe=recipe)
except Ingredient.DoesNotExist:
ingredients = None
form = RemoveIngredientForm(**kwargs)
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'>
{{ form.as_p }}
<input type='submit' value='submit'>
</form>
选择域不起作用,因为它需要一个选择字典。您想要做的是显示特定食谱的成分列表视图,每个成分旁边都有一个删除按钮,该按钮调用该特定成分的删除视图。所以你用食谱的 pk 调用你的 deleteingredients url。然后在您的函数中,您将成分的查询集传递给该食谱 pk 到上下文中。然后在您的模板中使用一个按钮渲染每种成分,该按钮使用该成分的 pk 调用该特定成分的删除。所以根本不需要表格。您只需要另一个删除成分然后重定向到食谱的视图。