drf 3小时_network

发布时间 2023-06-27 21:27:47作者: 德琪

课程:7-1 课程总结_哔哩哔哩_bilibili

源码:苏德琪/Django - 码云 - 开源中国 (gitee.com)

1.运行项目:

在终端内,python manage.py runserver 0.0.0.0:8000,运行manage.py文件

image-20230621103008826

(1)在浏览器内打到端口查询

image-20230621103426905

(2)在postman中测试端口

image-20230621104933430

删除节信息:delete

image-20230621105136775

2.新建项目

(1)新建Django工程

image-20230621164124223

(2)基本信息配置
setting中更改信息:
#修改
ALLOWED_HOSTS = ["*"]

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

……
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': []
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

……

#末尾添加
STATIC_ROOT = os.pardir.join(BASE_DIR, 'static')
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'staticfiles')
]
终端内执行命令:

python manage.py makemigrations

python manage.py migrate

image-20230621170250378

​ 在 Django 中,当你的模型发生变化时(例如添加、删除或修改模型的字段),你需要创建一个数据库迁移文件,以便将这些变化应用到数据库中。迁移文件记录了对数据库的修改操作,包括创建、修改或删除表、列、索引等。

  • 运行 python manage.py makemigrations 命令会分析你的模型文件,并生成包含数据库迁移操作的文件。这些文件将被存储在应用程序的 migrations 文件夹中。
  • 生成迁移文件后,你可以使用 python manage.py migrate 命令来应用这些迁移,将数据库结构与模型保持同步。

​ 总结起来,python manage.py makemigrations 命令是用于生成数据库迁移文件,以记录模型的变化,而 python manage.py migrate 命令是用于应用这些迁移文件,更新数据库结构。

配置用户信息

python manage.py createsuperuser

image-20230621170643870

这里我的用户名:

  • dq
  • dq271828

运行查看:[站点管理 | Django 站点管理员]http://127.0.0.1:8000/admin/

image-20230621202733062

image-20230622095831370

setting中配置drf:
INSTALLED_APPS = [
    ……
        'rest_framework',  # RESTful API
    'rest_framework.authtoken',  # DRF自带的token认证
]

……
# drf全局配置,最后添加
rest_framework = {
    'DEFAULT_PERMISSION_CLASSES': ['rest_framework.pagination.PageNUmberPagination'],
    'page_size': 50,
    'datetime_format': '%Y-%m-%d %H:%M:%S',
    'default_renderer_classes': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
    '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.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.TokenAuthentication',
        
    ] 
}
终端内执行命令:

python manage.py makemigrations

python manage.py migrate

image-20230622095613725
urls中配置信息:
from django.contrib import admin
from django.urls import path, include  # include()函数用于包含其它URLconf

urlpatterns = [
    path('api-auth/', include('rest_framework.urls')),
    path('admin/', admin.site.urls),
]

运行工程drf:
image-20230622103659802

网页端打到网址:http://127.0.0.1:8000/api-auth/login/

image-20230622103507309

成功跳转到这个路由:accounts/profile/

image-20230622103547403

3.序列化

(1)course app搭建(课程信息模型类)
  • course\apps.py
from django.apps import AppConfig

class CourseConfig(AppConfig):
    name = 'course'
    verbose_name = '课程信息'
  • course\models.py
from django.db import models
from django.conf import settings


class Course(models.Model):
    name = models.CharField(max_length=255, unique=True, help_text='课程名称', verbose_name='名称')
    introduction = models.TextField(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:
        db_table = 'course'
        verbose_name = '课程信息'
        verbose_name_plural = verbose_name
        ordering = ('price',)
    
    def __str__(self):
        return self.name

  • course\admin.py
from django.contrib import admin

from .models import Course


@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    list_display = ('name', 'introduction', 'teacher', 'price')
    serch_fields = list_display
    list_filter = list_display
    
终端内执行命令:

python manage.py makemigrations

python manage.py migrate

项目中已经生成migrations文件夹

image-20230622145850097

添加课程信息:

image-20230622145147448

image-20230622145349929

在控制台中序列化课程信息:(Django自带序列化工具)
from course.models import Course
from django.core import serizlizaers

serializers.serialize('json',Course.objects.all())                     #序列化全部字段
serializers.serialize('json',Course.objects.all(),fields=("name"))     #序列化 name 字段

image-20230622145617783

(2)序列化模型类

在app下面建立一个序列化文件

image-20230622165425899

  • serializers.py中:
from django import forms
from rest_framework import serializers
from .models import Course
from django.contrib.auth.models import User

# form类
class CourseForm(forms.ModelForm):
    class Meta:
        model = Course
        fields = ('name', 'introduction', 'teacher', 'price')

# 模型类
class CourseSerializer(serializers.ModelSerializer):
    teacher = serializers.ReadOnlyField(source='teacher.username')  # 只读字段
    
    class Meta:
        model = Course
        fields = '__all__'

# 用户类
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'  # 所有字段
(3)带URL的HyperlinkedModelSerializer
  • serializers.py中:
class CourseSerializer(serializers.HyperlinkedModelSerializer):
    teacher = serializers.ReadOnlyField(source='teacher.username')  # 只读字段
    
    class Meta:
        model = Course
        fields = ('id', 'url', 'name', 'introduction', 'teacher', 'price', 'create_at', 'update_at')

4.DRF视图开发RESTful APl接口

  • 函数式编程Function Based View
  • 类视图Classed Based View
  • 通用类视图Generic Classed Based View
  • DRF的视图集viewsets
(1)Django原生view开发Api接口

views.py中:

import json
from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views import View
from django.utils.decorators import method_decorator

course_dict = {
    'name': '课程名称',
    'introduction': '课程介绍',
    'price': 100,
}

# 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'))  # json.loads()将json字符串转换为python字典
        # return HttpResponse(json.dumps(course), content_type='application/json')
        return JsonResponse(course, safe=False)  # 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 HttpResponse(json.dumps(course), content_type='application/json')
(2)函数式编程
获取所有课程信息或新增一个课程
  • course/views中:
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":
        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/serializers.py中:
# 模型类
class CourseSerializer(serializers.ModelSerializer):
    teacher = serializers.ReadOnlyField(source='teacher.username')  # 只读字段
    
    class Meta:
        model = Course
        fields = '__all__'
  • course/urls中:(新建文件)
from django.urls import path, include
from course import views

urlpatterns = [
    path("fbv/list/", views.course_list, name="fbv_list")
]
  • drf/urls中:
from django.contrib import admin
from django.urls import path, include  # include()函数用于包含其它URLconf

urlpatterns = [
    path('api-auth/', include('rest_framework.urls')),
    path('admin/', admin.site.urls),
    path('course/', include('course.urls'))
]
image-20230622212504096
  • 测试post:(反序列化)

{

"name": "Django 快速入",

"introduction": "测",

"price": "0.99"

}

image-20230622214036527

获取、更新、删除一个课程
  • course/views中继续写:
@api_view(["GET", "PUT", "DELETE"])
def course_detail(request, pk):  # 获取、更新、删除一个课程
    try:
        course = Course.objects.get(pk=pk)
    except Course.DoesNotExist:
        return Response(data={"msg": "没有此课程信息"}, 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(data=s.data, status=status.HTTP_200_OK)
            return Response(data=s.errors, status=status.HTTP_400_BAD_REQUEST)
        
        elif request.method == "DELETE":
            course.delete()
            return Response(data={"msg": "删除成功"}, status=status.HTTP_204_NO_CONTENT)
  • course/urls中:
urlpatterns = [
    path("fbv/list/", views.course_list, name="fbv_list"),
    path("fbv/detail/<int:pk>/", views.course_detail, name="fbv_detail")
]

image-20230622220751426

(3)使用Postman测试API接口
GET请求:

http://127.0.0.1:8000/course/fbv/list/

  • 利用密码认证:

用户名:dq

密码:dq271828

image-20230623104229077

  • 利用token认证:

https://api.github.com/user/repos

Key:Authorization

Value:Token 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

image-20230623104738305

POST请求:

密码授权——>Body/raw-JSON——>添加信息,发送请求

image-20230623110031274image-20230623110151127

在网页端也能看到新增的第3条信息:

image-20230623110740193

GET单个请求:

http://127.0.0.1:8000/course/fbv/detail/2/

PUT更新请求:

更改课程3的价格

DELETE请求:

image-20230623112739130

(4)类视图编程
  • course/views中:
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView

from .models import Course
from .serializers import CourseSerializer

# 二、 类视图 Class Based View
class CourseList(APIView):
    def get(self, request):
        s = CourseSerializer(instance=Course.objects.all(), many=True)  # 序列化,这里是instance
        return Response(data=s.data, status=status.HTTP_200_OK)
    
    def post(self, request):
        s = CourseSerializer(data=request.data)  # 反序列化,这里是data
        if s.is_valid():
            s.save(teacher=request.user)
            print(type(request.data), type(s.data))
            return Response(data=s.data, status=status.HTTP_201_CREATED)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)
  • course/urls中:(新建文件)
from django.urls import path
from course import views

urlpatterns = [
    # Function-Based Views
    path("fbv/list/", views.course_list, name="fbv_list"),
    path("fbv/detail/<int:pk>/", views.course_detail, name="fbv_detail"),
    
    # Class-Based Views
    path("cbv/list/", views.CourseList.as_view(), name="cbv_list"),
]

image-20230623115121868

5.DRF认证方式

image-20230627094045275

(1)使用Django manage.py手动生成Token
  • 在settings——>INSTALLED_APPS中,添加'rest_framework.authtoken'
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',  # RESTful API
    'rest_framework.authtoken',  # DRF自带的token认证
    'course.apps.CourseConfig',
]
  • 在settings——>rest_framework中,添加'rest_framework.authentication.TokenAuthentication'

image-20230627104109766

  • 在终端输入命令:python manage.py drf_create_token dq

  • db.sqlite3中也可以看到key值

image-20230627094828568

(2)Django信号机制自动生成Token
a.信号机制自动生成Token
  • 在views中导入:
from django.db.models.signals import post_save
from django.conf import settings
from django.dispatch import receiver
from rest_framework.authtoken.models import Token


@receiver(post_save, sender=settings.AUTH_USER_MODEL)  # Django的信号机制
def generate_token(sender, instance=None, created=False, **kwargs):
    """
    创建用户时自动生成Token
    :param sender:
    :param instance:
    :param created:
    :param kwargs:
    :return:
    """
    if created:
        Token.objects.create(user=instance)
  • 在drf——>views中添加:

    from rest_framework.authtoken import views # DRF自带的token认证

    path('api-token-auth/', views.obtain_auth_token), # 获取token的接口

from django.contrib import admin
from django.urls import path, include  # include()函数用于包含其它URLconf
from rest_framework.authtoken import views  # DRF自带的token认证

urlpatterns = [
    path('api-token-auth/', views.obtain_auth_token),  # 获取token的接口
    path('api-auth/', include('rest_framework.urls')),
    path('admin/', admin.site.urls),
    path('course/', include('course.urls'))
]
b.测试新建用户是否生成
  • 运行工程

image-20230627100609817

image-20230627101130469

  • 新建用户: user01

image-20230627101254000

image-20230627101507284

  • 返回看到:user01有效

image-20230627101537303

  • 在db.sqlite3——>authtoken中可以看到新增的token

image-20230627101733417

c.利用postman测试api-token-auth接口:

image-20230627102038803

  • 利用postman添加新用户,生成token

  • 利用token认证(API Key),查询列表

image-20230627102905402

  • 响应成功

image-20230627103015099

6.DRF接口文档生成

  • drf——>settings中,添加:
REST_FRAMEWORK = {
     'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
 }
  • drf——>urls中,添加:
from rest_framework.documentation import include_docs_urls  # DRF自带的文档

urlpatterns = [
    path('docs/', include_docs_urls(title='DRF API文档', description='Django REST framework快速入门')),
]

image-20230627154008435