如何将多个图像上传到django中的博客文章

oll*_*all 22 django image image-uploading amazon-s3 cloudinary

我试图让每个用户将多张图片上传到一篇博文.我一直试图找出最好的方法来做几天.这样做的最佳做法是什么?

根据我的阅读,我应该从博客文章模型中创建一个单独的图像模型并使用外键.是对的吗?然后是如何允许他们同时上传多张图片的问题.我是否正确地假设我应该使用像drop zone这样的东西?

有关存储照片的最佳做法的任何建议也是受欢迎的.我看过亚马逊s3和cloudinary.我想创建一些可扩展的东西.

任何帮助将非常感激!

qas*_*ali 39

你只需要两个型号.一个用于邮政,另一个用于图像.您的图像模型将具有Post模型的外键:

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

class Post(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length=128)
    body = models.CharField(max_length=400)

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, default=None)
    image = models.ImageField(upload_to=get_image_filename,
                              verbose_name='Image')
Run Code Online (Sandbox Code Playgroud)

您需要为每个模型创建一个表单,但它们将彼此相关,例如当用户填写表单时,他必须完成图像表单以便成功发布帖子,我们将做在视图中,但是现在你的表单看起来像这样

from django import forms
from .models import Post, Images

class PostForm(forms.ModelForm):
    title = forms.CharField(max_length=128)
    body = forms.CharField(max_length=245, label="Item Description.")

    class Meta:
        model = Post
        fields = ('title', 'body', )


class ImageForm(forms.ModelForm):
    image = forms.ImageField(label='Image')    
    class Meta:
        model = Images
        fields = ('image', )
Run Code Online (Sandbox Code Playgroud)

现在这是所有事物中最重要的部分,即视图,因为这是将多个图像上传到单个魔法的地方.为了让我们能够一次上传多个图像,我们需要多个图像字段吗?这就是你爱上Django formsets的地方.我们将使用django formsets来实现这一点,你可以在Django文档中阅读有关我已经链接的表单集:)但是这里是你的视图应该是这样的:

*非常重要的进口

from django.shortcuts import render
from django.forms import modelformset_factory
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import HttpResponseRedirect
from .forms import ImageForm, PostForm

@login_required
def post(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_form = postForm.save(commit=False)
            post_form.user = request.user
            post_form.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_form, image=image)
                    photo.save()
            messages.success(request,
                             "Yeeew, check it out on the home page!")
            return HttpResponseRedirect("/")
        else:
            print(postForm.errors, formset.errors)
    else:
        postForm = PostForm()
        formset = ImageFormSet(queryset=Images.objects.none())
    return render(request, 'index.html',
                  {'postForm': postForm, 'formset': formset})
Run Code Online (Sandbox Code Playgroud)

在视图中,我们获取了两个表单,如果两个表单都有效,则视图将检查这两个表单.以这种方式,用户必须填写表格并上传所有图像,在这种情况下是3 extra=3.只有这样才能成功创建帖子.

您的模板应如下所示:

<form id="post_form" method="post" action="" enctype="multipart/form-data">

    {% csrf_token %}
    {% for hidden in postForm.hidden_fields %}
        {{ hidden }}
    {% endfor %}

    {% for field in postForm %}
        {{ field }} <br />
    {% endfor %}

    {{ formset.management_form }}
    {% for form in formset %}
        {{ form }}
    {% endfor %}


    <input type="submit" name="submit" value="Submit" />
</form>
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢!您如何将诸如dropzone js的拖放系统集成到其中?如果要使用拖放方法,是否需要模板集? (2认同)

Yas*_*ash 7

逐步解决方案=> 甚至,我也被卡住了。所以这就是我成功的方式

Finally实现下面的代码,我实现了这个

  • 1 带有许多图像的音符模型
  • 多次上传同时,使用相同的“选择文件”按钮,并且像Gmail 文件上传一样全部保存在一起)

这是我的笔记和图像模型-(或查看完整代码

class Note(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
    title = models.CharField(max_length=30)
    text = models.TextField(null=True,blank=True)
    created_date = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)

class Images(models.Model):
    note = models.ForeignKey(Note,on_delete=models.CASCADE)
    image = models.ImageField(upload_to=user_directory_path,null=True,blank=True)
Run Code Online (Sandbox Code Playgroud)

这是我的表格(多次上传文档链接)-(或查看完整代码

class NoteForm(forms.ModelForm):
    class Meta:
        model = Note
        fields = ['title','text'] #make sure to mention field here, if nothing is mentioned then all will be required.

class NoteFullForm(NoteForm): #extending form
    images = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

    class Meta(NoteForm.Meta):
        fields = NoteForm.Meta.fields + ['images',]
Run Code Online (Sandbox Code Playgroud)

这是我的查看文件-(或查看完整代码

def addNoteView(request):
if request.method == "POST":
    #images will be in request.FILES
    form = NoteFullForm(request.POST or None, request.FILES or None)
    files = request.FILES.getlist('images')
    if form.is_valid():
        user = request.user
        title = form.cleaned_data['title']
        text = form.cleaned_data['text']
        note_obj = Note.objects.create(user=user,title=title,text=text) #create will create as well as save too in db.
        for f in files:
            Images.objects.create(note=note_obj,image=f)
    else:
        print("Form invalid")
Run Code Online (Sandbox Code Playgroud)

而且,最后是我的 Html 文件(请务必按照文档中的说明绑定文件)-(或查看完整代码

<form action="{% url 'note:add_note' %}" method="post" class="note-form" enctype="multipart/form-data">{% csrf_token %}
  <div class="form-group">
    <label for="note-title">Title</label>
    <input type="text" name="title" class="form-control" id="note-title" placeholder="Enter Title" required>
  </div>
  <div class="form-group">
    <label for="note-description">Description</label>
    <textarea type="text" name="text" class="form-control" id="note-description" placeholder="Description here"></textarea>
  </div>
  <div class="form-group">
    <label for="note-image">Images</label>
    <input type="file" name="images" class="form-control-file" id="note-image" multiple>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)


小智 5

答案很简单。不需要那么多代码。

HTML 文件

<input type="file" name = "files" multiple />
Run Code Online (Sandbox Code Playgroud)

视图.PY

files = request.FILES.getlist('files')

for f in files:
    a = Image(image=f)
    a.save()
Run Code Online (Sandbox Code Playgroud)