Nomad
NomadOct. 20, 2020, 8:20 a.m.

Django form vs modelForm

django, Form, modelform

всем привет.

всем известно что в Django есть очень важное составляющая это формы

по сути при создании формы мы определяем "тип формы" то есть форма связанная с моделью или нет = forms.Form или forms.ModelForm

в процессе изучения Django я понял что даже если данные полученные с формы надо сохранить в базе то легко можно использовать форму не сязанная с моделью ау же в процессе обработку данных из ПОСТ запроса сохранять их в модель.

может кто сказать правильно ли так делать или же если даные для какой то модели форма должна быть всегда типа ModelForm ?

или же все зависит от ситуации!?

или правило одно: нету никаких правил )

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

4
Илья Чичак
  • Oct. 20, 2020, 9:04 a.m.
  • (edited)
  • The answer was marked as a solution.

использовать данные напрямую из request.POST - опасно и черевато.
сохранять данные из form.cleaned_data - нормально, но избытачно.
если форма используется для управления объектом модели - УДОБНЕЕ использовать ModelForm, но это не обязательно

проще всего придерживаться догики такой: меняется модель - ModelForm, что-то происходит с несколькими моделями или вообще не меняются модели - Form.

    Nomad
    • Oct. 20, 2020, 2:17 p.m.
    • (edited)

    спасибо за исчерпывающий ответ.
    вы писали "использовать данные напрямую из request.POST - опасно и черевато" а чему чревато?
    ведь если мы берем данные из post, и обрабатываем, проверяем их и только после этого сохраняем

      Илья Чичак
      • Oct. 21, 2020, 4 a.m.
      • (edited)

      напрямую данные из POST - я имел в виду, без проверок и всего прочего

      черевато тем, что там могут быть какие-то плохие данные типа sql-инъекций

      а если их проверять и обрабатывать - зачем делать двойную работу (форма делает начальную валидацию по параметрам своих полей + возможность указать какие-то кастомные проверки в Form.clean())?
      + всетаки какое-никакое разделение ответственности:
      - представление вызывает форму и отдает ответы
      - форма делает все с данными

      в форме можно отпределить метод save(), который есть в ModelForm, или process() - чтобы не вызывать двойственность и потом не думать, что это ModelForm

      def my_view(request):  # это долгий, трудоемкий и опасный пусть
          form = MyForm()
          if request.method == 'POST':
              if request.POST.get('param1'):
                  <check it>
              if request.POST.get('param2'):
      
      
      def my_view(request):  # это трудоемкий пусть
          form = MyForm(request.POST or None)
          if form.is_valid():
              mymodel_instance.param = request.POST.get('param')
      
      
      def my_view(request):  # это более менее простой путь
          form = MyForm(request.POST or None)
          if form.is_valid():
              mymodel_instance.param = form.cleaned_data['param']
              ...
      
      
      def my_view(request):  # это, как мне кажется самый понятный и простой путь
          form = MyForm(request.POST or None)
          if form.is_valid():
              form.process() # или save() для ModelForm
              return ...
          return ...
      

      основная мысль - не надо мешать разную логику в одном месте
      пусть view - занимается отбработкой HTTP запросов, а формы - обработкой введеных данных

      опять же, если у тебя логика, которая подразумевается для выполнения над данными формы, используется где-то еще (например в API) - вынеси это в отдельную функцию, это уже получится "слой бизнес логики" (можно погуглить "services layer django"). Как по мне: ниже самый оптимальный вариант:

      # services.py
      
      def create_user(username, password):
          new_user = get_user_model().create_user(username=username, password=password)
          return new_user
      
      # forms.py
      
      class CreateUserForm(forms.Form):
          username = forms.CharField(...)
          password = forms.CharField(...)
          password_confirm = forms.CharField(...)
      
          def clean(self):
              cleaned_data = super().clean()
              if cleaned_data['password'] != cleaned_data['password_confirm']:
                  self.add_error('password_confirm', 'Should be same!')
              if get_user_model().objects.filter(username=cleaned_data['username']).first():
                  self.add_error('username', 'Already exists!')
              return cleaned_data
      
          def process(self):
              return create_user(self.cleaned_data['username'], self.cleaned_data['password'])
      
      # views.py
      
      def create_user(request):
          form = CreateUserForm(request.POST or None)
          if form.is_valid():
              new_user = form.process()
              login(request, new_user)
              return redirect(...)
          return render(request, 'template.html', {'form': form})
      

      это тебе позволит:
      1) быстро и просто локализовать ошибки
      2) покрыть тестами каждый функционал будет сильно проще
      3) просто будет расширять функционал

        Nomad
        • Oct. 21, 2020, 4:28 a.m.

        спасибо за WOW раскрытие теммы

          Comments

          Only authorized users can post comments.
          Please, Log in or Sign up
          B

          C++ - Test 002. Constants

          • Result:16points,
          • Rating points-10
          B

          C++ - Test 001. The first program and data types

          • Result:46points,
          • Rating points-6
          FL

          C++ - Test 006. Enumerations

          • Result:80points,
          • Rating points4
          Last comments
          k
          kmssrFeb. 9, 2024, 2:43 a.m.
          Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
          Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
          EVA
          EVADec. 25, 2023, 6:30 p.m.
          Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
          J
          JonnyJoDec. 25, 2023, 4:38 p.m.
          Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
          G
          GvozdikDec. 19, 2023, 5:01 a.m.
          Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
          Now discuss on the forum
          AC
          Alexandru CodreanuJan. 19, 2024, 7:57 p.m.
          QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…
          BlinCT
          BlinCTDec. 27, 2023, 4:57 p.m.
          Растягивать Image на парент по высоте Ну и само собою дял включения scrollbar надо чтобы был Flickable. Так что выходит как то так Flickable{ id: root anchors.fill: parent clip: true property url linkFile p…
          Дмитрий
          ДмитрийJan. 10, 2024, 12:18 p.m.
          Qt Creator загружает всю оперативную память Проблема решена. Удалось разобраться с помощью утилиты strace. Запустил ее: strace ./qtcreator Начал выводиться весь лог работы креатора. В один момент он начал считывать фай…
          Evgenii Legotckoi
          Evgenii LegotckoiDec. 12, 2023, 2:48 p.m.
          Побуквенное сравнение двух строк Добрый день. Там случайно не высылается этот сигнал textChanged ещё и при форматировани текста? Если решиать в лоб, то можно просто отключать сигнал/слотовое соединение внутри слота и …

          Follow us in social networks