Django形式为多对多模型。如何从视图/模板填写表单?

时间:2014-02-06 10:27:18

标签: django django-forms django-templates django-orm

所以我有两个通过Many-to-many关系相关的模型。由于我需要一个额外的文件,我使用额外的模型CategoryByDay

基本上我在我的应用程序中想要的是创建一个习惯或日常列表,记录我今天要做的各种事情。所以我想将每个新的一天与每个类别联系起来并记录它的状态(如果已完成1,如果不是0)。我正在使用CharField,因为后来我想将其他内容记录为书籍阅读等,这与此无关

models.py

from django.db import models

class Day(models.Model):
    name = models.CharField(max_length=8)
    date = models.DateField()

    def __unicode__(self):
        return self.name

class Category(models.Model):
    name = models.CharField(max_length=100)
    categoryBD = models.ManyToManyField(Day, through='CategoryByDay')

    def __unicode__(self):
        return self.name

class CategoryByDay(models.Model):
    day = models.ForeignKey(Day)
    category = models.ForeignKey(Category)
    status = models.CharField(max_length=64)

在我的html中,我想显示一个类别列表及其附近的表单,其中只会发布状态,日期以及类别将自动填写。现在我不知道该怎么做。这是我到目前为止所看到的,在一些论坛上阅读,您可以从视图传递额外的数据(这不起作用,并形成要求我填写日期和类别形式)

views.py

def today(request):
    if request.method == 'POST':
#... POST validation here, not relevant
    else:
        day = datetime.date.today().strftime("%d/%m/%y")
        categories_list = Category.objects.all()
        category_form_list = []
# I am doing this strange list, because later in template I had problem
# accessing list through iteration like forloop.counter. 
# I will access it via for x,y in pair
        for category in categories_list:
            data = {'day': day,
            'category': category.name,}
            form = CategoryByDayForm(data)
            #So I tried adding data to form, it didn't work and can be ignored
            part = [category, form]
            category_form_list.append(part)
        context = { 't': t,
        'category_form_list': category_form_list,}
        return render(request, 'today/today.html', context)

这是我的表格,我应该早点补充一下。

形成py

class CategoryByDayForm(forms.ModelForm):
    status = forms.CharField(max_length=64, initial="0")
    day = forms.ModelMultipleChoiceField(queryset=Day.objects.all())
    category = forms.ModelMultipleChoiceField(queryset=Category.objects.all())
    class Meta:
        model = CategoryByDay

现在,在表单中,我不确定我应该在日期和类别中使用哪种表单类型。也许我应该以某种方式省略它?

最后模板:

今天html

#...
    <ul>
        {% for category, form in category_form_list %}
            <li>                   
                {{ category.name }}
                <form action="" method="post">
                    {% csrf_token %}
                    {{ form.non_field_errors}}
                    <div class="status">
                        {{ form.status.errors}}
                        {{ form.status }}
                        <input type="submit" value="Submit" />
                    </div>
                </form>
            </li>
        {% endfor %}
    </ul>
#...

这是有效的,只显示一个表单status但是当我点击提交并以我的方式调试它时,我有错误,我没有填写日期和类别表单。

有人可以告诉我如何继续吗?

2 个答案:

答案 0 :(得分:2)

我设法让它发挥作用。

对于未来的任何人偶然谷歌搜索和访问这个页面是我做的。

1.更改CategoryByDayForm的形式,使其仅接受状态并排除日期和类别

forms.py

from django import forms
from today.models import CategoryByDay, Category, Day

class CategoryByDayForm(forms.ModelForm):
    status = forms.CharField(max_length=64, initial="0")
    class Meta:
        model = CategoryByDay
        exclude = ['day', 'category']
  1. 在模板中,添加隐藏表单输入发送当前类别迭代:
  2. today.html

    #...
    {% for category, form in category_form_list %}
                    <li>                   
                        {{ category.name }}
                        <form action="" method="post">
                            {% csrf_token %}
                            {{ form.non_field_errors}}
                            <input type="hidden" value="{{ category.name }}" name="category">
                            <div class="status">
                                {{ form.status }}
                                <input type="submit" value="Submit" />
                            </div>
                        </form>
                    </li>
                {% endfor %}
    # ...
    

    最后,在视图中,我操纵了我得到的表单,所以我添加了缺少的元素(从表单我有状态,我仍然需要设置日期和类别)

    views.py

    def today(request):
        t = datetime.date.today().strftime("%d/%m/%y")
        day = Day.objects.filter(name=t)
        if request.method == 'POST':
                form = CategoryByDayForm(request.POST)
            if form.is_valid():
                category_status = form.save(commit=False)
                category_status.day = day[0]
                category_name = request.POST['category']
                category_status.category = Category.objects.filter(name=category_name)[0]
                category_status.save()
                form.save_m2m()
    

    ...

    希望将来可以帮助某人。

答案 1 :(得分:1)

另一种解决方案 views.py:

class ViewIndex(TemplateResponseMixin, View):
    template_name = 'frontend/view_index.html'

    def dispatch(self, request, *args, **kwargs):
       FS = modelformset_factory(CategoryByDay, extra=1)
       queryset = CategoryByDay.objects.filter(day__date=datetime.date.today())

       if request.method == 'POST':
           formset = FS(request.POST, request.FILES)

           if formset.is_valid():
               formset.save()
               formset = FS(queryset=queryset)

       else:
           formset = FS(queryset=queryset)


       return self.render_to_response({'formset':formset})

frontend / view_index.html:

{% extends 'base.html' %}
{% block content_main %}
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ formset.management_form }}
    {% for form in formset %}
       {{ form }}
       <hr/>
    {% endfor %}

    <input type="submit">
</form>
{% endblock %}

和urls.py

urlpatterns = patterns('',
   url(r'^$', ViewIndex.as_view(), name='view_index'),
)