【问题标题】:How can I upload multiple files to a model field?如何将多个文件上传到模型字段?
【发布时间】:2016-11-10 11:11:26
【问题描述】:

我想通过 ModelForm 上传多个文件,所有文件都分配给 Model 的 file 字段。我浏览了文档,看到了一个例子,我在这里实现了它,但我只能让我的表单选择多个文件,但只有一个被保存并分配给filesfield。下面是我的代码

models.py

class Feed(models.Model):
    user=models.ForeignKey(User,on_delete=models.CASCADE,related_name='feeds')
    text=models.TextField(blank=False,max_length=500)
    files = models.FileField(upload_to="files/%Y/%m/%d")

forms.py

class FeedForm(ModelForm):
    class Meta:
        model=Feed
        fields=('text','auth','files')
        widgets={"files":forms.FileInput(attrs={'id':'files','required':True,'multiple':True})}

和views.py

def post_feed(request):
    form_class = FeedForm
    if request.method == 'POST':
        form = form_class(request.POST,request.FILES)
        if form.is_valid():
            feed = form.save(commit=False)
            feed.user = User.objects.get(pk=1)
            feed.pub_date=timezone.now()
            #instance = Feed(files=request.FILES['files'])
           # feed.files=request.FILES['files']
            feed.save()
            return redirect('home')
    else:
        form = form_class()
        return render(request, 'post_feed.html', {'form': form,})

from django.views.generic.edit import FormView
from .forms import FeedForm

class FileFieldView(FormView):
    form_class=FeedForm
    template_name='post_feed.html'
 '''success_url=???   #I dont know what to write here.I thought of putting this
render(request, 'post_feed.html', {'form': form,}) because I just want 
to reload the page but it gave an error,so I removed it entirely.'''

    def post_feed(self,request,*args,**kwargs):
        form_class=self.get_form_class()
        form=self.get_form(form_class)
        filez=request.FILES.getlist('files')
        if form.is_valid():
            for f in filez:
                f.save()
            return self.form_valid(form)     
        else:
            return self.form_invalid(form) 

请帮帮我,在此先感谢。

【问题讨论】:

    标签: django


    【解决方案1】:

    您必须为文件创建一个单独的模型并使用外键连接它们:

    class Feed(models.Model):
        user=models.ForeignKey(User, on_delete=models.CASCADE, related_name='feeds')
        text=models.TextField(blank=False, max_length=500)
    
    
    class FeedFile(models.Model):
        file = models.FileField(upload_to="files/%Y/%m/%d")
        feed = models.ForeignKey(Feed, on_delete=models.CASCADE, related_name='files')
    

    我希望这会有所帮助。

    【讨论】:

    • 谢谢。但是哪个更可取?。要将文件外键放在 Feed 模型中还是您建议的上面?,考虑到我想在哪个文件中使用 FeedForm 是一个字段?
    • 如果您将文件放在 Feed 模型中,那么即使在 upload_to 目录中存在多个文件,您在数据库中也只会有 一个 对该文件的引用。我认为您应该使用Feed 的表单和FeedFile 的内联表单集。 This blog post 可能比我在这里输入的任何内容都能更好地帮助您。我希望这会有所帮助!
    【解决方案2】:

    建议使用从 Feed 模型到 FeedFile 模型的 M2M 字段。 让查询特定Feed 对象的文件时变得更加容易,我觉得这也是Feed 对象最常见的用例

    class Feed(models.Model):
        user=models.ForeignKey(User, on_delete=models.CASCADE, related_name='feeds')
        text=models.TextField(blank=False, max_length=500)
        files=models.ManyToManyField(FeedFile)
    
    class FeedFile(models.Model):
        file = models.FileField(upload_to="files/%Y/%m/%d")
    

    【讨论】:

    • 我更喜欢这个解决方案。它还将提供在创建提要模型实例时上传文件的选项,而不是在可以上传文件之前先创建提要实例的其他选项
    【解决方案3】:

    唷,我花了一整天的时间才弄清楚这一点。我的目标是将多个文件分配给一个类的一个实例,就像一个博客实例可以有多个图像。首先,您不能在模型中(例如在 Blog 类中)使用一个 models.FileField 来执行此操作,因为该字段并非旨在保存多个文件。因此,解决方案是为文件创建单独的模型并将它们与一对多关系(外键)连接起来,正如@Carlos Mermingas 所回答的那样。 话不多说,下面是上述情况的代码:

    # models.py
    class Feed(models.Model):
    user=models.ForeignKey(User, on_delete=models.CASCADE)
    text=models.TextField(blank=False, max_length=500)
    
    class FeedFile(models.Model):
    file = models.FileField(upload_to="files/%Y/%m/%d")
    feed = models.ForeignKey(Feed, on_delete=models.CASCADE)
    
    # forms.py
    ...
    from django.forms import ClearableFileInput
    ...
    class FeedModelForm(forms.ModelForm):
        class Meta:
            model = Feed
            fields = ['text']
    
    class FileModelForm(forms.ModelForm):
        class Meta:
            model = FeedFile
            fields = ['file']
            widgets = {
                'file': ClearableFileInput(attrs={'multiple': True}),
            }
            # widget is important to upload multiple files
    
    # views.py
    from .models import FeedFile
    ...
    def create_to_feed(request):
        user = request.user
        if request.method == 'POST':
            form = FeedModelForm(request.POST)
            file_form = FileModelForm(request.POST, request.FILES)
            files = request.FILES.getlist('file') #field name in model
            if form.is_valid() and file_form.is_valid():
                feed_instance = form.save(commit=False)
                feed_instance.user = user
                feed_instance.save()
                for f in files:
                    file_instance = FeedFile(file=f, feed=feed_instance)
                    file_instance.save()
        else:
            form = FeedModelForm()
            file_form = FileModelForm()
    
        # the rest is the basic code: template_name, context, render etc. 
    
    # in your template.html <form> tag must include enctype="multipart/form-data"
    

    奖励:如果您想在管理面板中查看上传的文件,您可以使用 InlineModelAdmin 对象。代码如下:

    # admin.py of your app
    from django.contrib import admin
    from .models import Feed, FeedFile
    
    class FeedFileInline(admin.TabularInline):
        model = FeedFile
    
    
    class FeedAdmin(admin.ModelAdmin):
        inlines = [
            FeedFileInline,
        ]
    
    admin.site.register(Feed, FeedAdmin)
    

    有关file uploadModel Forms的更多详细信息,如何包含widget in Model Form

    【讨论】:

    • 如何预览图像? urls.py 中图片的路径是什么?
    猜你喜欢
    • 1970-01-01
    • 2015-10-27
    • 2021-07-30
    • 2020-05-19
    • 2011-03-12
    • 1970-01-01
    • 2014-10-31
    • 1970-01-01
    • 2017-05-31
    相关资源
    最近更新 更多