DetailView从Django在NextJS 13中(获取数据)

huangapple go评论113阅读模式
英文:

DetailView from Django in NextJS 13 (fetching data)

问题

我有一个基于Django的后端应用程序,以及一个前端使用NextJS的应用程序。在我的Django应用程序中,我有一个名为Post的模型,其中包含两个视图 - PostDetailViewPostListView

  1. from django.shortcuts import get_object_or_404
  2. from django.template import TemplateDoesNotExist
  3. from rest_framework.views import APIView
  4. from rest_framework.response import Response
  5. from rest_framework import status
  6. from .models import Post
  7. from .serializers import PostSerializer
  8. from rest_framework.renderers import JSONRenderer
  9. from django.http import Http404, HttpResponse
  10. class JSONResponse(HttpResponse):
  11. def __init__(self, data, **kwargs):
  12. content = JSONRenderer().render(data)
  13. kwargs['content_type'] = 'application/json'
  14. super(JSONResponse, self).__init__(content, **kwargs)
  15. class PostListView(APIView):
  16. def get(self, request):
  17. posts = Post.objects.all()
  18. serializer = PostSerializer(posts, many=True)
  19. return JSONResponse(serializer.data)
  20. class PostDetailView(APIView):
  21. def get(self, request, pk):
  22. try:
  23. post = Post.objects.get(pk=pk)
  24. serializer = PostSerializer(post)
  25. return Response(serializer.data, status=status.HTTP_200_OK)
  26. except Post.DoesNotExist:
  27. raise Http404

我还设置了serializers.pyurls.py

  1. # serializers.py
  2. from rest_framework import serializers
  3. from .models import Post
  4. class PostSerializer(serializers.ModelSerializer):
  5. class Meta:
  6. model = Post
  7. fields = '__all__'
  8. # urls.py
  9. from django.contrib import admin
  10. from django.urls import include, path
  11. from . import views
  12. urlpatterns = [
  13. path('api/posts/', views.PostListView.as_view(), name='post-list'),
  14. path('api/posts/<int:pk>/', views.PostDetailView.as_view(), name='post-detail'),
  15. ]

在我的NextJS应用程序中,我正在使用一种新的文件夹结构,位于src/app。这是我的文件夹结构。

  1. - src/app
  2. -- blog
  3. --- page.tsx (这是我的 'ListView')
  4. -- [id]
  5. --- page.tsx (这是我的 'DetailView')

我的ListView运行良好,它显示了所有对象。

  1. interface Post {
  2. id: number;
  3. title: string;
  4. image_url: string | null;
  5. content: string;
  6. }
  7. const PostsList: React.FC = () => {
  8. const [posts, setPosts] = useState<Post[]>([]);
  9. useEffect(() => {
  10. fetchData();
  11. }, []);
  12. const fetchData = async () => {
  13. try {
  14. const response: AxiosResponse<Post[]> = await axios.get('http://127.0.0.1:8000/blog/api/posts/');
  15. const data: Post[] = response.data;
  16. setPosts(data);
  17. } catch (error) {
  18. console.error('Error fetching data:', error);
  19. }
  20. };
  21. return (
  22. // 返回你的ListView组件部分
  23. );
  24. };

但是我在DetailView中遇到了问题。我不知道如何显示它。你有解决这个问题的方法吗?

在本地主机上,我的链接如下:

  1. #Django (rest API)
  2. List View: http://127.0.0.1:8000/blog/api/posts/
  3. Detail View: http://127.0.0.1:8000/blog/api/posts/2/(其中2是我的帖子ID)
  4. #NextJS
  5. List View: http://127.0.0.1:3000/blog
  6. Detail View: http://127.0.0.1:3000/blog/2(其中2是我的帖子ID)

我尝试了类似于这样的东西,不幸的是它只显示“Loading...”,这是我无法获取数据的信息。

  1. import React, { useEffect, useState } from 'react';
  2. import axios, { AxiosResponse } from 'axios';
  3. import { usePathname, useRouter, useSearchParams } from 'next/navigation';
  4. interface Post {
  5. id: number;
  6. title: string;
  7. image_url: string | null;
  8. content: string;
  9. }
  10. const PostDetail: React.FC = () => {
  11. const [post, setPost] = useState<Post | null>(null);
  12. const searchParams = useSearchParams()
  13. const id = searchParams.get('')
  14. const fetchData = async () => {
  15. try {
  16. const response: AxiosResponse<Post> = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
  17. const data: Post = response.data;
  18. setPost(data);
  19. } catch (error) {
  20. console.error('Error fetching data:', error);
  21. }
  22. };
  23. fetchData();
  24. if (!post) {
  25. return <div>Loading...</div>;
  26. }
  27. return (
  28. // 返回你的DetailView组件部分
  29. );
  30. };
  31. export default PostDetail;

希望这些部分对你有所帮助。

英文:

I've got Django based app as my back-end, and NextJS as front-end. I've got a Post model in my Django App with two views - PostDetailView and PostListView.

  1. from django.shortcuts import get_object_or_404
  2. from django.template import TemplateDoesNotExist
  3. from rest_framework.views import APIView
  4. from rest_framework.response import Response
  5. from rest_framework import status
  6. from .models import Post
  7. from .serializers import PostSerializer
  8. from rest_framework.renderers import JSONRenderer
  9. from django.http import Http404, HttpResponse
  10. class JSONResponse(HttpResponse):
  11. def __init__(self, data, **kwargs):
  12. content = JSONRenderer().render(data)
  13. kwargs[&#39;content_type&#39;] = &#39;application/json&#39;
  14. super(JSONResponse, self).__init__(content, **kwargs)
  15. class PostListView(APIView):
  16. def get(self, request):
  17. posts = Post.objects.all()
  18. serializer = PostSerializer(posts, many=True)
  19. return JSONResponse(serializer.data)
  20. class PostDetailView(APIView):
  21. def get(self, request, pk):
  22. try:
  23. post = Post.objects.get(pk=pk)
  24. serializer = PostSerializer(post)
  25. return Response(serializer.data, status=status.HTTP_200_OK)
  26. except Post.DoesNotExist:
  27. raise Http404

I've also set up serializers.py and urls.py.

  1. #serializers.py
  2. from rest_framework import serializers
  3. from .models import Post
  4. class PostSerializer(serializers.ModelSerializer):
  5. class Meta:
  6. model = Post
  7. fields = &#39;__all__&#39;
  8. #urls.py
  9. from django.contrib import admin
  10. from django.urls import include, path
  11. from . import views
  12. urlpatterns = [
  13. path(&#39;api/posts/&#39;, views.PostListView.as_view(), name=&#39;post-list&#39;),
  14. path(&#39;api/posts/&lt;int:pk&gt;/&#39;, views.PostDetailView.as_view(), name=&#39;post-detail&#39;),
  15. ]

In my NextJS App I'm using new approach for folder structure with src/app. This is my folder structure.

  1. - src/app
  2. -- blog
  3. --- page.tsx (here is my &#39;ListView&#39;)
  4. -- [id]
  5. --- page.tsx (here is my &#39;DetailView&#39;)

My ListView works fine, it displays all my objects.

  1. interface Post {
  2. id: number;
  3. title: string;
  4. image_url: string | null;
  5. content: string;
  6. }
  7. const PostsList: React.FC = () =&gt; {
  8. const [posts, setPosts] = useState&lt;Post[]&gt;([]);
  9. useEffect(() =&gt; {
  10. fetchData();
  11. }, []);
  12. const fetchData = async () =&gt; {
  13. try {
  14. const response: AxiosResponse&lt;Post[]&gt; = await axios.get(&#39;http://127.0.0.1:8000/blog/api/posts/&#39;);
  15. const data: Post[] = response.data;
  16. setPosts(data);
  17. } catch (error) {
  18. console.error(&#39;Error fetching data:&#39;, error);
  19. }
  20. };
  21. return (

But I've got a problem with my DetailView. I don't know how display this. Have you got any solutions for this?

On local host my link look like this:

  1. #Django (rest API)
  2. List View: http://127.0.0.1:8000/blog/api/posts/
  3. Detail View: http://127.0.0.1:8000/blog/api/posts/2/ (where 2 is ID for my post)
  4. #NextJS
  5. List View: http://127.0.0.1:3000/blog
  6. Detail View: http://127.0.0.1:3000/blog/2 (where 2 is ID form my post

I've tried with something like this, unfortunetly it displays only 'Loading...' which is my info for bad fetching.

  1. import React, { useEffect, useState } from &#39;react&#39;;
  2. import axios, { AxiosResponse } from &#39;axios&#39;;
  3. import { usePathname, useRouter, useSearchParams } from &#39;next/navigation&#39;;
  4. interface Post {
  5. id: number;
  6. title: string;
  7. image_url: string | null;
  8. content: string;
  9. }
  10. const PostDetail: React.FC = () =&gt; {
  11. const [post, setPost] = useState&lt;Post | null&gt;(null);
  12. const searchParams = useSearchParams()
  13. const id = searchParams.get(&#39;&#39;)
  14. const fetchData = async () =&gt; {
  15. try {
  16. const response: AxiosResponse&lt;Post&gt; = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
  17. const data: Post = response.data;
  18. setPost(data);
  19. } catch (error) {
  20. console.error(&#39;Error fetching data:&#39;, error);
  21. }
  22. };
  23. fetchData();
  24. if (!post) {
  25. return &lt;div&gt;Loading...&lt;/div&gt;;
  26. }
  27. return (
  28. &lt;div&gt;
  29. &lt;h1 className=&#39;font-6xl font-red-800&#39;&gt;{post.title}&lt;/h1&gt;
  30. &lt;/div&gt;
  31. );
  32. };
  33. export default PostDetail;

答案1

得分: 0

你正在从Next.js的URL中获取帖子ID。由于你正在使用文件结构[id]/page.tsx,Next.js将自动在查询参数中填充id值。你可以使用next/router中的useRouter hook从查询参数中获取id:

  1. import React, { useEffect, useState } from 'react';
  2. import axios, { AxiosResponse } from 'axios';
  3. import { useRouter } from 'next/router';
  4. interface Post {
  5. id: number;
  6. title: string;
  7. image_url: string | null;
  8. content: string;
  9. }
  10. const PostDetail: React.FC = () => {
  11. const [post, setPost] = useState<Post | null>(null);
  12. const router = useRouter();
  13. const { id } = router.query;
  14. useEffect(() => {
  15. if (id) {
  16. fetchData();
  17. }
  18. }, [id]);
  19. const fetchData = async () => {
  20. try {
  21. const response: AxiosResponse<Post> = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
  22. const data: Post = response.data;
  23. setPost(data);
  24. } catch (error) {
  25. }
  26. };
  27. if (!post) {
  28. return <div>Loading...</div>;
  29. }
  30. return (
  31. <div>
  32. <h1 className='font-6xl font-red-800'>{post.title}</h1>
  33. </div>
  34. );
  35. };
  36. export default PostDetail;

请注意,这是你提供的代码的中文翻译。

英文:

You are getting the post ID from the URL in Next.js. Since you are using the file structure [id]/page.tsx, Next.js will automatically populate the id value in the query parameter. You can get the id from the query parameter with useRouter hook from next/router:

  1. import React, { useEffect, useState } from &#39;react&#39;;
  2. import axios, { AxiosResponse } from &#39;axios&#39;;
  3. import { useRouter } from &#39;next/router&#39;;
  4. interface Post {
  5. id: number;
  6. title: string;
  7. image_url: string | null;
  8. content: string;
  9. }
  10. const PostDetail: React.FC = () =&gt; {
  11. const [post, setPost] = useState&lt;Post | null&gt;(null);
  12. const router = useRouter();
  13. const { id } = router.query;
  14. useEffect(() =&gt; {
  15. if (id) {
  16. fetchData();
  17. }
  18. }, [id]);
  19. const fetchData = async () =&gt; {
  20. try {
  21. const response: AxiosResponse&lt;Post&gt; = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
  22. const data: Post = response.data;
  23. setPost(data);
  24. } catch (error) {
  25. }
  26. };
  27. if (!post) {
  28. return &lt;div&gt;Loading...&lt;/div&gt;;
  29. }
  30. return (
  31. &lt;div&gt;
  32. &lt;h1 className=&#39;font-6xl font-red-800&#39;&gt;{post.title}&lt;/h1&gt;
  33. &lt;/div&gt;
  34. );
  35. };
  36. export default PostDetail;

答案2

得分: 0

I've found solutions for this one.

  1. const [post, setPost] = useState<Post | null>(null);
  2. const pathname = usePathname();
  3. const id = pathname.split('/').pop();
  4. useEffect(() => {
  5. if (id) {
  6. fetchData();
  7. }
  8. }, [id]);
  9. const fetchData = async () => {
  10. try {
  11. const response: AxiosResponse<Post> = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
  12. const data: Post = response.data;
  13. setPost(data);
  14. } catch (error) {}
  15. };

(Note: The code is provided without translation as per your request.)

英文:

I've found solutions for this one.

  1. const [post, setPost] = useState&lt;Post | null&gt;(null);
  2. const pathname = usePathname();
  3. const id = pathname.split(&#39;/&#39;).pop();
  4. useEffect(() =&gt; {
  5. if (id) {
  6. fetchData();
  7. }
  8. }, [id]);
  9. const fetchData = async () =&gt; {
  10. try {
  11. const response: AxiosResponse&lt;Post&gt; = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
  12. const data: Post = response.data;
  13. setPost(data);
  14. } catch (error) {}
  15. };

huangapple
  • 本文由 发表于 2023年7月23日 22:16:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76748706.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定