且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用CreateView在Django中上传多个文件?

更新时间:2023-12-04 09:26:04

我在相同情况下使用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