Сохранение данных в ModelForm Django
Первая проблема. Мне необходимо сохранить в БД экземпляр модели на основе POST-данных формы, но с условием, что author я беру не из формы (и даже поле такое в форму не вывожу), а из request.user.
В документации (https://docs.djangoproject.com/en/4.0/topics/forms/modelforms/#the-save-method) предлагается решение:
form = PartialAuthorForm(request.POST)
author = form.save(commit=False)
author.title = 'Mr'
author.save()
Как воспроизвести пример в консоли понятно, но где именно в моем приложении я должен реализовать такую логику? И как передать в форму request.user?
Вторая проблема. В дополнительном поле (tags_field), не связанном с моделью, я хочу предварительно обработать полученные от пользователя теги (маркеров): если такой тег уже есть в Marker, то просто добавить id тега в m2m Post. Если тега нет, то вначале создать и сохранить новый экземпляр модели Marker, и только потом добавить его в m2m Post. Вопрос аналогичный: где именно в приложении мне необходимо реализовывать эту логику?
Вот основные файлы приложения:
models.py
class Post(models.Model):
event_describe = models.TextField(max_length=2000)
event_location = models.CharField(max_length=50)
author = models.ForeignKey(User, on_delete=models.PROTECT)
tags = models.ManyToManyField(Marker)
class Marker(models.Model):
author = models.ForeignKey(User, on_delete=models.PROTECT)
form.py
class CreatePostForm(ModelForm):
tags_field=CharField(max_length=70)
class Meta:
model = Post
fields = ('event_describe', 'event_location')
views.py
class PostCreateView(CreateView):
template_name = 'add_post.html'
form_class = CreatePostForm
success_url = reverse_lazy('posts')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['author'] = self.request.user
return context
В функции вьюхи прописать что-то вида
if request.method == 'POST':
form=FormClass(request.POST)
obj=App(**form.cleaned_data)
obj.author='new author'
obj.save()
В функции вида создаём новый объект модели с данными из пост метода, затем изменяем нужную характеристику и сохраняем, не забывая про валидацию
Похоже разобрался
Нужно переопределить у PostCreateView метод form_valid(), который вызывает (в случае, если данные из формы успешно провалидированы) form.save() для сохранения экземпляра модели.
Здесь можно изменить стандартную логику работы вьюхи. В моем случае вот так работает:
def form_valid(self, form):
"""If the form is valid, firstly save with commit=False argument the associated model."""
self.object = form.save(commit=False)
self.object.author = self.request.user
self.object.save()
# возвращаем form_valid предка
return super().form_valid(form)
# или формируем response самостоятельно
#return HttpResponseRedirect(self.get_success_url())
Странно, что в официальной документации не пишут про это...