我想要做的是更改前端内联formset的界面,以便复选框可以与“直通”模型上的两个不同的外键字段相关联。基本上,我想将两个下拉列表折叠成一个复选框。
在models.py中:
class Food(models.Model):
name = models.CharField(max_length=10)
class Day(models.Model):
"""Days of the week: Sunday, Monday, Tuesday, etc."""
name = models.CharField(max_length=10)
class Meal(models.Model):
"""Breakfast, Lunch, Dinner"""
name = models.CharField(max_length=10)
class Plan(models.Model):
name = models.CharField()
foods = models.ManyToManyField('Food',related_name='plans')
days = models.ManyToManyField('Day',related_name='plans',through='Schedule')
meals = models.ManyToManyField('Meal',related_name='plans',through='Schedule')
class Schedule(models.Model):
plan = models.ForeignKey(Plan)
day = models.ForeignKey(Day)
meal = models.ForeignKey(Meal)
每个计划都有一套相关的食物,然后通过Schedule模型在某些日子与某些膳食相关联。
我希望有一个模型表格,用户可以在其中制定膳食计划,在那里他们会说出他们将在哪些日子吃的食物。例如,用户可以先从这组食物中选择苹果和香蕉,然后他们应该能够选择哪些日子他们将要吃苹果和香蕉。
我的观点是:
def plan_add(request):
form = forms.PlanForm();
ScheduleFormSet = inlineformset_factory(Plan, Schedule)
formset_schedule = ScheduleFormSet()
response = render(request, 'template.html', {
'form' : form,
'formset_schedule' : formset_schedule,
})
return response
这给了我一个可行的表单,但却是一个不友好的用户界面。对于要添加的每个计划,您必须首先从下拉列表中选择日期,然后从第二个下拉菜单中选择膳食。我想要的是7个表格行,每行中都有一个复选框,你只需要勾选你想要的日程表。因此,我想在Schedule模型上创建一个与两个外键字段相关联的表单字段(复选框):日和餐。
我想知道是否有一种“Django”方法来解决这个问题,可能是通过重写inlineformset_factory,或者如果想要这样做这么奇怪,我应该手动构建这个表单,手动验证它,以及解析并手动保存数据。
答案 0 :(得分:0)
这就是我最终做的事情。我没有使用inlineformset_factory,因为我无法获得内联表单集所需的控件。对于食物,我使用CheckboxSelectMultiple小部件指定了一个自定义ModelMultipleChoiceField,然后通过获取日期并循环遍历它们来为每一天做同样的事情。
class PlanForm(ModelForm):
foods = forms.ModelMultipleChoiceField(
queryset=Food.objects.all(),
required=False,
widget=forms.CheckboxSelectMultiple,
label = "Foods:")
def __init__(self, *args, **kwargs):
super(PlanForm, self).__init__(*args, **kwargs)
days = Day.objects.all()
for day in days:
self.fields[day.name] = forms.ModelMultipleChoiceField(
queryset=Meal.objects.all(),
required=False,
widget=forms.CheckboxSelectMultiple,
label = day.name)
class Meta:
model = Plan
fields = (['name','description','foods']+[day.name for day in Day.objects.all()])
这是获取我想要的表单的基本代码。然后,在您的模板中,您可以执行类似的操作,并添加自定义html:
{% for field in form %}
{{ field.label_tag }}
{% for choice in field %}
{{choice}}
{% endfor %}
{% endfor %}
我最终也使用了这个解决方案:http://schinckel.net/2013/06/14/django-fieldsets/来获取字段集,因此我可以为表单上的每个组执行不同的呈现。