【问题标题】:Rendering images in Django ModelForm instead of __str__ representation在 Django ModelForm 中渲染图像而不是 __str__ 表示
【发布时间】:2021-04-28 10:14:00
【问题描述】:

我有以下 django 模型/表单/视图/html 设置。 所以我在 html 中渲染 InputFileForm,用户应该从下拉列表中选择一个 face_file,该文件保存在 Face 模型中(通过夹具预加载)。我希望在下拉列表中呈现 face_file 图像(或者单选也可以),而不是图像 str 名称 - 因为它目前看起来如下所示:

Image of current dropdown

简而言之:我希望在下拉菜单中呈现图像,而不是“Face 1”、“Face 2”...

提前感谢您的帮助!

class Face(models.Model):
    face_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=64)
    face_file = models.ImageField(upload_to='../media/faces', blank=True, null=True)

    def __str__(self):
        return self.name

class InputFile(models.Model):
    input_id = models.AutoField(primary_key=True)
    input_flatlay_file = models.ImageField(upload_to='../media/flatlays', blank=True, null=True)
    input_face_file = models.ForeignKey(Face, null=True, blank=True, on_delete=models.CASCADE, related_name="inputs_using_this_face")
    input_user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE, related_name="user_inputs")



class Prediction(models.Model):
    prediction_id = models.AutoField(primary_key=True)
    prediction_inputs = models.ForeignKey(InputFile, null=True, blank=True, on_delete=models.CASCADE, related_name="prediction_inputs")
    output_lookbook_file = models.ImageField(upload_to='../media/lookbooks', blank=True, null=True)
    prediction_user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE, related_name="user_predictions")



我有一个用于 InputFile 的 ModelForm:

class MyModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return mark_safe('<img src="%s">' %obj.face_file.url)


class InputFileForm(forms.ModelForm): 
    class Meta: 
        model = InputFile 
        fields = ['input_flatlay_file','input_face_file']
        widgets = {
                    'input_face_file': MyModelChoiceField(queryset=Face.objects.all()),
                }

在我看来.py:

def prediction(request):
    form=forms.InputFileForm()
    
    if request.method == 'POST':
        form = forms.InputFileForm(request.POST or None, request.FILES or None) 
        if form.is_valid():
            new_input = form.save(commit=False)
            new_input.input_user = request.user
            new_input.save()
            output_lookbook_file = util.prediction(new_input.input_flatlay_file, new_input.input_face_file.face_file)
            new_prediction = Prediction(output_lookbook_file = output_lookbook_file, prediction_user = request.user, prediction_inputs=new_input)
            new_prediction.save()
            return render(request, "modelgan/prediction.html", {"form": form, 
                                "new_input":new_input, "new_prediction": new_prediction })

        else:
            return render(request, "modelgan/prediction.html", {"form": form })

    return render(request, "modelgan/prediction.html", {"form": form })

在我的 html 中,我将 ModelForm 呈现如下:

    {% if user.is_authenticated %}

    <form action="{% url 'prediction' %}" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <form action="" method="POST">
  
            {% csrf_token %}
            {{ form.as_table  }}

            <input type="submit" value="Generate lookbook image">
        </form>
    </form>

【问题讨论】:

    标签: html django django-models django-forms


    【解决方案1】:

    您可以覆盖label_from_instance - 请参阅ModelChoiceField.iterator

    另见Overriding the default fields

    您可以执行以下操作:

    from django.utils.safestring import mark_safe
    from django.forms import ModelChoiceField
    
    class MyModelChoiceField(ModelChoiceField):
    
        def label_from_instance(self, obj):
            return mark_safe('<img width="60" src="%s">' % obj.face_file.url)
    
    
    class InputFileForm(forms.ModelForm):
    
        input_face_file = MyModelChoiceField(
            queryset=Face.objects.all(), required=False, 
            widget=forms.RadioSelect)
    
        class Meta: 
            model = InputFile 
            fields = ['input_flatlay_file','input_face_file']
    

    【讨论】:

    • 谢谢!我不得不将 "" 更改为 "" (以使其在 python 中工作,但不确定是否会在 HTML 中正确呈现);但是我最大的问题是我得到: TypeError: __init__() missing 1 required positional argument: 'queryset'
    • @JoSp90,你可以使用单引号!我更新了我的答案。
    • @JoSp90,同时将queryset=Face.objects.all()添加到MyModelChoiceField
    • 感谢@NKSM!但是,然后我得到以下“AttributeError:'ModelChoiceField'对象没有属性'to_field_name'”;好像这里没有使用小部件是正确的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    相关资源
    最近更新 更多