How to create multiple images upload in Django CreateView?

痞子三分冷 提交于 2021-01-29 09:21:04

问题


I have a django project and I created a post operation in this project, so the user will be able to share multiple picture posts. But I have a problem. I can't write multiple image upload function. I looked at a lot of content, but it doesn't work. Either it reports a problem or contex is not sent to the html page I wanted. Please help me. The multi picture function I want should be under CreateView and should be placed in the same templet as it. Also, there should be 4 Image upload buttons, and the last one should be assigned multiple features (to html tag)

models.py:

class Photo(models.Model):
post= models.ForeignKey(Person, on_delete=models.CASCADE)

image = models.ImageField(upload_to=get_image_filename)
uploaded_at = models.DateTimeField(auto_now_add=True)

views.py:

class PersonCreateView(CreateView):
model = Person
form_class = PersonForm
success_url = reverse_lazy('person_changelist')

forms.py:

    class PhotoForm(forms.ModelForm):
    image = forms.ImageField(label='Image')
    class Meta:
        model = Photo
        fields = ('image', )


class PersonForm(forms.ModelForm):
    title = forms.CharField(max_length=128)
    body = forms.CharField(max_length=245, label="Item Description.")
    file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

    class Meta:
        model = Person
        widgets = {
            'valyuta': forms.RadioSelect,
            'barter': forms.CheckboxInput,

        }
        fields = ('country', 'city', 'ban', 'yurus', 'reng', 'qiymet', 'valyuta', 'yanacaqnovu', 'oturucu', 'squtu', 'buraxilisili', 'hecm', 'seher', 'barter', 'metin')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['city'].queryset = City.objects.none()


        if 'country' in self.data:
            try:
                country_id = int(self.data.get('country'))
                self.fields['city'].queryset = City.objects.filter(country_id=country_id).order_by('name')
            except (ValueError, TypeError):
                pass  # invalid input from the client; ignore and fallback to empty City queryset
        elif self.instance.pk:
            self.fields['city'].queryset = self.instance.country.city_set.order_by('name')

回答1:


See if this works. Create a simple HTML form instead of the Django's model form

<form enctype="multipart/form-data" action="" method="post">
    <input type="file" name="uploaded_images" accept="image/*" multiple>
    <input type="submit" name="upload" value="Upload">
</form>

In your view:

if request.method == 'POST':
    for afile in request.FILES.getlist('uploaded_images'):
        #Save images in respective models with the links to other models
        return redirect('back/to/same/url')

This will enable the user to upload multiple images at once and you will easily be able to work with individual images.




回答2:


I was struggling with the same issue but eventually I succeeded. So i want to share my solution. First of all we need to create 2 models, one of them to put ImageField and connect using ForeignKey with the first model.

models.py

class Item(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="items")
    name = models.CharField(max_length=100)


class ItemImage(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    img = models.ImageField(default="store/default_noitem.jpg", upload_to=get_image_dir)

Then create form using inlineformset_factory. It helps especially in the case of working with related objects via a foreign key.

forms.py

from django import forms
from django.forms.models import inlineformset_factory

from .models import Item, ItemImage

class  ItemImageForm(forms.ModelForm):
    class Meta:
        model = ItemImage
        exclude = ()

class ItemForm(forms.ModelForm):
    class Meta:
        model = Item
        fields = ["name",]

ItemImageFormSet = inlineformset_factory(
    Item, ItemImage, form=ItemImageForm,
    fields=['img'], extra=3, can_delete=True  # <- place where you can enter the nr of img
)

And finally

views.py

class ItemCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
    template_name = "items/add_item_form.html"
    success_message = 'Item successfully added!'
    form_class = ItemForm

    def get_context_data(self, **kwargs):
        data = super(ItemCreateView, self).get_context_data(**kwargs)
        data['form_images'] = ItemImageFormSet()
        if self.request.POST:
            data['form_images'] = ItemImageFormSet(self.request.POST, self.request.FILES)
        else:
            data['form_images'] = ItemImageFormSet()
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        form_img = context['form_images']
        with transaction.atomic():
            form.instance.user = self.request.user
            self.object = form.save()
            if form_img.is_valid():
                form_img.instance = self.object
                form_img.save()
        return super(ItemCreateView, self).form_valid(form)

Remember to add (self.request.POST, self.request.FILES) inside formset and enctype="multipart/form-data" inside html where <form> tag is located.



来源:https://stackoverflow.com/questions/59922054/how-to-create-multiple-images-upload-in-django-createview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!