Как сделать одну форму для нескольких моделей с отношениями один-ко-многим в django?

У меня есть одна модель, имя которой Post. Она имеет два отношения "один-два-много" с моделями "PostImages" и "PostFiles". Я хочу создать только одну форму для обработки этого. Также я хочу, чтобы загрузка файлов и изображений не требовалась. И я сделал это, но мой код не запускает процесс валидации на "PostImagesForm" и "PostFilesForm", но он валидирует "PostForm".

models.py (я использую FileTypeValidator из пакета uload_validator, который отлично работает для миниатюр, так что с этим проблем нет)

class Post(models.Model):
    title           = models.CharField(max_length=60)
    content         = tinymce_models.HTMLField('content')
    date            = models.DateTimeField(default=timezone.now)
    slug            = AutoSlugField(populate_from='title', unique_with='date')
    thumbnail_big   = models.ImageField(upload_to='thumbnails/', validators=[FileTypeValidator(allowed_types=[VIEL])])
    thumbnail_small = models.ImageField(upload_to='thumbnails/', blank=False, default=thumbnail_big)



    def description(self):
        return HTMLtoString(self.content)



    def save(self, *args, **kwargs):
        #THUMBNAIL COMPRESSION
        #small thumbnail
        if SizeOfImageGreaterThan(self.thumbnail_big, TQS.SMALL_THUMBNAIL_RESOLUTION):
            thumbnail_compressed_small = Compress(self.thumbnail_big, TQS.SMALL_THUMBNAIL_RESOLUTION, TQS.SMALL_THUMBNAIL_QUALITY)

            self.thumbnail_small = thumbnail_compressed_small


        #big thumbnail
        if SizeOfImageGreaterThan(self.thumbnail_big, TQS.BIG_THUMBNAIL_RESOLUTION):
            thumbnail_compressed_big = Compress(self.thumbnail_big, TQS.BIG_THUMBNAIL_RESOLUTION, TQS.BIG_THUMBNAIL_QUALITY)

            self.thumbnail_big = thumbnail_compressed_big


        super(Post, self).save(*args, **kwargs)
    

    def get_absolute_url(self):
        return reverse("EatWell:Post", args=[self.slug])
        

class PostImages(models.Model):
    post        = models.ForeignKey(Post, on_delete=models.CASCADE)
    big_image   = models.ImageField(upload_to='images/', blank=True, null=True, validators=[FileTypeValidator(allowed_types=[VIEL])])
    small_image = models.ImageField(upload_to='images/', blank=False, default=big_image)


    def save(self, *args, **kwargs):
        #IMAGE COMPRESSION
        #small image
        if SizeOfImageGreaterThan(self.big_image, IQS.SMALL_IMAGE_RESOLUTION):
            small_image_compressed = Compress(self.big_image, IQS.SMALL_IMAGE_RESOLUTION, IQS.SMALL_IMAGE_QUALITY)

            self.small_image = small_image_compressed


        #big image
        if SizeOfImageGreaterThan(self.big_image, IQS.BIG_IMAGE_RESOLUTION):
            big_image_compressed = Compress(self.big_image, IQS.BIG_IMAGE_RESOLUTION, IQS.BIG_IMAGE_QUALITY)

            self.big_image = big_image_compressed
        
       
        super(PostImages, self).save(*args, **kwargs)


class PostFiles(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    file = models.FileField(upload_to='files/', blank=True, null=True)

forms.py (я использую crispy forms)

class PostCreationForm(forms.ModelForm):

    class Meta:
        model = models.Post
        fields = ['title', 'content', 'date', 'thumbnail_big']
        labels = {
            'thumbnail_big': 'Thumbnail',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.form_method = 'POST'
        self.helper = FormHelper(self)
        self.helper.form_tag = False
        self.helper.disable_csrf = True
        self.helper.layout = Layout(
            Fieldset(
                'Create a post',
                'title',
                'content',
                'date',
                Field('thumbnail_big'), #accept=VIEL),
            ),
            
        )


class PostImagesCreationForm(forms.ModelForm):

    class Meta:
        model = models.PostImages
        fields = ['big_image']
        labels = {'big_image' : ''}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.form_method = 'POST'
        self.helper = FormHelper(self)
        self.helper.form_tag = False
        self.helper.disable_csrf = True
        self.helper.layout = Layout(
            Fieldset(
                'Upload images',
                Field('big_image', multiple = True), #accept=VIEL),
            ),
        )


class PostFilesCreationForm(forms.ModelForm):

    class Meta:
        model = models.PostFiles
        fields = ['file']
        labels = {'file' : ''}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.form_method = 'POST'
        self.helper = FormHelper(self)
        self.helper.form_tag = False
        self.helper.disable_csrf = True
        self.helper.layout = Layout(
            Fieldset(
                'Upload files',
                Field('file', multiple = True), #, accept = VEL
            ),
            self.helper.add_input(Submit('submit','Submit')),
        )

views.py

@login_required()
def PostCreationView(request):

    post_form = forms.PostCreationForm()
    images_form = forms.PostImagesCreationForm()
    files_form = forms.PostFilesCreationForm()

    if request.method == 'POST':

        post_form = forms.PostCreationForm(request.POST, request.FILES)
        files_form = forms.PostFilesCreationForm(request.FILES)
        images_form = forms.PostImagesCreationForm(request.FILES)

        images = request.FILES.getlist('big_image')
        files = request.FILES.getlist('file')

        if post_form.is_valid():

            print('[INFO] PostCreationForm is valid')


            post_form.save()

            print('[INFO] PostCreationForm has been saved')


            if images_form.is_valid(): #always returns True

                print('[INFO] PostImagesCreationForm is valid')

                for image in images:

                    models.PostImages.objects.create(post=post_form.save(), big_image=image)

                    print('[INFO] New table for image has been created')

            else:

                print('[THREAD] PostImagesCreationForm is not valid')

                print(files_form.errors.as_data())


            if files_form.is_valid(): #always returns True

                print('[INFO] PostFilesCreationForm is valid')

                for file in files:

                    models.PostFiles.objects.create(post=post_form.save(), file=file)

                    print('[INFO] New table for file has been created')

            else:

                print('[THREAD] PostFilesCreationForm is not valid')

                print(files_form.errors.as_data())


            return redirect('EatWell:Blog')
        

        else:

            print('[THREAD] PostFilesCreationForm is not valid')

            print(post_form.errors.as_data())


    context = {
        'title' : 'Post Creation',
        'tinymce' : True,
        'post_form' : post_form,
        'images_form' : images_form,
        'files_form' : files_form
    }


    return render(request, 'postcreation/postcreation.html', context)

postcreation.html

{% extends 'postcreation/base.html' %}
{% load crispy_forms_tags %}

{% block body %}
<div class="container-sm border p-3">
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {% crispy post_form %}
        {% crispy images_form %}
        {% crispy files_form %}
    </form>
</div>
<div class="container-sm border p-3 m-3">
    <button class="btn btn-danger mr-2" onclick="location.href = '{% url 'PostCreation:Logout' %}'" ;>Log out</button><button class="btn btn-info"onclick="location.href = '{% url 'HomePage' %}'" ;>Return to the home page</button>
</div>
{% endblock body %}

Описанный там способ работает в основном так, как я хочу, но он не проверяет файлы и изображения в "PostFilesView" и в "ImageFileView", которые загружает пользователь

Вернуться на верх