带有更新的 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
有两个字段,name
和 slug
。 slug 字段<model_name_slug>
是从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_object
。 form_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通用视图Generic detail view PublisherList must be called with either an object pk or a slug
必须使用对象 pk 或 slug 调用通用详细视图 ProfileView