Nomad
20 октября 2020 г. 19:20

Django form vs modelForm

django, Form, modelform

всем привет.

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

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

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

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

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

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

2

Вам это нравится? Поделитесь в социальных сетях!

4
Илья Чичак
  • 20 октября 2020 г. 20:04
  • (ред.)
  • Ответ был помечен как решение.

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

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

    Nomad
    • 21 октября 2020 г. 1:17
    • (ред.)

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

      Илья Чичак
      • 21 октября 2020 г. 15:00
      • (ред.)

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

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

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

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

      1. def my_view(request): # это долгий, трудоемкий и опасный пусть
      2. form = MyForm()
      3. if request.method == 'POST':
      4. if request.POST.get('param1'):
      5. <check it>
      6. if request.POST.get('param2'):
      7.  
      8.  
      9. def my_view(request): # это трудоемкий пусть
      10. form = MyForm(request.POST or None)
      11. if form.is_valid():
      12. mymodel_instance.param = request.POST.get('param')
      13.  
      14.  
      15. def my_view(request): # это более менее простой путь
      16. form = MyForm(request.POST or None)
      17. if form.is_valid():
      18. mymodel_instance.param = form.cleaned_data['param']
      19. ...
      20.  
      21.  
      22. def my_view(request): # это, как мне кажется самый понятный и простой путь
      23. form = MyForm(request.POST or None)
      24. if form.is_valid():
      25. form.process() # или save() для ModelForm
      26. return ...
      27. return ...

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

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

      1. # services.py
      2.  
      3. def create_user(username, password):
      4. new_user = get_user_model().create_user(username=username, password=password)
      5. return new_user
      6.  
      7. # forms.py
      8.  
      9. class CreateUserForm(forms.Form):
      10. username = forms.CharField(...)
      11. password = forms.CharField(...)
      12. password_confirm = forms.CharField(...)
      13.  
      14. def clean(self):
      15. cleaned_data = super().clean()
      16. if cleaned_data['password'] != cleaned_data['password_confirm']:
      17. self.add_error('password_confirm', 'Should be same!')
      18. if get_user_model().objects.filter(username=cleaned_data['username']).first():
      19. self.add_error('username', 'Already exists!')
      20. return cleaned_data
      21.  
      22. def process(self):
      23. return create_user(self.cleaned_data['username'], self.cleaned_data['password'])
      24.  
      25. # views.py
      26.  
      27. def create_user(request):
      28. form = CreateUserForm(request.POST or None)
      29. if form.is_valid():
      30. new_user = form.process()
      31. login(request, new_user)
      32. return redirect(...)
      33. return render(request, 'template.html', {'form': form})

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

        Nomad
        • 21 октября 2020 г. 15:28

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

          Комментарии

          Только авторизованные пользователи могут публиковать комментарии.
          Пожалуйста, авторизуйтесь или зарегистрируйтесь
          • Последние комментарии
          • IscanderChe
            12 апреля 2025 г. 17:12
            Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
          • AK
            1 апреля 2025 г. 11:41
            Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
          • Evgenii Legotckoi
            9 марта 2025 г. 21:02
            К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
          • VP
            9 марта 2025 г. 16:14
            Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
          • ИМ
            22 ноября 2024 г. 21:51
            Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…