如何将多个文件上传到模型字段?

时间:2016-07-08 00:20:33

标签: django

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

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) 

请提前帮助我,谢谢。

3 个答案:

答案 0 :(得分:10)

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

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')

我希望这会有所帮助。

答案 1 :(得分:1)

Ph,我花了整整一天才弄清楚这一点。我的目标是将多个文件分配给一个类的一个实例,例如Blog实例可以具有多个图像。首先,您不能对一个模型(例如,在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

答案 2 :(得分:0)

建议使用从char *url = "rtp://127.0.0.1:1234"; AVFormatContext *oc = NULL; avformat_open_input(&oc, url, NULL , NULL); 模型到Feed模型的M2M字段。 查询特定FeedFile对象的文件时更容易,我认为这也是Feed对象最常用的用例

Feed