Использование 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 - это объект, который вы только что создали. Сигналы очень мощные и вы можете использовать их до и после сохранения, но имейте в виду, что не все здесь возможно.

Django Docs

Вы можете реализовать логику в методе .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].

Вернуться на верх