django rest framework

本文详细介绍如何使用Django Rest Framework(DRF)逐步构建一个图书管理系统,包括基础代码搭建、序列化器优化、视图与路由配置、认证权限设置、关联模型处理、超链接API设计、分页实现以及视图集与路由器的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码有繁琐到精炼:

目录

1.基础代码

2.serializers.py优化

3.Requests and Responses  views.py及urls.py优化

3.1 views.py   @api_view  函数视图

3.2 urls.py  接口文档

4.Class-based Views

4.1views.py   APIView

4.2 urls.py

5.视图使用 mixins 

6.views.py  使用基于类的通用视图

7.认证和权限

7.1 添加字段operator 录入者  models.py 

7.2  serializers.py 变动

7.3 views.py 只有登录才可以查看  permissions

8.两个关联model示例

8.1 views.py

8.2  serializers.py   设置书籍的出版社为汉字 publisher=...

8.3 urls.py 

9.关系和超链接API

9.1 serializers.py 

9.2 urls.py  name=..

10.为API的根创建端点及分页

10.1 在app01 APP中创建urls.py

10.2 restproject APP的urls.py 修改

10.3 views.py 新增代码段

10.4 settings.py新增代码段

11视图集和路由器

11.1 views.py

11.2 serializers.py

11.3  app01的urls.py

12.更改路径

12.1 restproject的路径

12.2app01的urls.py

 


models.py

from django.db import models

# Create your models here.
class Books(models.Model):
    name = models.CharField(max_length=32, verbose_name="书名")
    publisher = models.ForeignKey("Publishers")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "书籍"
        verbose_name_plural = verbose_name


class Publishers(models.Model):
    name = models.CharField(max_length=32, verbose_name="出版社名称")
    address = models.CharField(max_length=128, verbose_name="出版社地址")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "出版社"
        verbose_name_plural = verbose_name

1.基础代码

views.py

from django.shortcuts import render
from django.http import HttpResponse
from django.forms.models import model_to_dict
from django.core import serializers
from .models import Publishers, Books
from .serializers import PublishersSerializer
import json
# Create your views here.
def publisher_list(request):
    queryset = Publishers.objects.all()
    # data = []
    # for i in queryset:
    #     temp = {
    #         'name': i.name,
    #         'address': i.address
    #     }
    #     data.append(temp)

    # data = []
    # model_to_dict 对于图片等字段无法转换
    # for i in queryset:
    #     data.append(model_to_dict(i))

    # serialize已经把data转换成json格式
    # data = serializers.serialize("json", queryset)
    # return HttpResponse(data, content_type="application/json")

    s=PublishersSerializer(queryset,many=True)

    return HttpResponse(json.dumps(s.data), content_type="application/json")

urls.py

from django.conf.urls import url, include
from django.contrib import admin
from app01.views import publisher_list

urlpatterns = [
    url(r'^publishers/$', publisher_list),
    url(r'^admin/', admin.site.urls),
]

serializers.py

# -*- coding: utf-8 -*-
from rest_framework import serializers
from .models import Books, Publishers
class PublishersSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(required=False, max_length=32)
    address = serializers.CharField(required=False, max_length=128)

    def create(self, validated_data):
        return Publishers.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.address = validated_data.get('address', instance.address)
        instance.save()
        return instance

2.serializers.py优化

# -*- coding: utf-8 -*-
from rest_framework import serializers
from .models import Books, Publishers

class PublisherSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publishers
        fields = (
            'id', 'name', 'address'
        )

3.Requests and Responses  views.py及urls.py优化

3.1 views.py   @api_view  函数视图

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Publishers, Books
from .serializers import PublisherSerializer

@api_view(['GET', 'POST'])
def publisher_list(request):
    """
    列出所有的出版社 或创建新的出版社
    """
    if request.method == 'GET':
        queryset = Publishers.objects.all()
        s = PublisherSerializer(queryset, many=True)
        return Response(s.data)

    elif request.method == 'POST':
        s = PublisherSerializer(data=request.data)
        if s.is_valid():
            s.save()
            return Response(s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def publisher_detail(request,pk):
    try:
        s = Publishers.objects.get(pk=pk)
    except Publishers.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = PublisherSerializer(s)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = PublisherSerializer(s, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        s.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

3.2 urls.py  接口文档

from rest_framework.documentation import include_docs_urls
from django.conf.urls import url, include
from django.contrib import admin
from app01.views import publisher_list, publisher_detail

urlpatterns = [
    url(r'^docs/', include_docs_urls(title="图书管理系统")),
    url(r'^publishers/$', publisher_list),
    url(r'^publishers/(?P<pk>[0-9]+)$', publisher_detail),
    url(r'^admin/', admin.site.urls),
]

4.Class-based Views

4.1views.py   APIView

from django.http import Http404
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Publishers, Books
from .serializers import PublisherSerializer

class PublishersList(APIView):
    """
    列出所有的出版社 或创建新的出版社
    """
    def get(self, request, format=None):
        queryset = Publishers.objects.all()
        s = PublisherSerializer(queryset, many=True)
        return Response(s.data)

    def post(self, request, format=None):
        s = PublisherSerializer(data=request.data)
        if s.is_valid():
            s.save()
            return Response(s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)


class PublishersDetail(APIView):
    """
    Retrieve, update or delete a snippet instance.
    """
    def get_object(self, pk):
        try:
            return Publishers.objects.get(pk=pk)
        except Publishers.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        publisher = self.get_object(pk)
        s = PublisherSerializer(publisher)
        return Response(s.data)

    def put(self, request, pk, format=None):
        publisher = self.get_object(pk)
        s = PublisherSerializer(publisher, data=request.data)
        if s.is_valid():
            s.save()
            return Response(s.data)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        publisher = self.get_object(pk)
        publisher.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

4.2 urls.py

from rest_framework.documentation import include_docs_urls
from django.conf.urls import url, include
from django.contrib import admin
from app01.views import PublishersList, PublishersDetail

urlpatterns = [
    url(r'^docs/', include_docs_urls(title="图书管理系统")),
    url(r'^publishers/$', PublishersList.as_view()),
    url(r'^publishers/(?P<pk>[0-9]+)/$', PublishersDetail.as_view()),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^admin/', admin.site.urls),
]

5.视图使用 mixins 

from rest_framework import mixins
from rest_framework import generics
from .models import Publishers, Books
from .serializers import PublisherSerializer


class PublisherList(mixins.ListModelMixin,
                    mixins.CreateModelMixin,
                    generics.GenericAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class PublisherDetail(mixins.RetrieveModelMixin,
                      mixins.UpdateModelMixin,
                      mixins.DestroyModelMixin,
                      generics.GenericAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

6.views.py  使用基于类的通用视图

from rest_framework import generics
from .models import Publishers, Books
from .serializers import PublisherSerializer


class PublisherList(generics.ListCreateAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer


class PublisherDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer

7.认证和权限

7.1 添加字段operator 录入者  models.py 

from django.db import models

# Create your models here.
class Books(models.Model):
    name = models.CharField(max_length=32, verbose_name="书名")
    publisher = models.ForeignKey("Publishers")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "书籍"
        verbose_name_plural = verbose_name


class Publishers(models.Model):
    name = models.CharField(max_length=32, verbose_name="出版社名称")
    address = models.CharField(max_length=128, verbose_name="出版社地址")
    operator = models.ForeignKey("auth.User")

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "出版社"
        verbose_name_plural = verbose_name

7.2  serializers.py 变动

# -*- coding: utf-8 -*-
from rest_framework import serializers
from .models import Books, Publishers


class PublisherSerializer(serializers.ModelSerializer):
    operator = serializers.ReadOnlyField(source='operator.username')
    class Meta:
        model = Publishers
        fields = (
            'id', 'name', 'address', 'operator'
        )

7.3 views.py 只有登录才可以查看  permissions

from rest_framework import generics, permissions
from .models import Publishers, Books
from .serializers import PublisherSerializer


class PublisherList(generics.ListCreateAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer
    permission_classes = (permissions.IsAuthenticated,)


class PublisherDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer
    permission_classes = (permissions.IsAuthenticated,)

7.4 views.py 只有创建该出版社的用户可以修改,其他用户只看查看

7.4.1permissions.py(新增)

# -*- coding: utf-8 -*-
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True

        return obj.operator == request.user

7.4.2 views.py

from rest_framework import generics, permissions
from .models import Publishers, Books
from .serializers import PublisherSerializer
from .permissions import IsOwnerOrReadOnly


class PublisherList(generics.ListCreateAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer
    permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly)

    def perform_create(self, serializer):
        serializer.save(operator=self.request.user)


class PublisherDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer
    permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly)

8.两个关联model示例

8.1 views.py

from rest_framework import generics, permissions
from .models import Publishers, Books
from .serializers import PublisherSerializer, BookSerializer
from .permissions import IsOwnerOrReadOnly


class PublisherList(generics.ListCreateAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer
    permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly)

    def perform_create(self, serializer):
        serializer.save(operator=self.request.user)


class PublisherDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer
    permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly)


class BookList(generics.ListCreateAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializer
    permission_classes = (permissions.IsAuthenticated,)


class BookDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Books.objects.all()
    serializer_class = BookSerializer
    permission_classes = (permissions.IsAuthenticated,)

8.2  serializers.py   设置书籍的出版社为汉字 publisher=...

# -*- coding: utf-8 -*-
from rest_framework import serializers
from .models import Books, Publishers

class PublisherSerializer(serializers.ModelSerializer):
    operator = serializers.ReadOnlyField(source='operator.username')

    class Meta:
        model = Publishers
        fields = (
            'id', 'name', 'address', 'operator'
        )


class BookSerializer(serializers.ModelSerializer):
    publisher=serializers.StringRelatedField(source="publisher.name")
    class Meta:
        model = Books
        fields = "__all__"

8.3 urls.py 

from rest_framework.documentation import include_docs_urls
from django.conf.urls import url, include
from django.contrib import admin
from app01.views import PublisherList, PublisherDetail, BookList, BookDetail

urlpatterns = [
    url(r'^docs/', include_docs_urls(title="图书管理系统")),
    url(r'^publishers/$', PublisherList.as_view()),
    url(r'^publishers/(?P<pk>[0-9]+)/$', PublisherDetail.as_view()),
    url(r'^books/$', BookList.as_view()),
    url(r'^books/(?P<pk>[0-9]+)/$', BookDetail.as_view()),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^admin/', admin.site.urls),
]

9.关系和超链接API

9.1 serializers.py 

# -*- coding: utf-8 -*-
from rest_framework import serializers
from .models import Books, Publishers

class PublisherSerializer(serializers.ModelSerializer):
    operator = serializers.ReadOnlyField(source='operator.username')

    class Meta:
        model = Publishers
        fields = (
            'id', 'name', 'address', 'operator'
        )


class BookSerializer(serializers.HyperlinkedModelSerializer):
    publisher = serializers.HyperlinkedRelatedField(view_name='publisher-detail', read_only=True)
    class Meta:
        model = Books
        fields = (
            'id', 'name', 'publisher'
        )

9.2 urls.py  name=..

from rest_framework.documentation import include_docs_urls
from django.conf.urls import url, include
from django.contrib import admin
from app01.views import PublisherList, PublisherDetail, BookList, BookDetail

urlpatterns = [
    url(r'^docs/', include_docs_urls(title="图书管理系统")),
    url(r'^publishers/$', PublisherList.as_view(), name="publisher-list"),
    url(r'^publishers/(?P<pk>[0-9]+)/$', PublisherDetail.as_view(), name="publisher-detail"),
    url(r'^books/$', BookList.as_view(), name="book-list"),
    url(r'^books/(?P<pk>[0-9]+)/$', BookDetail.as_view(), name="book-detail"),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    url(r'^admin/', admin.site.urls),
]

10.为API的根创建端点及分页

10.1 在app01 APP中创建urls.py

from django.conf.urls import url, include
from app01.views import PublisherList, PublisherDetail, BookList, BookDetail, api_root

urlpatterns = [
    url(r'^$', api_root),
    url(r'^publishers/$', PublisherList.as_view(), name="publisher-list"),
    url(r'^publishers/(?P<pk>[0-9]+)/$', PublisherDetail.as_view(), name="publisher-detail"),
    url(r'^books/$', BookList.as_view(), name="book-list"),
    url(r'^books/(?P<pk>[0-9]+)/$', BookDetail.as_view(), name="book-detail"),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

10.2 restproject APP的urls.py 修改

from rest_framework.documentation import include_docs_urls
from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^api/', include("app01.urls")),
    url(r'^docs/', include_docs_urls(title="图书管理系统")),
    url(r'^admin/', admin.site.urls),
]

10.3 views.py 新增代码段

@api_view(['GET'])
def api_root(request, format=None):
    return Response({
        'books': reverse('book-list', request=request, format=format),
        'publishers': reverse('publisher-list', request=request, format=format)
    })

10.4 settings.py新增代码段

STATIC_URL = '/static/'
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAdminUser'
    ],
    'PAGE_SIZE': 1
}

11视图集和路由器

11.1 views.py

from rest_framework import viewsets, permissions
from .models import Publishers, Books
from .serializers import PublisherSerializer, BookSerializer
from .permissions import IsOwnerOrReadOnly

class PublisherViewSet(viewsets.ModelViewSet):
    queryset = Publishers.objects.all()
    serializer_class = PublisherSerializer
    permission_classes = (permissions.IsAuthenticated, IsOwnerOrReadOnly)


class BookViewSet(viewsets.ModelViewSet):
    queryset = Books.objects.all()
    serializer_class = BookSerializer
    permission_classes = (permissions.IsAuthenticated,)

11.2 serializers.py

# -*- coding: utf-8 -*-
from rest_framework import serializers
from .models import Books, Publishers

class PublisherSerializer(serializers.ModelSerializer):
    operator = serializers.ReadOnlyField(source='operator.username')

    class Meta:
        model = Publishers
        fields = (
            'id', 'name', 'address', 'operator'
        )


class BookSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Books
        fields = (
            'id', 'name', 'publisher'
        )

11.3  app01的urls.py

from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter
from app01.views import PublisherViewSet, BookViewSet

router = DefaultRouter()
router.register(r'publishers', PublisherViewSet)
router.register(r'books', BookViewSet)
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

12.更改路径

12.1 restproject的路径

from rest_framework.documentation import include_docs_urls
from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^restproject/', include("app01.urls")),
    url(r'^docs/', include_docs_urls(title="图书管理系统")),
    url(r'^admin/', admin.site.urls),
]

12.2app01的urls.py

from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter
from rest_framework.schemas import get_schema_view
from app01.views import PublisherViewSet, BookViewSet

router = DefaultRouter()
router.register(r'publishers', PublisherViewSet)
router.register(r'books', BookViewSet)
schema_view = get_schema_view(title='Pastebin API')
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^schema/$', schema_view),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Christian_yang

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值