如何允许用户在Django中上传多个图片和文件?

huangapple go评论71阅读模式
英文:

How can I allow users to upload multiple images and files in django?

问题

我想创建类似Facebook/Twitter的创建帖子功能。我有一个类似于example.com/username/posts/create的网址,其中包含与帖子模型相关的表单。正如您可能知道的,标准的ImageField和FileField没有上传多个项目的功能,也没有像拖放这样的良好编辑器。拖放并不是关键功能,但我真的想以某种方式处理类似Twitter/Facebook的编辑器,带有方便的按钮来上传照片/视频/文件。

我看到有很多自定义编辑器,如DJANGO-CKEDITOR等,但我不明白它们如何与一个图像/文件字段一起工作。也许有人曾经面对过这个问题?

以下是我表单和模型,如果有帮助的话:

Models.py

class Post(models.Model):
    title = models.CharField(max_length=200, null=True, blank=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    images = models.ImageField(null=True, blank=True, upload_to="posts/images")
    body = models.TextField(max_length=255)
    post_date = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)
    likes = models.ManyToManyField(User, through='UserPostRel', related_name='likes')

forms.py

class PostCreationForm(ModelForm):
    class Meta:
        model = Post
        fields = [
            'title',
            'body',
            'images',
        ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['title'].label = "Title"
        self.fields['body'].label = "Body"
        self.fields['images'].label = "Images"

希望这对您有所帮助。

英文:

I want to create functionality like facebook/twitter for creating a post. I have a url smth like example.com/username/posts/create with the form related to the post model. As you probably know, there is no ability in vanilla ImageField & FileField to upload multiple items, as well as no decent editor for drag&drop like things. Drag&Drop isn't a crucial feature, but I really want to handle with a twitter/facebook like editor somehow. With all it's convenient buttons for photo/video/file.

I saw there is a bunch of custom editors like DJANGO-CKEDITOR and etc., but I don't understand how it suppose to work anyway with one image/file field. Maybe, somebody was facing the problem?

Attach my form and model in case it will help:

Models.py

class Post(models.Model):
    title = models.CharField(max_length=200, null=True, blank=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    images = models.ImageField(null=True, blank=True, upload_to="posts/images")
    body = models.TextField(max_length=255)
    post_date = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)
    likes = models.ManyToManyField(User, through='UserPostRel', related_name='likes')

forms.py

class PostCreationForm(ModelForm):
    class Meta:
        model = Post
        fields = [
            'title',
            'body',
            'images',

        ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['title'].label = "Title"
        self.fields['body'].label = "Body"
        self.fields['images '].label = "images"

答案1

得分: 3

通常,这是通过额外的模型完成的:

class Post(models.Model):
    title = models.CharField(max_length=200, null=True, blank=True)
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    body = models.TextField(max_length=255)
    post_date = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)
    likes = models.ManyToManyField(
        settings.AUTH_USER_MODEL, through='UserPostRel', related_name='likers'
    )


class PostImage(models.Model):
    post = models.ForeignKey(Post, related_name='images')
    image = models.ImageField(upload_to='posts/images')

然后,我们创建一个小表单来处理批量上传:

class PostForm(forms.ModelForm):
    files = forms.FileField(
        label='',
        required=False,
        widget=forms.ClearableFileInput(attrs={'multiple': True}),
    )

    class Meta:
        model = Post
        fields = [
            'title',
            'body',
        ]
        labels = {'title': 'Title', 'body': 'Body'}

    def _save_m2m(self):
        super()._save_m2m()
        images = [
            PostImage(post=self.instance, image=file)
            for file in self.files.get('files')
        ]
        PostImage.objects.bulk_create(images)

然后,在视图中,我们让表单处理这个操作:

from django.shortcuts import redirect, render

def my_view(request):
    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES)
        if form is_valid():
            form.save()
            return redirect('<i>name-of-some-view</i>')
    else:
        form = PostForm()
    return render(request, '<i>name-of-some-template.html</i>', {'form': form})

注意:通常更好地使用 settings.AUTH_USER_MODEL 来引用用户模型,而不是直接使用 User 模型。有关更多信息,您可以查看文档中的 引用 User 模型 部分

英文:

Usually this is done through an extra model:

<pre><code>class Post(models.Model):
title = models.CharField(max_length=200, null=True, blank=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
body = models.TextField(max_length=255)
post_date = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
likes = models.ManyToManyField(
settings.AUTH_USER_MODEL, through='UserPostRel', related_name='likers'
)

class PostImage(models.Model):
post = models.ForeignKey(Post, related_name='images')
image = models.ImageField(upload_to='posts/images')</code></pre>

Then we make a small form to handle the bulk upload:

<pre><code>class PostForm(forms.ModelForm):
files = forms.FileField(
label='',
required=False,
widget=forms.ClearableFileInput(attrs={'multiple': True}),
)

class Meta:
    model = Post
    fields = [
        &#39;title&#39;,
        &#39;body&#39;,
    ]
    labels = {&#39;title&#39;: &#39;Title&#39;, &#39;body&#39;: &#39;Body&#39;}

def _save_m2m(self):
    super()._save_m2m()
    images = [
        PostImage(post=self.instance, image=file)
        for file in self.files.get(&#39;files&#39;)
    ]
    PostImage.objects.bulk_create(images)&lt;/code&gt;&lt;/pre&gt;

Then in the view we let the form handle this:

<pre><code>from django.shortcuts import redirect, render

def my_view(request):
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('<i>name-of-some-view</i>')
else:
form = PostForm()
return render(request, '<i>name-of-some-template.html</i>', {'form': form})</code></pre>


> Note: It is normally better to make use of the settings.AUTH_USER_MODEL&nbsp;<sup>[Django-doc]</sup> to refer to the user model, than to use the User model&nbsp;<sup>[Django-doc]</sup> directly. For more information you can see the referencing the User model section of the documentation.

huangapple
  • 本文由 发表于 2023年2月27日 04:43:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/75574896.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定