【问题标题】:Inject non-form element into dynamic Django form?将非表单元素注入动态 Django 表单?
【发布时间】:2016-02-25 15:20:43
【问题描述】:

是否可以将非表单元素注入到动态 Django 表单的上下文中?我有一个“删除用户照片”表单,我想在其中包含每个用户的缩略图,并在其下方添加一个 BooleanField 复选框和标签:

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

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

谢谢。

# 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>

【问题讨论】:

  • 表单只是一个类。它可以具有您想通过 args 或 kwargs 分配的任何属性。
  • 对,但我不明白在图像不属于表单上下文的情况下如何渲染图像。我的模板是说,“for field in form...”如果图像不是“form.field”或“form.label”,你将如何将它注入到动态表单中?
  • 我给你加个例子。

标签: django django-models django-forms django-templates


【解决方案1】:

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

# 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>

【讨论】:

  • 谢谢布兰登,但这似乎不起作用。由于这是一个动态表单,因此每个用户的照片都可以删除一个字段和字段标签。设置 self.user_photo 只捕获列表中最后一个用户的照片,而不是列表中每个用户的照片。
  • 对不起,我误解了你的问题。我已经为你更新了答案
  • 感谢 Brandon,但我无法让您的代码正常工作。如果我在表单内部进行调试和中断,我可以看到 field.photo 被设置但模板没有呈现它。我在浏览器中做了“查看源代码”,但它不存在。今天下午我确实设法使用自定义模板标签自己解决了这个问题。我会尽快发布我的代码。
【解决方案2】:

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

    # 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 返回所需的 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多