在 Django-REST-framework 中为 ModelViewSet 使用 defaultRouter() 时重定向错误
Wrong redirects when using defaultRouter() for ModelViewSet in Django-REST-framework
我有一个 Django 项目,我在其中制作了 3 个不同的应用程序:"blog"、"users"、"api"。
这是一个可以使用模型 Post 发布消息的网站。我想使用 Django Rest API 来访问模型。它有效,但它与 "blog" 的 UpdateView 和 DeleteView 的一些重定向混淆。
我认为使用 DefaultRouter() 可能有问题?
当我尝试使用 blog/PostupdateView blog/PostDeleteView(继承自 UpdateView 和 DeleteView)视图时,我不断被重定向到 /api/blog/postid/ 而不是仅仅访问我的 detailView 路径应该只是 /blog/postid/
我不知道为什么。
我的Post型号:
class Post(models.Model):
...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
我的序列化程序:
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('id', 'title', 'content', 'date_posted', 'author', 'rooms')
我对 Post 的 api 视图:
class PostView(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
我的 urls 文件:
主要urls.py:
urlpatterns = [
...
path('', include('blog.urls')),
path('api/',include('api.urls')),
]
blog/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:
router = routers.DefaultRouter()
router.register('post', views.PostView)
urlpatterns = [
path('',include(router.urls))
]
my PostCreateView in blog/views.py
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):
...
当使用 PostCreateView 时,我应该被重定向到创建的 Post 的详细视图,如 Post 模型中所定义。相反,我被重定向到路由器在 api/urls.py
中生成的 api url
解决问题的一种简单方法是,将 get_absolute_url()
方法更改为
class Post(models.Model):
...
def __str__(self):
return self.title
<b>def get_absolute_url(self):
return "/blog/{}/".format(self.pk)</b>
更新
问题是什么?
您为 API 和常规视图定义了具有相同名称 post-detail
的 URL。您应该使用唯一名称命名 URL。
# blog/urls.py
urlpatterns = [
...
path('post/<int:pk>/', PostDetailView.as_view(), <b>name='blog-post-detail'</b>),
path('post/new/', PostCreateView.as_view(), <b>name='blog-post-create'</b>),
...
]
#models.py
class Post(models.Model):
...
def __str__(self):
return self.title
def get_absolute_url(self):
<b>return reverse('blog-post-detail', kwargs={'pk': self.pk})</b>
我是新手,无法发表评论,所以我会在已接受答案的评论中回答 OP 的问题,以供找到此内容的其他人使用。
当你向默认路由器注册路由时,Django 会自动为它们分配一组 url,格式为 {basename}-{something else}
,其中 {something else}
取决于关于您调用的操作和 HTTP 方法。基本名称由视图集的 queryset
属性决定(因此您的基本名称将为 post
)。
对于“GET”+“检索”操作,url 将是 {basename}-detail
,对于您的查询集,它会转换为 post-detail
,它会覆盖您的 post-detail
为非 api 视图定义。
您可以通过使用基本名称注册路由器来绕过它,因此非api post-detail
URL 名称将对应于 post/<pk>
URL,而{other basename}-detail
可以对应API视图:
router.register('post', views.PostView, basename='api-post')
我有一个 Django 项目,我在其中制作了 3 个不同的应用程序:"blog"、"users"、"api"。 这是一个可以使用模型 Post 发布消息的网站。我想使用 Django Rest API 来访问模型。它有效,但它与 "blog" 的 UpdateView 和 DeleteView 的一些重定向混淆。 我认为使用 DefaultRouter() 可能有问题?
当我尝试使用 blog/PostupdateView blog/PostDeleteView(继承自 UpdateView 和 DeleteView)视图时,我不断被重定向到 /api/blog/postid/ 而不是仅仅访问我的 detailView 路径应该只是 /blog/postid/ 我不知道为什么。
我的Post型号:
class Post(models.Model):
...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
我的序列化程序:
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('id', 'title', 'content', 'date_posted', 'author', 'rooms')
我对 Post 的 api 视图:
class PostView(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
我的 urls 文件:
主要urls.py:
urlpatterns = [
...
path('', include('blog.urls')),
path('api/',include('api.urls')),
]
blog/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:
router = routers.DefaultRouter()
router.register('post', views.PostView)
urlpatterns = [
path('',include(router.urls))
]
my PostCreateView in blog/views.py
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):
...
当使用 PostCreateView 时,我应该被重定向到创建的 Post 的详细视图,如 Post 模型中所定义。相反,我被重定向到路由器在 api/urls.py
中生成的 api url解决问题的一种简单方法是,将 get_absolute_url()
方法更改为
class Post(models.Model):
...
def __str__(self):
return self.title
<b>def get_absolute_url(self):
return "/blog/{}/".format(self.pk)</b>
更新
问题是什么?
您为 API 和常规视图定义了具有相同名称 post-detail
的 URL。您应该使用唯一名称命名 URL。
# blog/urls.py
urlpatterns = [
...
path('post/<int:pk>/', PostDetailView.as_view(), <b>name='blog-post-detail'</b>),
path('post/new/', PostCreateView.as_view(), <b>name='blog-post-create'</b>),
...
]
#models.py
class Post(models.Model):
...
def __str__(self):
return self.title
def get_absolute_url(self):
<b>return reverse('blog-post-detail', kwargs={'pk': self.pk})</b>
我是新手,无法发表评论,所以我会在已接受答案的评论中回答 OP 的问题,以供找到此内容的其他人使用。
当你向默认路由器注册路由时,Django 会自动为它们分配一组 url,格式为 {basename}-{something else}
,其中 {something else}
取决于关于您调用的操作和 HTTP 方法。基本名称由视图集的 queryset
属性决定(因此您的基本名称将为 post
)。
对于“GET”+“检索”操作,url 将是 {basename}-detail
,对于您的查询集,它会转换为 post-detail
,它会覆盖您的 post-detail
为非 api 视图定义。
您可以通过使用基本名称注册路由器来绕过它,因此非api post-detail
URL 名称将对应于 post/<pk>
URL,而{other basename}-detail
可以对应API视图:
router.register('post', views.PostView, basename='api-post')