简体   繁体   English

在 Django-REST-framework 中为 ModelViewSet 使用 defaultRouter() 时重定向错误

[英]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)

UPDATE更新

What was the problem?出了什么问题?

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.

相关问题 在django-rest-framework中将HyperLink添加到ModelViewSet - Add a HyperLink in django-rest-framework to a ModelViewSet 如何在django-rest-framework的modelviewset中取消设置csrf? - How to unset csrf in modelviewset of django-rest-framework? 创建时向django-rest-framework ModelViewSet添加其他字段的最佳方法 - best way to add additional fields to django-rest-framework ModelViewSet when create django-rest-framework:使用相同的 ModelViewSet 渲染 HTML 和 JSON - django-rest-framework: Rendering both HTML and JSON with the same ModelViewSet django-rest-framework:在ModelViewSet中添加批量操作 - django-rest-framework: Adding bulk operation in a ModelViewSet 在 Django REST 框架中,将 ModelViewSet 与渲染器一起使用, - In Django REST Framework, Using ModelViewSet with renderers, Swagger 使用 DefaultRouter 在 Django Rest Framework 中仅打印字符串数据类型 - Swagger prints only string datatype in Django Rest Framework using DefaultRouter django-rest-framework如何决定`ModelViewSet`的默认`allowed_methods`应该是什么? - How does django-rest-framework decide what the default `allowed_methods` should be for a `ModelViewSet`? 使用django-rest-framework进行密码哈希处理? - Password hash using django-rest-framework? 使用API​​TestCase和django-rest-framework - using APITestCase with django-rest-framework
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM