如何使用CreateView在Django中上传多个文件? [英] How to carry out uploading multiple files in Django with CreateView?

查看:60
本文介绍了如何使用CreateView在Django中上传多个文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请帮助我。我是Django的新手,不能理解以下内容-我有CreateView的子类来创建注释。我想创建一个项目,使人们可以留下他们的评论并将文件(图像)附加到该评论。一个人应该可以将尽可能多的图像附加到带有文本注释的一个表单中。我在互联网上发现一个决定,我需要使用2种模型-1种用于文本注释的模型+ 1种用于图像的单独模型。是这样吗?

Please help me. I am new to Django, cannot undertsand the following thing - I have subclass of CreateView for creating a comment. I want to create a project where people can leave their comments and attach files (images) to this comment. One should have possibility to attach as many images as he wants to ONE form with text comment. I have found in Internet a decision that I need to use 2 models - 1 model for text comment + 1 separate model for images. Is it so?

评论(文本)表单是通过CreateView子文件夹在我的views.py中创建和处理的。如何使用我的CreateView连接新的单独图像模型?

Comment (text) form is created and handled in my views.py by sublass of CreateView. How to connect new separate model for images with my CreateView ?

models.py

class Descriptions(models.Model):
…
city = models.ForeignKey(Cities, on_delete=models.CASCADE)
description = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.DO_NOTHING)
…
class Description_Photos(models.Model):
    image = models.ImageField(upload_to='images/', blank=True)
    description = models.ForeignKey(Descriptions, on_delete=models.CASCADE, related_name='photos')

forms.py

class DescriptionsForm(forms.ModelForm):
    class Meta:
        model = Descriptions
        exclude = []
        widgets = {'description': forms.Textarea(attrs={'cols':90})}

class Photos_form(forms.Form):
    photos = forms.FileField(widget=forms.FileInput(attrs={'multiple': True}))

views.py

class DescriptionCreate(CreateView):
    model = Descriptions
    form_class = DescriptionsForm
    template_name = 'countries/new_description.html'

    def get_success_url(self):
        return reverse('countries:descr', args=[self.kwargs['country_id'], self.kwargs['city_id']])

    def get_context_data(self, **kwargs):
        self.city = get_object_or_404(Cities, id=self.kwargs['city_id'])
        kwargs['city'] = self.city
        return super().get_context_data(**kwargs)

    def form_valid(self, form):
        form.instance.city = get_object_or_404(Cities, id=self.kwargs['city_id'])
        form.instance.owner = self.request.user
        messages.success(self.request, 'Your post has been added, thank you')
        return super().form_valid(form)

所以我的问题是对于类Photos_form(forms.Form),我应该在views.py中写什么:?如何将此类与我的类DescriptionCreate(CreateView)连接?

So my question is what should I write in views.py for class Photos_form(forms.Form): ? How to connect this class and my class DescriptionCreate(CreateView) ?

推荐答案

我在相同情况下使用FormSets https://docs.djangoproject.com/ zh_cn / 2.0 / topics / forms / formsets /

I use for same situations FormSets https://docs.djangoproject.com/en/2.0/topics/forms/formsets/

为图像模型声明FormSet

Declare FormSet for images models

…

# forms.py

class DescriptionsForm(forms.ModelForm):
    class Meta:
        model = Descriptions
        exclude = []
        widgets = {'description': forms.Textarea(attrs={'cols':90})}

class Photos_form(forms.Form):
    photos = forms.FileField(widget=forms.FileInput(attrs={'multiple': True}))


##### Declare FORMSET !!! ###
class BasePhotosFormSet(BaseModelFormSet):

    """By default, when you create a formset from a model, the formset
    will use a queryset that includes all objects in the model"""

    def __init__(self, *args, **kwargs):
        if 'city' in kwargs.keys():
            city = kwargs.pop('city')
        else:
            city = None
        super().__init__(*args, **kwargs)
        if city and isinstance(instance, Cities):
            self.queryset = Description_Photos.objects.filter(city=city)
        else:
            self.queryset = Description_Photos.objects.none()

# I usually declare formset for create operations and formset for update operations separately          
PhotosCreateFormSet = forms.modelformset_factory(Description_Photos, Photos_form,
                                                    fields=Photos_form.Meta.fields, extra=0,
                                                    formset=BasePhotosFormSet)


PhotosUpdateFormSet = forms.modelformset_factory(Description_Photos, Photos_form, can_delete=True,
                                              fields=PropertyImageForm.Meta.fields, extra=0,
                                              formset=BasePhotosFormSet)


#############

# views.py

class DescriptionCreate(CreateView):

    def __init__(self, **kwargs):
        self.object = None
        super().__init__(**kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.POST:
            images_formset = PhotosCreateFormSet(self.request.POST, self.request.FILES, city=self.object)
        else:
            images_formset = PhotosCreateFormSet(instance=self.object)
        context['formset'] = images_formset
        context['city'] = self.object
        return context

模板

    <div id="img-form-template" style="display: none">
       <!- Declare EMPTY FORM for dynamically rebuild user interface by jQuery, for example->
      {{ formset.empty_form }}
    </div>
    ...
    <div id="my-images">
        ...
        {{ formset.management_form }}
        {% for image_form in formset %}
            {{ image_form }}
        {% endfor %}
    </div>
    ...
    <script>
      ...
      <!- Any javascript code to dynamically create empty form based on template "#img-form-template" ->
      ...
    </script>

我尝试将自定义代码重写为您的变体形式。
我想在您的示例中将 self.city 声明为创建模型实例是一个坏主意:Django自动创建 self.object

I've tried to rewrite my custom code to your variant. I suppose it is a bad idea to declare self.city in your example as creation model instance: Django automatically create self.object

这篇关于如何使用CreateView在Django中上传多个文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆