Django formset создает несколько входов для загрузки нескольких изображений - PullRequest
7 голосов
/ 01 апреля 2020

Я пытаюсь создать простую форму обмена сообщениями, подобную этой.

enter image description here

Я использую набор форм для загрузки изображений. Но это дает мне несколько входов, как вы можете видеть. Также каждый вход может выбрать одно изображение. Но я пытаюсь загрузить несколько изображений с одним входом.

views.py

def share(request):

    ImageFormSet = modelformset_factory(Images,
                                        form=ImageForm, extra=3)
    # 'extra' means the number of photos that you can upload   ^

    if request.method == 'POST':
        postForm = PostForm(request.POST)
        formset = ImageFormSet(request.POST, request.FILES,
                               queryset=Images.objects.none())

        if postForm.is_valid() and formset.is_valid():
            post = postForm.save(commit=False)
            post.author = request.user
            post.save()

            for form in formset.cleaned_data:
                # this helps to not crash if the user
                # do not upload all the photos
                if form:
                    image = form['image']
                    photo = Images(post=post, image=image)
                    photo.save()

            return redirect("index")

        else:
            print(postForm.errors, formset.errors)
    else:
        postForm = PostForm()
        formset = ImageFormSet(queryset=Images.objects.none())
    return render(request, "share.html", {"postForm": postForm, 'formset': formset})

поделиться. html

 <form  method="POST" id="post-form" class="post-form js-post-form" enctype="multipart/form-data">
            {% csrf_token %}
             {{ formset.management_form }}
                {% for form in formset %}
                    {{ form }}
                {% endfor %} 
   </form>

если вам нужно, формы .py

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ["title", "content"]

    def __init__(self, *args, **kwargs):
        super(PostForm, self).__init__(*args, **kwargs)
        self.fields['title'].widget.attrs.update({'class': 'input'})
        self.fields['content'].widget.attrs.update({'class': 'textarea'})


class ImageForm(forms.ModelForm):
    image = forms.ImageField(label='Image')

    class Meta:
        model = Images
        fields = ('image', )

        def __init__(self, *args, **kwargs):
            self.fields['image'].widget.attrs.update(
                {'class': 'fileinput', 'multiple': True})

models.py

from django.db import models
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify


class Post(models.Model):
    # on_delete ile, bu kullanıcı silindiğinde bu kullanıcıya ait tüm postlar da silinecek.
    author = models.ForeignKey(
        "auth.User", on_delete=models.CASCADE, verbose_name="Yazar")
    title = models.CharField(max_length=150, verbose_name="Başlık")
    content = models.TextField(verbose_name="İçerik")
    # auto_now_add = True ile veritabanına eklendiği tarihi otomatik alacak
    created_date = models.DateTimeField(auto_now_add=True)

    # admin panelinde Post Object 1 yazması yerine başlığı yazsın istersek...
    def __str__(self):
        return self.title


def get_image_filename(instance, filename):
    title = instance.post.title
    slug = slugify(title)
    return "post_images/%s-%s" % (slug, filename)


class Images(models.Model):
    post = models.ForeignKey(
        Post, on_delete=models.DO_NOTHING, default=None)
    image = models.ImageField(upload_to=get_image_filename,
                              verbose_name='Image', default="images/default_game_img.png")

Ответы [ 2 ]

8 голосов
/ 04 апреля 2020

Если вам требуется одно поле для загрузки нескольких изображений, попробуйте следующее:

views.py

from .forms import PostForm
from .models import Post, Images

def share(request):
    form = PostForm()

    if request.method == 'POST':
        post = Post()
        post.title = request.POST['title']
        post.content = request.POST['content']
        post.author = request.user
        post.save()

        for image in request.FILES.getlist('images'):
            image_obj = Image()
            image_obj.post_id = post.id
            image_obj.image = image
            image_obj.save()

    return render(request, 'share.html', {'form': form})

forms.py

from django import forms

class PostForm(forms.Form):
    title = forms.CharField(label='', 
                        widget=forms.TextInput(attrs={
                            'class': 'input',
                            }
                        )) 

    content = forms.CharField(label='', 
                           widget=forms.Textarea(attrs={
                               'class': 'textarea',
                               }
                           ))                    

    images = forms.ImageField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

share. html

<form  method="POST" id="post-form" class="post-form js-post-form" enctype="multipart/form-data">
            {% csrf_token %}
            {% for elem in form %}
                {{ elem }}
            {% endfor %}
</form>
2 голосов
/ 11 апреля 2020

Я думаю, что вы слишком много думаете о реализации, вам следует попробовать lib как django -multiupload

И вы можете найти правильную реализацию для загрузки нескольких изображений по этой ссылке

{ ссылка }

Надеюсь, это облегчит вашу реализацию и решит вашу проблему. Поправь меня, если у тебя это не получится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...