[英]Wrong redirects when using defaultRouter() for ModelViewSet in Django-REST-framework
I have a Django Project where i made 3 Different Apps: "blog", "users", "api".我有一个 Django 项目,我在其中制作了 3 个不同的应用程序:“博客”、“用户”、“api”。 It is a Website where messages can be posted by using a model Post.
这是一个可以使用模型 Post 发布消息的网站。 I want to use an Django Rest API for accessing the Model.
我想使用 Django Rest API 来访问模型。 It works, but it messes with some redirects of the UpdateView and DeleteView of "blog".
它有效,但它与“博客”的 UpdateView 和 DeleteView 的一些重定向混淆。 I think it could be a problem with using DefaultRouter() ?
我认为使用 DefaultRouter() 可能有问题?
When i try to use my blog/PostupdateView blog/PostDeleteView ( inherited from UpdateView and DeleteView) views, i keep getting redirected to /api/blog/postid/ instead of just accessing my detailView where the path should be just /blog/postid/ and i cannot figure out why.当我尝试使用我的 blog/PostupdateView blog/PostDeleteView(从 UpdateView 和 DeleteView 继承)视图时,我不断被重定向到/api/blog/postid/而不是仅仅访问我的 detailView 路径应该只是/blog/postid/我不知道为什么。
my Post Model:我的帖子模型:
class Post(models.Model):
...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
my Serializer:我的序列化器:
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('id', 'title', 'content', 'date_posted', 'author', 'rooms')
my api view for Post:我对 Post 的 api 视图:
class PostView(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
My urls Files:我的网址文件:
main urls.py:主要网址.py:
urlpatterns = [
...
path('', include('blog.urls')),
path('api/',include('api.urls')),
]
blog/urls.py:博客/urls.py:
urlpatterns = [
...
path('post/<int:pk>/', PostDetailView.as_view(),name='post-detail'),
path('post/new/', PostCreateView.as_view(),name='post-create'),
...
]
api/urls.py: api/urls.py:
router = routers.DefaultRouter()
router.register('post', views.PostView)
urlpatterns = [
path('',include(router.urls))
]
my PostCreateView in blog/views.py我在 blog/views.py 中的 PostCreateView
class PostCreateView( LoginRequiredMixin, UserPassesTestMixin, CreateView):
model = Post
fields = ['title', 'content', 'rooms']
def test_func(self):
...
def get_form(self, form_class=None):
...
def form_valid(self, form):
...
When using PostCreateView, i should be redirected to the detail-view of the created Post, as defined in the Post model.使用 PostCreateView 时,我应该被重定向到创建的 Post 的详细视图,如 Post 模型中定义的那样。 Instead im getting redirected to the api url that is generated by the router in api/urls.py
相反,我被重定向到由路由器在 api/urls.py 中生成的 api url
One of the easy methods to solve the issue is, change the get_absolute_url()
method as解决问题的一种简单方法是,将
get_absolute_url()
方法更改为
class Post(models.Model):
...
def __str__(self):
return self.title
def get_absolute_url(self): return "/blog/{}/".format(self.pk)
You are defined the URLs with the same name, post-detail
, for API and usual view.您为 API 和普通视图定义了具有相同名称的 URL,
post-detail
。 You should name the URLs with unique names.您应该使用唯一的名称来命名 URL。
# blog/urls.py
urlpatterns = [
...
path('post/<int:pk>/', PostDetailView.as_view(),
name='blog-post-detail'),
path('post/new/', PostCreateView.as_view(),
name='blog-post-create'),
...
]
#models.py
class Post(models.Model):
...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog-post-detail', kwargs={'pk': self.pk})
I am new and can't comment, so I'll answer OP's question in the comment on the accepted answer, for anyone else who find this.我是新手,无法发表评论,因此我将在对已接受答案的评论中回答 OP 的问题,供其他任何发现此问题的人使用。
When you register a route with the default router, Django will automatically assign a set of url's for them, which are in the format {basename}-{something else}
, where {something else}
depends on what action you called and the HTTP method.当您使用默认路由器注册路由时,Django 会自动为它们分配一组 url,格式为
{basename}-{something else}
,其中{something else}
取决于您调用的操作和 HTTP 方法. The basename is determined by the queryset
attribute of the viewset (so your basename would be post
). basename 由 viewset 的
queryset
属性确定(因此您的 basename 将是post
)。
For "GET" + "retrieve" action, the url will be {basename}-detail
, which for your queryset translated to post-detail
, which overrides the post-detail
you defined for the non-api view.对于 "GET" + "retrieve" 操作,url 将是
{basename}-detail
,它为您的查询集转换为post-detail
,它覆盖您为非 api 视图定义的post-detail
。
You can get around it by registering the router with a basename, so the non-api post-detail
URL name will correspond to the post/<pk>
URL, and {other basename}-detail
can correspond to the API view:你可以通过用basename注册路由器来绕过它,所以非api
post-detail
URL名称将对应post/<pk>
URL,而{other basename}-detail
可以对应API视图:
router.register('post', views.PostView, basename='api-post')
https://www.django-rest-framework.org/api-guide/routers/ https://www.django-rest-framework.org/api-guide/routers/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.