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



在我的基于泛型类的CreateView上,我想执行一条指令,从与当前创建的对象相关的另一个模型中创建新对象。

示例:Collection是一个与3个不同的Element对象相关的模型。当我创建一个与CollectionUser相关的MyCollection对象时,3MyElement对象也必须创建,并且与新创建的MyCollection对象相关。与CCD_ 9相关的每个CCD_。

# 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

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

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

# 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(),
),
]

当我创建一个新的MyCollection对象时,所有的MyElements都在数据库中成功创建,但我得到了这个错误:

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

我不明白为什么。

我的CreateView url没有任何pk,因为当你创建一个新对象时,它还没有pk。此外,MyCollection也有自己的get_absolute_url。没有那个具体的指导,我工作得很好。

有人能解释一下错误的原因吗?在创建对象后,是否有更好的方法来执行这样的指令?

谢谢你的帮助。

FYI:
Django 3.1
Pyhton 3.8

编辑

我试着使用postrongave信号(这实际上写起来更干净(,但我遇到了完全相同的错误。

# 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)

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

编辑2

通过从MyCollectionCreateView类中删除get_absolute_url()覆盖,它实际上是有效的。这很好,但我仍然想知道问题出在哪里。如果这解决了问题,可能是我没有看到的愚蠢的事情。

# models.py
# ... previous code
class MyCollectionCreateView(CreateView):
model = MyCollection
# more attributes and methods...
# Removing this solved the issue
# def get_success_url(self):
#     create_myelements_for_mycollection(self.get_object())
#
#     return super().get_success_url()
# more code ...

get_absolute_url()在为模型创建新实例时使用,因为django必须知道创建新帖子或创建新实例后该去哪里。

来自错误

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

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

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

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

以生成要在例如锚标签中使用的上述模式的CCD_ 20。

相关内容

最新更新