Единая форма для всего процесса или отдельная для каждого типа поста | django

Я пытаюсь сделать приложение наподобие reddit, где вы можете создавать посты для любого сервера, но вам разрешено размещать только изображение&видео/текст, но не оба. Но проблема в том, что я не знаю, должен ли я сделать одну ModelForm для всего процесса и скрывать или показывать fileField и textField с помощью Javascript, или сделать ModelForm для каждого типа поста и изменить форму, которая отображается с помощью Javascript

posts/forms.py:

class CreatePostTextForm(ModelForm):
    class Meta:
        model = Post
        fields = ['title','video','image','text']
        widgets ={'title':forms.TextInput({'placeholder':'تیتر'}), 
        'text':forms.Textarea({'placeholder':'متن'})}

posts/views.py

class CreatePostView(LoginRequiredMixin, View):
form_class = CreatePostTextForm

def dispatch(self, request, *args, **kwargs):
    user = User.objects.get(id=kwargs['pk'])
    if not user.id == request.user.id:
        messages.error(request, 'شما نمیتوانید باپست ایجاد کنید')
        return redirect('home:home')
    return super().dispatch(request, *args, **kwargs)

def get(self, request, pk):
    form = self.form_class()
    return render(request, 'posts/create-post.html', {'form':form})

def post(self, request, pk):
    form = self.form_class(request.POST, request.FILES)
    if form.is_valid():
        saved_form = form.save(commit=False)
        saved_form.creator = request.user
        saved_form.save()
        messages.success(request, 'پست شما باموفقیت ایجاد شد')
        return redirect('home:home')
    return render(request, 'posts/create-post.html', {'form':form})

posts/create-post.html

<div class="create-post-form-wrapper col-8">
  <div class="form-header">
    <div class="form-types">
      <button onclick="postType(0)">
        <p>متن</p>
        <img src="{% static 'posts/svgs/file.svg' %}" alt="" />
      </button>
      <button onclick="postType(1)">
        <p>عکس</p>
        <img src="{% static 'posts/svgs/image.svg' %}" alt="" />
      </button>
      <button onclick="postType(2)">
        <p>فیلم</p>
        <img src="{% static 'posts/svgs/video.svg' %}" alt="" />
      </button>
      <button onclick="postType(2)">
        <p>لینک</p>
        <img src="{% static 'posts/svgs/link.svg' %}" alt="" />
      </button>
    </div>
  </div>
  <div class="form-wrapper">
    <form
      class="post-form"
      action=""
      method="post"
      enctype="multipart/form-data"
      novalidate
    >
      {% csrf_token %}
      <div class="form-body">
        <div id="title-field">{{form.title}} {{ form.title.errors }}</div> 
        <div class="field">{{form.text}} {{ form.text.errors }}</div> //will change depending on postType() js function
        <div class="field">{{form.video}} {{ form.video.errors }}</div> //will change depending on postType() js function
        <div class="field">{{form.image}} {{ form.image.errors }}</div> //will change depending on postType() js function
      </div>
    </form>
    <div class="form-footer">
      <button id="submit" onclick="submit()">ارسال</button>
    </div>
  </div>
</div>

и вот форма, которая имеет кнопки для скрытия или отображения полей, которые включены в CreatePostForm:

  1. показывает заголовок и текстовое поле
  2. показывает заголовок и видео поле

С помощью jQuery вы можете динамически скрыть ввод текстового поля или, напротив, ввод изображения&видео. Или, например, вы можете проверить данные POST и убедиться, что отправлены оба варианта (изображение&видео/текст), после чего не обрабатывать форму, а вернуть сообщение об ошибке. Ваш код должен выглядеть следующим образом:

if request.POST.get('images&videos') and request.POST.get('text'): 
    ... # return error message

Приведенный выше код не очень читабелен, так как я написал его приблизительно, чтобы показать вам, как это можно сделать, и надеюсь, что вы поняли мою мысль. Просто переделайте его под себя.

Конечно, этот метод не будет иметь той динамики, которую вы могли бы иметь с JS, но также решает проблему.

Я бы предпочел выбрать метод jQuery fadeOut() (https://api.jquery.com/fadeout/), но оба эти решения хороши.

Задавайте вопросы, если есть, я вам помогу

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