NextJS 13中Django的DetailView(获取数据)

3qpi33ja  于 2023-08-04  发布在  Go
关注(0)|答案(2)|浏览(91)

我有基于Django的应用程序作为我的后端,NextJS作为前端。我在Django App中有一个Post模型,有两个视图-PostDetailViewPostListView

from django.shortcuts import get_object_or_404
from django.template import TemplateDoesNotExist
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Post
from .serializers import PostSerializer
from rest_framework.renderers import JSONRenderer
from django.http import Http404, HttpResponse

class JSONResponse(HttpResponse):
def __init__(self, data, **kwargs):
    content = JSONRenderer().render(data)
    kwargs['content_type'] = 'application/json'
    super(JSONResponse, self).__init__(content, **kwargs)

class PostListView(APIView):
def get(self, request):
    posts = Post.objects.all()
    serializer = PostSerializer(posts, many=True)
    return JSONResponse(serializer.data)

class PostDetailView(APIView):
def get(self, request, pk):
    try:
        post = Post.objects.get(pk=pk)
        serializer = PostSerializer(post)
        return Response(serializer.data, status=status.HTTP_200_OK)
    except Post.DoesNotExist:
        raise Http404

字符串
我还建立了serializers.py和urls.py。

#serializers.py

from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
class Meta:
    model = Post
    fields = '__all__'

#urls.py
from django.contrib import admin
from django.urls import include, path

from . import views

urlpatterns = [
path('api/posts/', views.PostListView.as_view(), name='post-list'),
path('api/posts/<int:pk>/', views.PostDetailView.as_view(), name='post-detail'),
]


在我的NextJS应用程序中,我使用src/app的文件夹结构的新方法。这是我的文件夹结构。

- src/app
-- blog
--- page.tsx (here is my 'ListView')
-- [id]
--- page.tsx (here is my 'DetailView')


我的ListView工作正常,它显示了我所有的对象。

interface Post {
 id: number;
 title: string;
 image_url: string | null;
 content: string;
}

const PostsList: React.FC = () => {
const [posts, setPosts] = useState<Post[]>([]);

useEffect(() => {
 fetchData();
}, []);

 const fetchData = async () => {
    try {
     const response: AxiosResponse<Post[]> = await axios.get('http://127.0.0.1:8000/blog/api/posts/');
     const data: Post[] = response.data;
     setPosts(data);
   } catch (error) {
     console.error('Error fetching data:', error);
   }
 };

 return (

但我的DetailView有问题。我不知道该怎么展示。你对此有什么解决办法吗?

在本地主机上,我的链接看起来像这样:

#Django (rest API)
List View: http://127.0.0.1:8000/blog/api/posts/
Detail View: http://127.0.0.1:8000/blog/api/posts/2/ (where 2 is ID for my post)

#NextJS
List View: http://127.0.0.1:3000/blog
Detail View: http://127.0.0.1:3000/blog/2 (where 2 is ID form my post

**我试过这样的东西,不幸的是,它只显示'加载中...'这是我的信息不好取。

import React, { useEffect, useState } from 'react';
import axios, { AxiosResponse } from 'axios';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';

interface Post {
  id: number;
  title: string;
  image_url: string | null;
  content: string;
}

const PostDetail: React.FC = () => {
  const [post, setPost] = useState<Post | null>(null);

  const searchParams = useSearchParams()
  const id = searchParams.get('')

  const fetchData = async () => {
    try {
      const response: AxiosResponse<Post> = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
      const data: Post = response.data;
      setPost(data);
    } catch (error) {
      console.error('Error fetching data:', error);
    }
  };

  fetchData();

  if (!post) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1 className='font-6xl font-red-800'>{post.title}</h1>
        </div>
  );
};

export default PostDetail;

qlckcl4x

qlckcl4x1#

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

import React, { useEffect, useState } from 'react';
import axios, { AxiosResponse } from 'axios';
import { useRouter } from 'next/router';

interface Post {
  id: number;
  title: string;
  image_url: string | null;
  content: string;
}

const PostDetail: React.FC = () => {
  const [post, setPost] = useState<Post | null>(null);
  const router = useRouter();
  const { id } = router.query;

  useEffect(() => {
    if (id) {
      fetchData();
    }
  }, [id]);

  const fetchData = async () => {
    try {
      const response: AxiosResponse<Post> = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
      const data: Post = response.data;
      setPost(data);
    } catch (error) {

    }
  };

  if (!post) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1 className='font-6xl font-red-800'>{post.title}</h1>      
    </div>
  );
};

export default PostDetail;

字符串

hlswsv35

hlswsv352#

我已经找到解决办法了。

const [post, setPost] = useState<Post | null>(null);
const pathname = usePathname();
const id = pathname.split('/').pop();

useEffect(() => {
if (id) {
  fetchData();
}
}, [id]);

const fetchData = async () => {
try {
  const response: AxiosResponse<Post> = await axios.get(`http://127.0.0.1:8000/blog/api/posts/${id}/`);
  const data: Post = response.data;
  setPost(data);
} catch (error) {}
};

字符串

相关问题