Nomad
Oct. 20, 2020, 7:20 p.m.

Django form vs modelForm

django, Form, modelform

всем привет.

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

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

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

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

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

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

2

Do you like it? Share on social networks!

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

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

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

    Nomad
    • Oct. 21, 2020, 1:17 a.m.
    • (edited)

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

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

      напрямую данные из 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
        • Oct. 21, 2020, 3:28 p.m.

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

          Comments

          Only authorized users can post comments.
          Please, Log in or Sign up
          • Last comments
          • AK
            April 1, 2025, 11:41 a.m.
            Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
          • Evgenii Legotckoi
            March 9, 2025, 9:02 p.m.
            К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
          • VP
            March 9, 2025, 4:14 p.m.
            Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
          • ИМ
            Nov. 22, 2024, 9:51 p.m.
            Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
          • Evgenii Legotckoi
            Oct. 31, 2024, 11:37 p.m.
            Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup