将非表单元素注入动态 Django 表单?

Inject non-form element into dynamic Django form?

是否可以将非表单元素注入到动态 Django 表单的上下文中?我有一个 "Delete user photos" 表单,我想在其中包含每个用户的缩略图,并在其下方带有 BooleanField 复选框和标签:

+------------+
|            |
|   photo    |
|            |
+------------+
[x]  Delete <username>'s photos

现在我知道如何创建动态复选框及其标签,但我不确定如何添加每个用户的照片。从我下面的代码可以看出,每个 HTML 输入标签的名称属性将包含用户的 ID,我将在用户提交表单时检查此属性以确定是否删除他们的照片。我想在 link 到用户个人资料照片的每个输入标签上方插入一个标签。图片标签的 "src" 属性将包含用户的 ID,该 ID 为他们的照片创建 link。有没有办法 "inject" 这个非表单图像标签进入这个动态表单的上下文,以便在每个复选框输入标签的正上方呈现图像标签?

谢谢。

# views.py
def remove_access_to_private_photos(request, template):
    if request.method == 'POST':
        form = RemovePrivatePhotoAccessForm(request.POST, this_user_id=request.user.id)
        if form.is_valid():
            for name, value in form.cleaned_data.items():
                if value == True:
                    # Profile links to User via a OneToOneField
                    this_user = Profile.objects.get(user_id=request.user.id)
                    other_user = Profile.objects.get(user_id=name)
                    this_user.remove_private_access(other_user_prof)
        return redirect('photos-home')
    else:
        form = RemovePrivatePhotoAccessForm(this_user_id=request.user.id)
    context = {'form': form}
    return render(request, template, context)

# models.py
class RemovePrivatePhotoAccessForm(forms.Form):
    def __init__(self, *args, **kwargs):
        this_user_id = kwargs.pop('this_user_id')
        super(RemovePrivatePhotoAccessForm, self).__init__(*args, **kwargs)
        user = User.objects.get(pk=this_user_id)
        user_prof = Profile.objects.get(user=user)
        other_user_id_list = user_prof.gave_private_access().values_list('user_id', flat=True)
        for id in other_user_id_list:
            other_user = User.objects.get(pk=id)
            self.fields[str(id)] = forms.BooleanField(required=False)
            self.fields[str(id)].label = mark_safe('<a href="/photos/delete/%s/%s">%s</a>') % (id, this_user_id, other_user.username)

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

    {% for field in form %}

        {# I'D LIKE TO PUT <IMG> TAG HERE #}
        {{ field }} Delete {{ field.label|safe }}'s photos

    {% endfor %}

    <input type="submit" value="Submit" />
</form>

表单字段只是一个 class,因此您可以在实例化时或实例化后添加所需的任何属性。鉴于此示例代码,您的观点保持不变。

# forms.py
from .models import Profile  # or whatever


class RemovePrivatePhotoAccessForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        user_id = kwargs.pop('user_id')

        user_profile = Profile.objects.get(pk=user_id)
        other_profiles = user_profile.gave_private_access()

        for profile in other_profiles:
            id = str(profile.id)
            field = forms.BooleanField(required=False)
            field.label = mark_safe('<a href="/photos/delete/%s/%s">%s</a>') % (id, user_profile.id, profile.username)
            field.photo = profile.photo
            self.fields[id] = field

        super(RemovePrivatePhotoAccessForm, self).__init__(*args, **kwargs)



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

    {% for field in form %}

        <img src="{{ field.photo.url }}" />
        {{ field }} Delete {{ field.label|safe }}'s photos

    {% endfor %}

    <input type="submit" value="Submit" />
</form>

这是我解决这个问题的方法。首先我创建了一个自定义模板标签:

    # photos/templatetags/photos_extras.py
    from django import template
    from django.contrib.auth.models import User
    from django.utils.safestring import mark_safe

    register = template.Library()

    @register.simple_tag
    def render_image(uid):
        user = User.objects.get(pk=uid)
        src_string = ''.join([
            '/photos/',
            user.username, '_',
            user.profile.image_id,
            '_thumb.jpg'])
        img_tag = ''.join([
            '<img src="',
            src_string,
            '" alt="',
            user.username,
            '" />'])
        return mark_safe(img_tag)

然后我将自定义模板标签插入到我的模板中。 field.name 包含所需用户的用户 ID,render_image returns 包含所需的 HTML img 标签。

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

    {% for field in form %}

        {% render_image field.name %}
        {{ field }} Delete {{ field.label|safe }}'s photos

    {% endfor %}

    <input type="submit" value="Submit" />
</form>