Использование self.object в CreateView для создания объектов в других таблицах
Когда пользователь создает новый листинг с помощью CreateView
, я пытаюсь использовать этот новый объект для создания Bid
в таблице Bids
.
class ListingCreateView(CreateView):
model = Listing
fields = ['title', 'description', 'starting_bid', 'url']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def post(self, request, *args: Any, **kwargs: Any):
self.object = self.get_object()
starting_bid = self.request.POST['starting_bid']
Bids.objects.create(bid_value=starting_bid, bidder=self.request.user, item=self.object)
return super().post(request, *args, **kwargs)
Но он возвращает ошибку Generic detail view ListingCreateView must be called with either an object pk or a slug in the URLconf.
В docs говорится, что "При использовании CreateView вы имеете доступ к self.object, который является создаваемым объектом. Если объект еще не создан, значение будет None."
При использовании CreateView, когда self.object
будет содержать создаваемый объект? Как мне работать с объектом, который только что был создан в CreateView
?
Для такого поведения я настоятельно рекомендую использовать signals.py.
Ваш apps.py
from django.apps import AppConfig
class YourAppConfig(AppConfig):
name = 'your_app'
def ready(self):
import your_app.signals
signals.py (в той же папке)
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Bids, Listing
@receiver(post_save, sender=Listing)
def create_bids(sender, instance, created, **kwargs):
if created:
Bids.objects.create(bidder=instance.author, ...)
created
- переменная, добавленная из Django - True, если объект только что был создан, иначе False. instance
- это объект, который вы только что создали. Сигналы очень мощные и вы можете использовать их до и после сохранения, но имейте в виду, что не все здесь возможно.
Вы можете реализовать логику в методе .form_valid(…)
[Django-doc], например:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect
class ListingCreateView(LoginRequiredMixin, CreateView):
model = Listing
fields = ['title', 'description', 'starting_bid', 'url']
def form_valid(self, form):
form.instance.author = self.request.user
self.object = form.save()
Bids.objects.create(
bid_value=form.cleaned_data['starting_bid'],
bidder=self.request.user,
item=self.object
)
return HttpResponseRedirect(self.get_success_url())
Примечание: обычно модели Django дается сингулярное имя, поэтому
Bid
вместо.Bids
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin
mixin [Django-doc].