【问题标题】:Django formset creates multiple inputs for multiple image uploadDjango formset 为多个图像上传创建多个输入
【发布时间】:2020-07-12 14:42:22
【问题描述】:

我正在尝试创建一个像这样的简单帖子共享表单。

我正在使用表单集进行图片上传。但这给了我多个输入,如您所见。每个输入也可以选择单个图像。但我正在尝试使用单个输入上传多张图片。

views.py

def share(request):

    ImageFormSet = modelformset_factory(Images,
                                        form=ImageForm, extra=3)
    # 'extra' means the number of photos that you can upload   ^

    if request.method == 'POST':
        postForm = PostForm(request.POST)
        formset = ImageFormSet(request.POST, request.FILES,
                               queryset=Images.objects.none())

        if postForm.is_valid() and formset.is_valid():
            post = postForm.save(commit=False)
            post.author = request.user
            post.save()

            for form in formset.cleaned_data:
                # this helps to not crash if the user
                # do not upload all the photos
                if form:
                    image = form['image']
                    photo = Images(post=post, image=image)
                    photo.save()

            return redirect("index")

        else:
            print(postForm.errors, formset.errors)
    else:
        postForm = PostForm()
        formset = ImageFormSet(queryset=Images.objects.none())
    return render(request, "share.html", {"postForm": postForm, 'formset': formset})

share.html

 <form  method="POST" id="post-form" class="post-form js-post-form" enctype="multipart/form-data">
            {% csrf_token %}
             {{ formset.management_form }}
                {% for form in formset %}
                    {{ form }}
                {% endfor %} 
   </form>

如果你需要,forms.py

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ["title", "content"]

    def __init__(self, *args, **kwargs):
        super(PostForm, self).__init__(*args, **kwargs)
        self.fields['title'].widget.attrs.update({'class': 'input'})
        self.fields['content'].widget.attrs.update({'class': 'textarea'})


class ImageForm(forms.ModelForm):
    image = forms.ImageField(label='Image')

    class Meta:
        model = Images
        fields = ('image', )

        def __init__(self, *args, **kwargs):
            self.fields['image'].widget.attrs.update(
                {'class': 'fileinput', 'multiple': True})

models.py

from django.db import models
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify


class Post(models.Model):
    # on_delete ile, bu kullanıcı silindiğinde bu kullanıcıya ait tüm postlar da silinecek.
    author = models.ForeignKey(
        "auth.User", on_delete=models.CASCADE, verbose_name="Yazar")
    title = models.CharField(max_length=150, verbose_name="Başlık")
    content = models.TextField(verbose_name="İçerik")
    # auto_now_add = True ile veritabanına eklendiği tarihi otomatik alacak
    created_date = models.DateTimeField(auto_now_add=True)

    # admin panelinde Post Object 1 yazması yerine başlığı yazsın istersek...
    def __str__(self):
        return self.title


def get_image_filename(instance, filename):
    title = instance.post.title
    slug = slugify(title)
    return "post_images/%s-%s" % (slug, filename)


class Images(models.Model):
    post = models.ForeignKey(
        Post, on_delete=models.DO_NOTHING, default=None)
    image = models.ImageField(upload_to=get_image_filename,
                              verbose_name='Image', default="images/default_game_img.png")

【问题讨论】:

  • 我是 django 新手。我可以使用其他东西来代替 formset。它只需要解决我的问题。

标签: python django


【解决方案1】:

如果你需要一个文件来上传多张图片,试试这个:

views.py

from .forms import PostForm
from .models import Post, Images

def share(request):
    form = PostForm()

    if request.method == 'POST':
        post = Post()
        post.title = request.POST['title']
        post.content = request.POST['content']
        post.author = request.user
        post.save()

        for image in request.FILES.getlist('images'):
            image_obj = Image()
            image_obj.post_id = post.id
            image_obj.image = image
            image_obj.save()

    return render(request, 'share.html', {'form': form})

forms.py

from django import forms

class PostForm(forms.Form):
    title = forms.CharField(label='', 
                        widget=forms.TextInput(attrs={
                            'class': 'input',
                            }
                        )) 

    content = forms.CharField(label='', 
                           widget=forms.Textarea(attrs={
                               'class': 'textarea',
                               }
                           ))                    

    images = forms.ImageField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

share.html

<form  method="POST" id="post-form" class="post-form js-post-form" enctype="multipart/form-data">
            {% csrf_token %}
            {% for elem in form %}
                {{ elem }}
            {% endfor %}
</form>

【讨论】:

  • 我看到request.FILES.getlist ('image') 没有返回任何内容。你能写剩下的views.py吗?我无法将图像保存到数据库。
  • 查看使用:form = ImageForm() if request.method == 'POST': for image in request.FILES.getlist('image'): photo = Images(image=image) photo.save()
  • 这不会保存到数据库中。还有form = ImageForm()为什么? form 在这种情况下是未使用的变量。
  • 您不必使用表单集。使用表格
  • 给我看看你的模型,我为你写完整的工作变体
【解决方案2】:

我认为你想太多了,你应该尝试像django-multiupload这样的lib

并且可以通过这个链接找到多张图片上传的有效实现

https://stackoverflow.com/a/44075555/10798048

希望这将简化您的实施并解决您的问题。如果它不适合你,请纠正我。

【讨论】:

    猜你喜欢
    • 2014-06-14
    • 2015-06-14
    • 2019-04-15
    • 1970-01-01
    • 2016-04-14
    • 2021-12-07
    • 2018-12-11
    • 2010-10-29
    • 2015-04-21
    相关资源
    最近更新 更多