如何循环表单字段选项并显示关联的模型实例字段

siz*_*ght 12 python django django-templates django-forms

我有一个带有多选字段的ModelForm.选项是属于特定俱乐部的远足者的填充实例.

我想通过在第1列包含复选框的表格中显示选项来自定义表单显示的方式,还有一些列显示每个hiker的详细信息.例如,列是(checboxes,名称,年龄,最喜欢的远足径).

我不知道如何处理这个问题.如何使用模板中的关联模型实例字段访问和显示表单字段选项.有人知道Django这样做的方法吗?

#models.py
class Club(models.Model):
    title = models.CharField()
    hikers = models.ManyToManyField(Hikers)

class Hiker(models.Model):
    name = models.CharField()
    age = models.PositiveIntegerField()
    favourite_trail = models.CharField()

#forms.py
class ClubForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        club_pk = kwargs['club_pk']
        del kwargs['club_pk']
        super(ClubForm, self).__init__(*args, **kwargs)
        choices = [(ts.pk, ts.name) for hiker in Club.objects.filter(pk=club_pk)]
        self.fields['hikers'].choices = choices

    class Meta:
        model = Club
        fields = ('hikers',)
        widgets = {'hikers': forms.CheckboxSelectMultiple}
Run Code Online (Sandbox Code Playgroud)

Ber*_*ant 39

如果您在HTML模板中定义整个表单,则最简单.您应该能够在模板中迭代字段的值,如下所示:

{% for value, text in form.hikers.field.choices %}
    {{ value }}: {{ text }}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)


Arm*_*nce 10

尝试此解决方案:

<ul>
{% for choice in form.my_choice_field.field.choices %}
  <li>
    <input type="radio" name="my_choice_field" value="{{choice.0}}"
      {% ifequal form.my_choice_field.data choice.0 %} 
         checked="checked"
      {% endifequal %}/>
    <label for="">{{choice.1}}</label>
 </li>
{% endfor %}
</ul>
Run Code Online (Sandbox Code Playgroud)

看到这个链接:http://www.ilian.io/django-forms-choicefield-and-custom-html-output/


sed*_*nym 8

这是令人惊讶的棘手,但你可以用它做的ModelMultipleChoiceField,CheckboxSelectMultiple和自定义模板过滤器.表单和窗口小部件类大部分都在那里,但模板过滤器确定了哪个窗口小部件为您提供查询集中的每个实例.见下文...

通用解决方案

# forms.py
from django import forms
from .models import MyModel

class MyForm(forms.Form):
    my_models = forms.ModelMultipleChoiceField(
                                      widget=forms.CheckboxSelectMultiple,
                                      queryset=None) 

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['my_models'].queryset = MyModel.objects.all()


# myapp/templatetags/myapp.py
from django import template
from copy import copy

register = template.Library()

@register.filter
def instances_and_widgets(bound_field):
    """Returns a list of two-tuples of instances and widgets, designed to
    be used with ModelMultipleChoiceField and CheckboxSelectMultiple widgets.

    Allows templates to loop over a multiple checkbox field and display the
    related model instance, such as for a table with checkboxes.

    Usage:
       {% for instance, widget in form.my_field_name|instances_and_widgets %}
           <p>{{ instance }}: {{ widget }}</p> 
       {% endfor %}
    """
    instance_widgets = []
    index = 0
    for instance in bound_field.field.queryset.all():
         widget = copy(bound_field[index])
         # Hide the choice label so it just renders as a checkbox
         widget.choice_label = ''
         instance_widgets.append((instance, widget))
         index += 1
    return instance_widgets


# template.html
{% load myapp %}     
<form method='post'>
   {% csrf_token %}     
   <table>
       {% for instance, widget in form.job_applications|instances_and_widgets %}
           <tr>
               <td>{{ instance.pk }}, {{ instance }}</td>
               <td>{{ widget }}</td>
           </tr>
       {% endfor %}
   </table>
   <button type='submit' name='submit'>Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)

具体到你

如果您调整表单,它应该工作:

class ClubForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        cluk_pk = kwargs.pop('club_pk')
        super(ClubForm, self).__init__(*args, **kwargs)
        self.fields['hikers'].queryset = Club.objects.filter(pk=club_pk)

    class Meta:
        model = Club
        fields = ('hikers',)
        widgets = {'hikers': forms.CheckboxSelectMultiple}
Run Code Online (Sandbox Code Playgroud)