带有更新的 slug 的 Django 通用视图 UpdateView 重定向 URL

Posted

技术标签:

【中文标题】带有更新的 slug 的 Django 通用视图 UpdateView 重定向 URL【英文标题】:Django Generic View UpdateView redirect URL with updated slug 【发布时间】:2016-01-11 23:06:51 【问题描述】:

这是我的更新视图,由带有 slug 字段的 URL 调用,例如

/mymodel/update/<model_name_slug>/

MyModel 有两个字段,nameslug。 slug 字段&lt;model_name_slug&gt; 是从MyModel.name 自动生成的。如果用户更新它,将自动生成一个新的 slug 字段。然后,我想使用新生成的 slug 字段重定向到这个新 URL。

slug 字段自动生成正在工作。它在MyModelEditForm 中实现。但是,下面的代码将不起作用。原因是:

1) 用户输入此 URL 以更新现有模型

/mymodel/update/example-model

2) 用户将 Name 属性更改为 "example model changed"。然后 slug 字段将在MyModel 中生成为"example-model-changed"

3) 但是 URL 没有重定向到 "/mymodel/update/example-model-changed",因为 get_object() 将返回 None. get() 将无法将新生成的 URL "example-model-changed" 与原始 "example-model" 进行比较

我在下面的代码中缺少什么?我尝试使用self.object 访问新更新的对象,但出现以下错误:

 MyModelUpdateView object has no attribute 'object'

这里是sn-p的代码:

class MyModelUpdateView(LoginRequiredMixin, UpdateView):
    model = MyModel
    form_class = MyModelUpdateForm
    template_name = 'mymodel/update_mymodel.html'

    def get_success_url(self):
        view_name = 'update_mymodel'
        return reverse_lazy(view_name, kwargs='model_name_slug': self.kwargs.get('model_name_slug',''))

    def get_form_kwargs(self):
        '''
        This injects form with keyword arguments.
        '''
        kwargs = super(MyModelUpdateView, self).get_form_kwargs()
        #Update the kwargs with the user_id
        kwargs['user'] = self.request.user
        return kwargs

    def get(self, request, *args, **kwargs):
        # self.object = self.get_object()
        if self.request.path != self.object.get_absolute_url():
            return HttpResponseRedirect(self.object.get_absolute_url())
        else:
            return super(MyModelUpdateView, self).get(request,*args, **kwargs)
            # context = self.get_context_data(object=self.object)
            # return self.render_to_response(context)

    def get_object(self, queryset=None):
        instance = MyModel.objects.get(slug=self.kwargs.get('model_name_slug',''))
        return instance

即使正确更新了 get_success_url(),get_object() 似乎也有两个相互冲突的要求: 1) 能够使用现有的“example-model” slug 字段获取正确的对象; 2) 能够在现有 URL 未重定向之前使用新生成的“example-model-changed”获取更新的对象。

【问题讨论】:

顺便说一句,我认为如果您在视图上设置slug_url_kwarg = 'model_name_slug',您将不必覆盖get_object 方法。 你的意思是slug_url_kwarg会自动成为get_success_url中新生成的slug字段吗? 不,这与在get_success_url 中获取蛞蝓是分开的 - 为此,请参阅下面的答案。您已覆盖 get_object,但您不必这样做,只需将 slug_url_kwarg = 'model_name_slug' 设置为类属性即可。 谢谢。我会试一试,让你知道。顺便说一句,我想出了另一种方法来做到这一点,并将其发布在下面 【参考方案1】:

您不必在get_success_url 方法中使用self.get_objectform_valid()在保存表单时设置self.object,所以你可以使用self.object.slug获取新的url。

def get_success_url(self):
    view_name = 'update_mymodel'
    # No need for reverse_lazy here, because it's called inside the method
    return reverse(view_name, kwargs='model_name_slug': self.object.slug)

【讨论】:

这行得通。这里需要注意的一点是,顺序是 --> form_valid() --> 里面有 save() --> 保存后有 HttpResponseRedirect(self.get_success_url()) ,你可以在这里使用更新的蛞蝓(来自 self.object.slug)。【参考方案2】:

没有太多使用基于类的视图,但是..

def get_success_url(self):
        view_name = 'update_mymodel'
        return reverse_lazy(view_name, kwargs='model_name_slug': self.kwargs.get('model_name_slug',''))

如果 get_success_url 应该返回您想要将用户重定向到的 url,您不应该使用更新的 slug 而不是旧的吗?

self.get_object().model_name_slug

我猜这是在 atm 正确完成的。

1) 能够使用现有的“示例模型”获取正确的对象 蛞蝓场;

您希望根据更新的重定向模型获取更新的 url。您在哪里创建更新的网址? get_success_url?.那我不明白为什么reverse_lazy(view_name, kwargs='model_name_slug': self.get_object().model_name_slug) 不起作用?

2) 能够使用新生成的获取更新的对象 "example-model-changed" 在现有 URL 没有被重定向之前。

【讨论】:

self.get_object() 将无法返回更新后的对象 然后更改 get_object() 以使用更新的 slug 而不是 kwarg 的 我认为您不需要使用reverse_lazy,除非您将结果分配给类变量。改为用户reverse【参考方案3】:

感谢 Alasdair 和 eugene 的快速帮助。

与此同时,我想出了另一种方法来做到这一点!也就是说,在 URL 中使用两个参数,例如 和 。

在 *** 网址中查找。你注意到类似的事情了吗?是的,就是这样。我猜33115530是pk。剩下的就是 slug field 自动生成了!

然后,在get_object中,会通过 获取新更新的对象,get_success_url可以使用对象中更新的新slug字段。

【讨论】:

以上是关于带有更新的 slug 的 Django 通用视图 UpdateView 重定向 URL的主要内容,如果未能解决你的问题,请参考以下文章

将 Pk 或 Slug 传递给 Django 中的通用 DetailView?

Django:两个模型中的一个 url 搜索(cbv)

django通用视图Generic detail view PublisherList must be called with either an object pk or a slug

必须使用对象 pk 或 slug 调用通用详细视图 ProfileView

通用详细视图 UserProfileDetailView 必须在 URLconf 中使用对象 pk 或 slug 调用

如何在 Django 通用列表视图类中使用 slugfield 创建链接?