【问题标题】:How to create Django form for a photo grid?如何为照片网格创建 Django 表单?
【发布时间】:2015-05-20 14:57:41
【问题描述】:

我正在尝试创建一个包含一到十张照片网格的 Django 表单。每张照片下方将有两个单选按钮组,一个指示查看者是否批准或拒绝该照片,第二组指示是否需要旋转照片。默认情况下会选中“批准”和“否”单选按钮:

(photo1)
Approve or reject?  Approve (x)  Reject( )
Rotate?  No (x)  Left ( )  Right ( )  Flip ( )

(photo2)
Approve or reject?  Approve (x)  Reject( )
Rotate?  No (x)  Left ( )  Right ( )  Flip ( )

(more photos...)

当查看者提交表单时,我想检查每张照片的名称(例如“foobar.jpg”)及其单选按钮,以确定它是被批准还是被拒绝以及是否需要旋转。照片名称都包含在一个 Python 列表中,我通过识别特定目录中的照片名称来填充该列表。

我不太明白如何定义一个表单,其中您有多个相同的表单“组件”(在本例中为照片加上单选按钮)都在同一个表单中。我也不明白如何将照片名称合并到表单中,以便显示照片。每张照片的名称都应该放在隐藏字段中吗?我在 Django 文档中没有看到任何解决这种情况的内容。

这似乎不是 Django Formsets 的工作。另外,我不想使用 ModelForms。感谢您的帮助。

以下是我的视图、表单和模板的缩略版本:

# views.py
def review_photos(request, template):
    if request.method == "POST":
        form = ReviewPhotosForm(request.POST)  # Need another arg?
        if form.is_valid():
            # Extract each photo name and examine its corresponding radio buttons.
            pass
    else:
        photo_names = list_all_files_in_dir("/path/to/photo/dir")
        form = ReviewPhotosForm(photo_names=photo_names)
    return render_to_response(template, locals(), context_instance=RequestContext(request))

# forms.py
class ReviewPhotosForm(forms.Form):
    DECISION_CHOICES = ( ('approve', 'Approve'), ('reject', 'Reject') )
    ROTATE_CHOICES = ( ('none,', 'None'), ('right', 'Right'), ('left', 'Left'), ('flip', 'Flip') )

    def __init__(self, *args, **kwargs):
        photo_names = kwargs.pop('photo_names')
        super(ReviewPhotosForm, self).__init__(*args, **kwargs)
        for name in photo_names:
            self.fields[???] = forms.ChoiceField(
                label = 'Approve or reject?',
                choices = self.DECISION_CHOICES,
                widget = forms.RadioSelect(renderer=widget.HorizontalRadioRenderer),
                initial = 'approve')

            self.fields[???] = forms.ChoiceField(
                label = 'Rotate?',
                choices = self.ROTATE_CHOICES,
                widget = forms.RadioSelect(renderer=widget.HorizontalRadioRenderer),
                initial = 'none')

# review_photos.html
<form action="." method="post">{% csrf_token %}
    <ul>
        <!-- How do I insert each photo's name into the form? -->
        {% for field in form %}
        <li>
            <img src="{{ photo_name }}" />  <!-- ??? -->
            <div id="decision">
                {{ ???.label }}
                {{ ??? }}
            </div>
            <div id="rotate">
                {{ ???.label }}
                {{ ??? }}
            </div>
        </li>
        {% endfor %}
    </ul>
    <input type="submit" value="Submit" />
</form>

【问题讨论】:

    标签: python django django-forms django-templates django-views


    【解决方案1】:

    相反,这正是表单集的工作:'多个相同的表单“组件”都在同一个表单中'正是它们的本质。

    class ReviewPhotosForm(forms.Form):
        DECISION_CHOICES = ( ('approve', 'Approve'), ('reject', 'Reject') )
        ROTATE_CHOICES = ( ('none,', 'None'), ('right', 'Right'), ('left', 'Left'), ('flip', 'Flip') )
    
        # hidden field to associate radio buttons with a photo
        photo_name = forms.CharField(widget=forms.HiddenInput)
    
        approve = forms.ChoiceField(
            label='Approve or reject?',
            choices=self.DECISION_CHOICES,
             widget=forms.RadioSelect(renderer=widget.HorizontalRadioRenderer),
            initial='approve')
    
        rotate = forms.ChoiceField(
            label='Rotate?',
            choices=self.ROTATE_CHOICES,
            widget=forms.RadioSelect(renderer=widget.HorizontalRadioRenderer),
            initial='none')
    

    查看:

    def review_photos(request, template):
        ReviewPhotosFormSet = formset_factory(ReviewPhotosForm, extra=0)
    
        if request.method == "POST":
            formset = ReviewPhotosFormSet(request.POST)
            if formset.is_valid():
                # list of photos and radio buttons is in formset.cleaned_data
                pass
        else:
            photo_names = list_all_files_in_dir("/path/to/photo/dir")
            initial_data = [{'photo_name': name} for name in photo_names]
    
            form = ReviewPhotosForm(initial=initial_data)
        return render(request template, {'formset': formset})
    

    模板:

    <form action="." method="post">{% csrf_token %}
        {{ formset.management_form }}
        <ul>
            {% for form in formset %}
            <li> {{ form.photo_name }}
                <img src="{{ form.photo_name.value }}" />
                <div id="decision">
                    {{ form.decision.label_tag }}
                    {{ form.decision }}
                    {{ form.decision.errors }}
                </div>
                <div id="rotate">
                    {{ form.rotate.label_tag }}
                    {{ form.rotate }}
                    {{ form.rotate.errors }}
                </div>
            </li>
            {% endfor %}
        </ul>
    </form>
    

    【讨论】:

    • 谢谢丹尼尔。我非常感谢你的帮助。 Django Formsets 文档让我感到困惑,因为它们指的是“同一页面上的多个表单”,我认为一个表单包含一个提交按钮。对我来说,这意味着使用表单集意味着会有多个提交按钮,而我的表单并非如此。您认为只有两个小错别字。一、视图需要从django.forms.formsets导入formset_factory。二、else块应该是“formset = ReviewPhotosFormSet(initial=...)”而不是“form = ReviewPhotosForm(...)”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-19
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    相关资源
    最近更新 更多