繁体   English   中英

如何将图像文件保存在 Django 中

[英]how can i save images files in Django

  1. 我想以一种形式接收多个图像组并保存它们。 我想用相同的主标题和不同的标题保存每个图像组。 如何在 views.py 上保存和定位图像文件?

  2. 我没有将表单交给 views.py 的请求,因为用户可以添加和删除内容。 当我想接收我不知道有多少的数据时,有没有办法使用表单标签?

在此处输入图像描述

视图.py

def debate_create(request):
    if request.method == "POST":
        content = request.POST.items()
        for k,v in content:
            if k == 'sup_title':
                sup_title = SuperTitle()
                sup_title.author = request.user
                sup_title.super_title = v
                sup_title.save()
                sup_title_id = sup_title.id
            elif 'img' not in k and 'opt' not in k and 'section' in k:
                sub_title = Subtitle()
                sub_title.super_title = get_object_or_404(SuperTitle, pk = sup_title_id)
                sub_title.sub_title = v
                sub_title.save()
            elif 'img' in k and v != '':
                stg = Images()
                # imgs = request.FILES.getlist("?????")
                # for image in imgs
                stg.sub_title = get_object_or_404(Subtitle, pk = sub_title.id)
                stg.save()
            elif 'section' in k and 'opt' in k:
                opt = SelectOption()
                opt.sub_title = get_object_or_404(Subtitle, pk = sub_title.id)
                opt.option = v
                opt.save()
        return render(request, 'polls/test.html')
    else:
        pass

html

<form method="POST" id="debate_form" action="{% url 'polls:debate_create' %}">
        {% csrf_token %}
        <input type='text' name='sup_title' placeholder='제목'>
        <div id="form_container">
            <section id='section_1'>
                <input type="text" name="section_1">
                <input type="file" name="img_section_1" multiple>
                <div id="section_1_div">
                    <input type="text" name="section_1_opt_1" value="찬성">
                    <input type="text" name="section_1_opt_2" value="반대">
                </div>
                <input type="button" value="선택지 추가하기" onclick='add_option(this.id)' id="section_1">
                <input type="button" value="선택지 삭제하기" onclick='sub_option(this.id)' id="section_1">
            </section>
        </div>
        <input type="button" value='질문 추가하기' onclick='add_content()'>
        <input type="button" value='질문 삭제하기' onclick='sub_content()'>
        <input type="submit">
    </form>

在 Django 中当然有一种方法可以实现这一点,它被称为model 表单集

假设您的模型是这样定义的

# models.py
from django.db import models

class SuperTitle(models.Model):
    super_title = models.CharField(max_length=50)
    author = models.ForeignKey(User, on_delete=models.PROTECT)

class Subtitle(models.Model):
    super_title = models.ForeignKey(SuperGroup, on_delete=models.CASCADE)
    subtitle = models.CharField(max_length=50)
    image = models.ImageField(upload_to='path/to/uploads/')
    # I changed opt from a model to a field of Subtitle, 
    # since it has only 2 values in your example.
    # Feel free to change it back. 
    opt = models.IntegerField(choices=[(1,"찬성"), (2, "반대")])

那么在你看来

# views.py
from django import forms
from .models import SuperTitle, Subtitle

def debate_create(request):
    SuperTitleForm = forms.modelform_factory(SuperTitle, fields=['super_title'])
    SubtitleFormSet = forms.modelformset_factory(Subtitle, fields=['subtitle', 'image', 'opt'])
    if request.method == 'POST':
        super_title_form = SuperTitleForm(request.POST)
        # NOTE uploaded files are available in request.FILES
        subtitle_formset = SubtitleFormSet(request.POST, request.FILES, queryset=Subtitle.objects.none())
        if super_title_form.is_valid() and subtitle_formset.is_valid():
            super_title = super_title_form.save()
            subtitles = subtitle_forms.save(commit=False)
            for subtitle in subtitles:
                subtitle.super_title = super_title
            Subtitle.objects.bulk_create(subtitles)
    else:
        super_title_form = SuperTitleForm()
        subtitle_formset = SubtitleFormSet(queryset=Subtitle.objects.filter(super_title__author=request.user))
    context = {
        'super_title_form': super_title_form,
        'subtitle_formset': subtitle_formset,
    }
    return render(request, 'polls/test.html', context)

请注意,我将queryset=Subtitle.objects.none()传递给 formset。 这将使 formset 只处理新的字幕。 如果您想编辑甚至删除现有字幕,请将查询集更改为,例如queryset=Subtitle.objects.filter(super_title__author=request.user) Django 建议订购查询集。

而且您可能需要对super_title_form做类似的事情,以便它知道您正在编辑哪个 super_title。

另请注意,手动渲染表单集时有两个必需的隐藏字段:

{{ subtitle_formset.management_form.TOTAL_FORMS }}
{{ subtitle_formset.management_form.INITIAL_FORMS }}

就个人而言,我喜欢将这两个放在{% csrf_token %}旁边,以防忘记它们。

已编辑:您的第一个问题还有一件事

您可以自定义图像存储路径,如下所示

def subtitle_image_path(instance, filename):
    return f'uploads/{instance.super_title.id}/{filename}'
class Subtitle(models.Model):
    ..
    image = models.ImageField(upload_to=subtitle_image_path)

并且 django 会在您调用form.save() (或subtitle.save()在这种情况下)时自动将图像保存到uploads/1/img01.png

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM