在Django CreateView中创建对象后,如何添加指令?

问题描述

在基于通用类的CreateView上,我想执行一条指令,该指令根据与当前创建的对象相关的另一个模型创建新的对象。

示例:def fizzbuzz(numSize,&block) 1.upto(numSize).map do |num| if num % 15 == 0 "FizzBuzz" elsif num % 3 == 0 "Fizz" elsif num % 5 == 0 "Buzz" else num.to_s end end.map(&block) end 一个与3个不同的Collection对象相关的模型。当我创建与ElementMyCollection相关的Collection对象时,也必须创建3 User对象并与新创建的{{1} }对象。与MyElement相关的每个MyCollection之一。

Element

我使用的是Django的通用CreateView,经过一番研究,我发现可以通过重写get_success_url()方法在CreateView中执行其他操作。

在我的示例中,我做了类似的事情:

Collection
# models.py

from django.contrib.auth.models import User
from django.db import models


class Collection(models.Model):
    # attributes and methods...


class Element(models.Model):
    collection = models.ForeignKey(Collection,# more arguments...)
    # more attributes and methods


class MyCollection(models.Model):
    user = models.ForeignKey(User,# more arguments...)
    collection = = models.ForeignKey(Collection,# more arguments...)
    # more attributes and methods

    def get_absolute_url(self):
        reverse(# some url with the object pk)


class MyElement(models.Model):
    element = models.ForeignKey(Element,# more arguments...)
    my_collection = models.ForeignKey(MyCollection,# more arguments...)
    # more attributes and methods
# views.py

from django.views.generic import CreateView

from .utils import create_myelements_for_mycollection


class MyCollectionCreateView(CreateView):
    model = MyCollection
    # more attributes and methods...

    def get_success_url(self):
        create_myelements_for_mycollection(self.get_object())  # Here is where the bug occurs,works fine without this line

        return super().get_success_url()

当我创建一个新的# utils.py from .models import Collection,Element,MyCollection,MyElement def create_myelements_for_mycollection(my_collection): for element in my_collection.collection.elements_set.all(): MyElement.objects.create( element=element,my_collection=my_collection,) 对象时,所有# urls.py from django.urls import re_path from . import views urlpatterns = [ re_path( r"^myelement/l/$",views.MyElementListView.as_view(),),re_path( r"^myelement/r/(?P<pk>[0-9]+)/$",views.MyElementDetailView.as_view(),re_path( r"^myelement/c/(?P<element_pk>\d+)/$",views.MyElementCreateView.as_view(),re_path( r"^mycollection/l/$",views.MyCollectionListView.as_view(),re_path( r"^mycollection/r/(?P<pk>[0-9]+)/$",views.MyCollectionDetailView.as_view(),re_path( r"^mycollection/c/(?P<collection_pk>\d+)/$",views.MyCollectionCreateView.as_view(),] 都已在数据库中成功创建,但出现此错误

AttributeError:通用详细信息视图MyCollectionCreateView必须使用URLconf中的对象pk或slug调用

我不明白为什么。

我的CreateView网址没有任何pk,因为当您创建新对象时,它还没有pk。另外,MyCollection有自己的MyElements。没有该特定说明,我就可以正常工作。

有人可以向我解释导致错误的原因以及在对象创建之后是否有更好的方法来执行这样的指令?

谢谢您的帮助。

MyCollection

编辑

我尝试改用post_save信号(这实际上更容易编写),但是我却遇到了完全相同的错误

get_absolute_url

AttributeError:通用详细信息视图MyCollectionCreateView必须使用URLconf中的对象pk或slug调用

编辑2

通过从FYI: Django 3.1 Pyhton 3.8 类中删除# models.py from django.db.models.signals import post_save from django.dispatch import receiver from .utils import create_myelements_for_mycollection # ...models @receiver(post_save,sender=MyCollection) def create_myelements_for_mycollection(sender,instance,**kwargs): if instance is created: # ? (Didn't look at how to write this condition in a signal yet) create_myelements_for_mycollection(my_collection) 覆盖,它实际上可以工作。很好,但我仍然想知道问题出在哪里。如果这解决了问题,可能是我没看到的愚蠢。

get_absolute_url()

解决方法

get_absolute_url()用于为模型创建新实例,因为Django必须在创建新帖子或创建新实例时知道去向。

从错误

AttributeError:通用详细信息视图MyCollectionCreateView必须使用URLconf中的对象pk或slug调用。

它告诉您必须使用object pkslug来调用它,因此,URL的构造就是问题所在。我不确定方法create_myelements_for_mycollection()是否满足需要。

理想情况下,您需要的东西例如

def get_absolute_url(self):
    return f"/mycollection/{self.slug}/"

以上述模式生成URL,例如在锚标记中使用。