Django REST Framework入门学习

Django REST Framework

导学

  • 学习目标:使用DRF开发RESTful API接口
  • 学习内容:序列化(serializers)、视图集(viewsets)、路由(routers)、认证(authentication)、认证(permission)
  • 学习效果:DRF的多种视图实现课程信息的增删改查

image.png


一、创建项目

1.1 创建Django项目

image.png

1.2 修改 settings.py配置文件
ALLOWED_HOSTS = ["*"]

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False

// 在settings.py文件的最下面添加
STATIC_ROOT = os.path.join(BASE_DIR, "static")

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "staticfiles")
]

然后在 drf_tutonrial项目下新建一个static文件夹

1.3 生成数据表

python manage.py makemigrations

python manage.py migrate

创建管理员用户,填写用户名、邮箱地址(非必填)和密码

python manage.py createsuperuser

1.4 运行并访问

运行命令:python manage.py runserver

image.png

image.png


二、安装 Django REST Framework

  • 1)点击Settings进行安装

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xc5crBWn-1602137911055)(F:\Android\android案例开发笔记\直播案例开发图片\image-20201007142127980.png)]

  • 2)在pycharm控制台中通过命令进行安装

    pip install djangorestframework

2.1 在 settings.py中添加配置
INSTALLED_APPS = [
    ......,
    'rest_framework',  # RESTful API
    'rest_framework.authtoken',  # DRF自带的 Token认证
]

在settings.py文件最下面添加DRF的全局配置

# DRF的全局配置
REST_FRAMEWORK = {
    # 设置分页
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
    # 设置日期格式化
    'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S',
    # 当 DRF返回 response对象时,要使用的那个 rander类
    'DEFAULT_RENDER_CLASSES': [
        'rest_framework.renders.JSONRenderer',
        'rest_framework.renders.BrowsableAPIRenderer',
    ],
    # 解析器,如何解析 request请求中的 request.data
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser',
    ],
    # 权限以及认证相关的配置
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ]
}
2.2 生成数据表

python manage.py makemigrations

python manage.py migrate

2.3 添加DRF登录以及退出的路由

在urls.py文件中

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

urlpatterns = [
    path('admin/', admin.site.urls),
    # DRF的登录退出
    path('api-auth/', include('rest_framework.urls')),
]
2.4 运行并访问

运行命令:python manage.py runserver

image.png

这里跳转到了这个404页面。因为我们还有开发这个accounts/profile/路由,实际上已经登录成功了

image-20201007143911287.png


三、编写课程信息模型

3.1 在course/models.py中编写课程信息模型
from django.db import models
from django.conf import settings

# Create your models here.


class Course(models.Model):
    name = models.CharField(max_length=255, unique=True, help_text='课程名称', verbose_name='名称')
    introduction = models.CharField(max_length=255, unique=True, help_text='课程介绍', verbose_name='介绍')
    teacher = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, help_text='课程讲师', verbose_name='讲师')
    price = models.DecimalField(max_digits=6, decimal_places=2, help_text='课程价格', verbose_name='价格')
    create_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    update_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        verbose_name = '课程信息'
        verbose_name_plural = verbose_name
        # 使用价格排序
        ordering = ('price',)

    def __str__(self):
        return self.name
3.2 将上面的字段注册到admin.py中

方便添加数据时可以从Admin后台直接加

from django.contrib import admin
from .models import Course

# Register your models here.


@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    list_display = ('name', 'introduction', 'teacher', 'price')
    # 可搜索字段
    search_fields = list_display
    # 过滤字段
    list_filter = list_display

3.3 生成数据表

python manage.py makemigrations

python manage.py migrate

image.png

image.png


四、序列化(Serialization)

4.1 什么时序列化

我们可以将序列化理解为:将程序中的一个数据结构类型转换为其他格式(字典、JSON、XML等),例如将Django中的模型类对象转换为JSON字符串,这个转换过程我们称为序列化。

4.2 继承ModelSerializer序列化模型类
from django import forms
from rest_framework import serializers
from .models import Course
from django.contrib.auth.models import User


# class CourseForm(forms.ModelForm):
#     """ form表单类的写法,这里不用 """
#     class Meta:
#         model = Course
#         fields = ('name', 'introduction', 'teacher', 'price')


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'


class CourseSerializer(serializers.ModelSerializer):
    """ 课程序列化模型类 """
    # 外键字段 只读
    teacher = serializers.ReadOnlyField(source='teacher.username')

    class Meta:
        model = Course
        # fields = ('id', 'name', 'introduction', 'teacher', 'price', 'create_at', 'update_at')
        # 如果将所有字段都包含进来可以写 __all__
        fields = '__all__'

        
# 在后面视图集的时候使用
# class CourseSerializer(serializers.HyperlinkedModelSerializer):
#     """ 课程序列化模型类 [带超链接的API] """
#     # 外键字段 只读
#     teacher = serializers.ReadOnlyField(source='teacher.username')
#
#     class Meta:
#         model = Course
#         # url是默认值。可在settings.py中设置 URL_FIELD_NAME使全局生效
#         fields = ('id', 'url', 'name', 'introduction', 'teacher', 'price', 'create_at', 'update_at')

五、Django的views开发RESTful API接口

5.1 DRF视图开发RESTful API接口
  • 函数式编程 Function Based View
  • 类视图 Classed Based View
  • 通用类视图 Generic Classed Based View
  • DRF的视图集 viewsets
5.2 Django 原生开发API接口
from django.shortcuts import render
import json
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.views import View

# Create your views here.
course_dict = {
    'name': '课程名称',
    'introduction': '课程介绍',
    'price': 0.11
}

# 原生 Django FBV 编写 API接口
@csrf_exempt
def course_list(request):
    if request.method == 'GET':
        # return HttpResponse(json.dumps(course_dict), content_type='application/json')
        # 与上面的写法效果是一样的
        return JsonResponse(course_dict)
    if request.method == 'POST':
        course = json.loads(request.body.decode('utf-8'))
        # return HttpResponse(json.dumps(course), content_type='application/json')
        return JsonResponse(course, safe=False)


# 原生 Django CBV 编写 API接口
@method_decorator(csrf_exempt, name='dispatch')
class CourseList(View):
    def get(self, request):
        return JsonResponse(course_dict)

    def post(self, request):
        course = json.loads(request.body.decode('utf-8'))
        return JsonResponse(course, safe=False)
5.3 DRF中的装饰器api_view
5.3.1 查看和添加课程信息
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Course
from .serializers import CourseSerializer


""" 一、函数式编程 Function Based View """
@api_view(["GET", "POST"])
def course_list(request):
    """
    获取所有课程信息或新增一个课程
    :param request:
    :return:
    """
    if request.method == 'GET':
        s = CourseSerializer(instance=Course.objects.all(), many=True)
        return Response(data=s.data, status=status.HTTP_200_OK)
    elif request.method == 'POST':
        # 部分更新用 partial=True属性
        # s = CourseSerializer(data=request.data, partial=True)
        s = CourseSerializer(data=request.data)
        if s.is_valid():
            s.save(teacher=request.user)
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)
  • 在 course下新建 urls.py文件
from django.urls import path, include
from course import views

urlpatterns = [
    # Function Based View
    path('fbv/list/', views.course_list, name='fbv-list')
]
  • 然后在总的路由中添加课程的路由
urlpatterns = [
    path('admin/', admin.site.urls),
    # DRF的登录退出
    path('api-auth/', include('rest_framework.urls')),
    path('course/', include('course.urls'))
]

  • 运行并访问

    这里我们可以先在Admin后台管理中添加一条课程信息

    image.png

    在访问course/fbv/list接口

    image.png

    添加一条课程信息—[POST],再刷新

    image.png

    image.png

    image.png


5.3.2 获取、更新、删除一条课程信息

views.py

@api_view(["GET", "PUT", "DELETE"])
def course_detail(request, pk):
    """
    获取、更新、删除一条课程
    :param request:
    :param pk:
    :return:
    """
    try:
        course = Course.objects.get(pk=pk)
    except Course.DoesNotExist:
        return Response(data={"message": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
    else:
        if request.method == "GET":
            s = CourseSerializer(instance=course)
            return Response(data=s.data, status=status.HTTP_200_OK)
        elif request.method == "PUT":
            s = CourseSerializer(instance=course, data=request.data)
            if s.is_valid():
                s.save()
                return Response(s.data, status=status.HTTP_200_OK)
        elif request.method == "DELETE":
            course.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)
  • 运行并访问

    获取一条课程信息:

    image.png

    image.png


5.4 使用Postman工具测试API接口

Postman工具下载地址:https://www.postman.com/downloads/

第一次请求需要进行认证,选择用户名和密码认证

image.png

  • 1)查询所有课程信息
    image-20201007185507187.png

  • 2)添加一条课程信息

    image.png

    响应我们添加的数据

    image.png

  • 3)获取一条课程信息

    image.png

  • 4)更新一条课程信息,比如说更新第二条

    更新前:
    image-20201007191035610.png

    更新后:

    image.png

  • 5)删除一条课程信息,比如说删除id为3的

    image.png


六、DRF中的视图APIView

6.1 获取课程信息和添加课程信息
from rest_framework.views import APIView

"""二、 类视图 Class Based View"""


class CourseList(APIView):
    def get(self, request):
        """
        查询所有课程信息
        :param request:
        :return:
        """
        queryset = Course.objects.all()
        s = CourseSerializer(instance=queryset, many=True)  # instance是查询集
        return Response(s.data, status=status.HTTP_200_OK)

    def post(self, request):
        """
        添加课程信息
        :param request:
        :return:
        """
        s = CourseSerializer(data=request.data)  # 这里的 data是前端传递过来的数据
        if s.is_valid():
            s.save(teacher=self.request.user)
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)
6.2 在urls.py文件中添加路由
urlpatterns = [
    # Function Based View
    path('fbv/list/', views.course_list, name='fbv-list'),
    path('fbv/detail/<int:pk>/', views.course_detail, name='fbv-detail'),
    
    # Class Based View
    path('cbv/list/', views.CourseList.as_view(), name='cbv-list')
]
6.3 使用Postman测试接口
  • 1)查询课程信息

    image.png

  • 2)添加课程信息

    image.png

6.4 编写课程的详情信息接口
class CourseDetail(APIView):
    @staticmethod
    def get_object(pk):
        """
        处理通用的返回对象
        :param pk:
        :return:
        """
        try:
            return Course.objects.get(pk=pk)
        except Course.DoesNotExist:
            return

    def get(self, request, pk):
        """
        获取一条课程信息
        :param request:
        :param pk:
        :return:
        """
        obj = self.get_object(pk=pk)
        # 如果没有获取到该课程信息
        if not obj:
            return Response(data={"message": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        # 有课程信息,进行序列化
        s = CourseSerializer(instance=obj)
        return Response(s.data, status=status.HTTP_200_OK)

    def put(self, request, pk):
        """
        更新一条课程信息
        :param request:
        :param pl:
        :return:
        """
        obj = self.get_object(pk=pk)
        # 如果没有获取到该课程信息
        if not obj:
            return Response(data={"message": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        # 反序列化
        s = CourseSerializer(instance=obj, data=request.data)
        if s.is_valid():
            s.save()
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        """
        删除一条课程信息
        :param request:
        :param pk:
        :return:
        """
        obj = self.get_object(pk=pk)
        # 如果没有获取到该课程信息
        if not obj:
            return Response(data={"message": "没有此课程信息"}, status=status.HTTP_404_NOT_FOUND)
        obj.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
6.6 使用Postman测试接口
  • 1)获取一条课程信息

    GET http://127.0.0.1:8000/course/cbv/detail/4/

  • 2)更新一条课程信息

    PUT http://127.0.0.1:8000/course/cbv/detail/4/

  • 3)删除一条课程信息

    DELETE http://127.0.0.1:8000/course/cbv/detail/2/


7、DRF中的通用类视图GenericAPIView

7.1 增删改查一次搞定
from rest_framework import generics

""" 三、通用类视图 Generic Class Based View """


class GCourserList(generics.ListCreateAPIView):
    queryset = Course.objects.all()
    serializer_class = CourseSerializer

    # 因为在保存这个实例的时候没有把当前请求的用户赋值给我们自定义的 teacher,
    # 所以我们要重写这个方法
    def perform_create(self, serializer):
        serializer.save(teacher=self.request.user)


class GCourseDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    
    # 这里因为不需要更新 teacher字段,所以不需要重新上面的方法
7.2 添加路由
# Generic Class Based View
path('gcbv/list/', views.GCourserList.as_view(), name='gcbv-list'),
path('gcbv/detail/<int:pk>/', views.GCourseDetail.as_view(), name='gcbv-list')
7.4 使用Postman工具测试API接口
  • 1)获取所有课程信息

    GET http://127.0.0.1:8000/course/gcbv/list/

  • 2)添加一条课程信息

    POST http://127.0.0.1:8000/course/gcbv/list/

  • 3)获取一条课程信息

    GET http://127.0.0.1:8000/course/gcbv/detail/6/

  • 4)修改一条课程信息

    PUT http://127.0.0.1:8000/course/gcbv/detail/6/

  • 5)删除一条课程信息

    DELETE http://127.0.0.1:8000/course/gcbv/detail/6/


八、DRF的viewsets视图集的增删改查接口

8.1 只需一个接口实现增删改查
from rest_framework import viewsets

""" 四、DRF的视图集viewsets """


class CourseViewSet(viewsets.ModelViewSet):
    queryset = Course.objects.all()
    serializer_class = CourseSerializer
    
    def perform_create(self, serializer):
        serializer.save(teacher=self.request.user)
8.2 设置路由
  • 1)写法一

    # viewsets
    path('viewset/', views.CourseViewSet.as_view({
            "get": "list", "post": "create"
    }), name='viewsets-list'),
    path('viewset/<int:pk>/', views.CourseViewSet.as_view({
            "get": "retrieve", "put": "update", "patch": "partial_update", "delete": "destroy"
    }), name='viewsets-detail')
    

    不同的请求对应不同的方法

    image.png

  • 2)写法二

    from rest_framework.routers import DefaultRouter
    
    # 实例化
    router = DefaultRouter()
    # 把实例集注册到这个路由里面
    router.register(prefix='viewsets', viewset=views.CourseViewSet)
    
    urlpatterns = [
    		......
        path('', include(router.urls))
    ]
    
8.3 使用Postman工具测试API接口
  • 1)获取全部课程信息

    GET http://127.0.0.1:8000/course/viewsets

  • 2)获取一条课程信息

    GET http://127.0.0.1:8000/course/viewsets/7

  • 3)添加一条课程信息

    POST http://127.0.0.1:8000/course/viewsets/

  • 4)修改一条课程信息

    PUT http://127.0.0.1:8000/course/viewsets/8/

  • 5)删除一条课程信息

    DELETE http://127.0.0.1:8000/course/viewsets/8/

下一篇:https://blog.csdn.net/qq_43401941/article/details/108962931

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值