如何在 Django 模板中使用表单集的模型表单实例

How to use model form instances of a formset in Django template

我正在尝试访问表单集中的表单实例,但它不起作用。我可以使用变量符号访问它们,如 {{ form }},但不能在代码中,如 {% url 'section' form.instance.pk %}。我需要遍历表单集中的表单以及相应的模型实例。

我的看法:

# views.py

def sec(request, companyurl):
    company = get_if_exists(Company, author=request.user)

    SectionFormSet = modelformset_factory(Section, form=SectionForm, can_delete=True)
    sections = Section.objects.filter(company=company).order_by('order')
    formset = SectionFormSet(request.POST or None,
                             initial=[{'company': company}],
                             queryset=sections

    context = {
        'sections': sections,
        'formset': formset,
    }
    return render(request, 'questions/sections.html', context)

我的模型:

# models.py

class Section(models.Model):

    section = models.CharField(max_length=100)
    company = models.ForeignKey(Company, on_delete=models.CASCADE)
    order = models.PositiveIntegerField(default=1000000)
    show = models.BooleanField(default=True)

    def __str__(self):
        return self.section

我的表单(我使用的是 django-crispy 表单):

# forms.py
class SectionForm(forms.ModelForm):
    class Meta:
        model = Section
        fields = ['company', 'section', 'show', 'order']
        labels = {
            'section': '',
            'show': 'Show'
        }
    def __init__(self, *args, **kwargs):
        super(SectionForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Div(
                Div(HTML("##"), css_class = 'my-handle col-auto'),
                Div('section', css_class='col-3'),
                Div('show', css_class = 'col-auto'),
                Div('DELETE', css_class = 'col-auto'),
                Field('company', type='hidden'),
                Field('order', type='hidden'),
                css_class='row',
            ),
        )

我的模板(这是问题所在):

<form action="#" method="post">
  {% csrf_token %}

  {{ formset.management_form }}

  <div id="simpleList" class="list-group">


  {% for fo in formset %}

    <div class="list-group-item hold">

      {% crispy fo %}

      <!-- TESTING TO SEE IF THIS WORKS, AND IT DOES! -->
      {{ fo.instance }} + {{ fo.instance.pk }} + {{ fo.instance.section }}

      <!-- THE PROBLEM OCCURS WHEN THIS IS ADDED -->
      <a href="{% url 'section' fo.instance.pk fo.instance.section %}">
        {{ fo.instance }}
      </a>
      <!-------------------------------------------->

      <input type="hidden" name="order" value="{{ section.pk }}">

      {% for hid in fo.hidden_fields %}
        {{ hid }}
      {% endfor %}

    </div>

  {% endfor %}

  <button type="submit" class="btn btn-outline-primary">Save changes</button>

</form>

当我添加 <a href="{% url 'section' fo.instance.pk fo.instance.section %}>link</a> 行时,我得到

Reverse for 'section' with arguments '(None, '')' not found. 1 pattern(s) tried: ['section/(?P<pk>[0-9]+)/(?P<section>[^/]+)\Z']

错误很明显。 fo.instance.pkNonefo.instance.section 是一个空字符串。然而,当我删除锚标记时,上面的行出现并显示了这两个的正确值。我 认为 我知道 {{ }}{% %} 的区别,我想我知道模型表单实例是如何绑定到模型的,但我是遗漏了一些东西。

感谢您的帮助。

表单集创建空白表单

当我打印结果时,答案就在眼前。最后一个表格,一个空白, 当然 给了我 None 和一个空字符串,因为它没有数据可以填充它。因此,简单的解决方案是在尝试使用信息形成 url 之前检查这一点。因此,这与 {{ }}{% %} 之间的差异也没有任何关系,也不构成实例。

{% for fo in formset %}

    <div class="list-group-item hold">

      {% crispy fo %}

      <!-- TESTING TO SEE IF THIS WORKS, AND IT DOES! -->
      {{ fo.instance }} + {{ fo.instance.pk }} + {{ fo.instance.section }}

      <!-- THE PROBLEM OCCURED WHEN THIS WAS ADDED -->
      <!-- THE SIMPLE SOLUTION: --------------------->
      {% if fo.instance.pk %}
         <a href="{% url 'section' fo.instance.pk fo.instance.section %}">
           {{ fo.instance }}
         </a>
      {%  endif %}
      <!-------------------------------------------->

      <input type="hidden" name="order" value="{{ section.pk }}">

      {% for hid in fo.hidden_fields %}
        {{ hid }}
      {% endfor %}

    </div>

  {% endfor %}

  <button type="submit" class="btn btn-outline-primary">Save changes</button>

</form>