Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django:使用多个外键为“through”模型自定义内联表单集_Django_Foreign Keys_Many To Many_Inline Formset - Fatal编程技术网

Django:使用多个外键为“through”模型自定义内联表单集

Django:使用多个外键为“through”模型自定义内联表单集,django,foreign-keys,many-to-many,inline-formset,Django,Foreign Keys,Many To Many,Inline 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.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)
每个计划都有一组相关的食物,然后通过时间表模型与特定日期的特定膳食相关联

我想有一个模型表单,用户可以创建一个膳食计划,在那里他们可以说他们将在哪天吃什么食物。例如,用户可以首先从食物中选择苹果和香蕉,然后他们应该能够选择在哪一天吃苹果和香蕉

我的看法是:

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个桌子行,每一行都有一个复选框,用于每顿饭,你只需选中你想放在时间表上的每顿饭的复选框。因此,我想使一个表单字段成为与日程模型上的两个外键字段关联的复选框:day和Dine


我想知道是否有Django方法来实现这一点,可能是通过重写inlineformset_工厂,或者这是一件非常奇怪的事情,我应该手动构建这个表单,手动验证它,手动解析并保存数据

以下是我最后做的事情。我没有使用inlineformset\u工厂,因为我无法获得内联表单集所需的控件。对于食物,我指定了一个带有复选框SelectMultiple小部件的定制ModelMultipleChiceField,然后通过获取日期并循环它们来完成每天的相同操作

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 %}

我还使用了这个解决方案:获取字段集,这样我就可以对表单上的每个组进行不同的渲染。

我喜欢手动构建表单。我认为django.forms是django框架中最脆弱、最不灵活、最不直观的部分。但是,您可能希望查看crispy表单或django表单向导以获得更好的UIT,这有助于您了解,在这种情况下,手动构建表单并不是一种不好的做法。我知道我可以做到这一点,我觉得这样做会让Django拥有很多强大的内置功能。你只需分解表单字段并按自己喜欢的方式放置它们,然后在客户端使用js收集数据并发送,就好像你正确使用了它一样。这样您就有了灵活性,但不会失去内置功能