Django ManyToManyField and Form



我正在编写我的第一个Django应用程序,在我的models.py文件中有两个类,Ingredient和Meal。一种食物有很多成分,你可以设定食物中每种成分的数量,这就是我的models.py:

class Ingredient(models.Model):
name = models.CharField(max_length=200)
class Meal(models.Model):
name = models.CharField(max_length=200)
ingredients = models.ManyToManyField(Ingredient, through='Recipe_Ingredient')
class Recipe_Ingredient(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
quantity = models.FloatField()
UNITY_CHOICES = (
('g', 'Gram(s)'),
('kg', 'Kilogram(s)'),
('l', 'Liter(s)'),
('cl', 'Centiliter(s)'),
)
quantityUnit = models.CharField(
max_length=2,
choices=UNITY_CHOICES,
default='g',
)

Recipe_Ingrent类是用于存储数量的ManyToMany关联表。

这里的问题是我不知道在这种情况下如何使用Forms。我有一个模板meal_edit.html,它调用form.py中的django表单。

要添加一种成分,我的表格很简单,比如:

from .models import Ingredient
class IngridientForm(forms.ModelForm):
class Meta:
model = Ingredient
fields = ('name',)

那么,我该如何制作一个表格,用多种成分和每种成分的数量创建一个食谱呢?

Django表单集:

从本质上讲,每个Ingredient都是较大表单中的一个表单(尽管,您的模板中只有一个<form标签。例如:

models.py:

class Ingredient(models.Model):
name = models.CharField(max_length=200)
class Meal(models.Model):
name = models.CharField(max_length=200)
class Recipe_Ingredient(models.Model):
meal = models.ForeignKey(Meal, on_delete=models.CASCADE)
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE) # Not sure what this is, but I'll leave that to you
ingredient = models.ForeignKey(Ingredient, on_delete=models.CASCADE)
quantity = models.FloatField()
UNITY_CHOICES = (
('g', 'Gram(s)'),
('kg', 'Kilogram(s)'),
('l', 'Liter(s)'),
('cl', 'Centiliter(s)'),
)
quantityUnit = models.CharField(
max_length=2,
choices=UNITY_CHOICES,
default='g',
)

forms.py:

from django import forms
from your_app import models
class IngredientForm(forms.ModelForm):
class Meta:
model = models.Recipe_Ingredient
fields = ['ingredient', 'quantity', 'quantityUnit']

IngredientFormset = forms.inlineformset_factory(models.Meal, models.Recipe_Ingredient, form=IngredientForm, extra=2)

views.py:

from your_app import forms, models
class YourMealModelView():
model = models.Meal
def get_context_data(self, *args, **kwargs):
context_data = super().get_context_data(**kwargs)
if self.request.method == 'POST':
context_data['ingredients_formset'] = forms.IngredientFormset(
self.request.POST,
instance=self.object,   # as in your Meal object
prefix='ingredients'
)
else:
context_data['ingredients_formset'] = forms.IngredientFormset(
instance=self.object, prefix='ingredients'
)
def form_valid(self, form):
# You can manipulate the formsets here as well:
context_data = self.get_context_data()
ingredients_formset = context_data['ingredients_formset']
meal = form.save()
for i_form in ingredients_formset:
delete = i_form.cleaned_data.get('DELETE')
if delete:
i_form.instance.delete()
continue
# do stuff and save
ingredient_recipe = i_form.save(commit=False)
ingredient_recipe.meal = meal
ingredient_recipe.save()

模板:

<form id="meal_form">
{% for field in form.fields %}
{{ field.label }}
{{ field }}
{% endfor %}
<table>
<thead>
{{ ingredients_formset.management_form }}
<tr>
<th>Ingredient</th>
<th>Quantity</th>
<th>Units</th>
<th>Delete?</th>
</tr>
</thead>
<tbody>
{% for i_form in ingredients_formset.forms %}
<tr id="{{ i_form.prefix }}">
{{ i_form.id }}
<td>{{ i_form.ingredient }}</td>
<td>{{ i_form.quantity }}</td>
<td>{{ i_form.quantityUnit }}</td>
<td>{% if i_form.instance.pk %}{{i_form.DELETE %}{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>

当然,我遗漏了很多东西,比如用javascript向表单集添加新项目,如何处理新餐与编辑现有餐,以及Django View要使用什么等等,但这给了你一个想法。

最新更新