django

安装django

pip install django

创建项目

django-admin startproject demo1
# 确保scripts在环境变量中

创建app

python manage.py startapp app01

目录视图

│  manage.py
│
├─app01
│  │  admin.py
│  │  apps.py
│  │  models.py 
│  │  tests.py
│  │  views.py # url视图映射函数
│  │  __init__.py
│  │
│  └─migrations
│          __init__.py
│
└─demo1
    │  asgi.py #异步接口
    │  settings.py
    │  urls.py # url和函数的对应关系
    │  wsgi.py #同步接口
    │  __init__.py
    │
    └─__pycache__
            settings.cpython-36.pyc
            __init__.cpython-36.pyc

启动

  • 注册app,settings-》INSTALLED_APPS

    在这里插入图片描述

  • 编写URL和视图对应关系

    urls.py

在这里插入图片描述

  • 编写函数

在这里插入图片描述

  • 启动

    • 命令行

      python manage.py runserver
      

连接数据库

  • 引入ORM框架

    # 安装三方模块
    pip install mysqlclient
    
    # 失败安装百度,下载wel包,pip isntall 文件位置
    
  • 配置settings

    DATABASES = {
        'default': {
            "ENGINE": 'django.db.backends.mysql',
            "HOST": "124.71.217.135",
            "PORT": 3306,
            "USER": "root",
            "PASSWORD": "Wang@2001767812",
            "NAME": "jd"
        }
    }
    
  • 在models.py中

    # 创建表
    class UserInfo(models.Model):
        name = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
        age = models.IntegerField()
    
  • 如果已经存在的表注册

    在Django中使用已经存在的数据库表,需要进行以下步骤:

    1. 在Django的settings.py文件中,配置数据库连接信息,包括数据库类型、数据库名称、数据库用户名、数据库密码、数据库主机和端口等信息。
    2. 在models.py文件中,定义一个类,该类对应已经存在的数据库表,并且使用Meta类指定该类对应的数据库表名。
    3. 在该类中定义字段,每个字段对应数据库表中的一个列。

    例如,假设已经存在一个名为users的数据库表,包含id、name和age三个列,那么可以在models.py文件中定义如下类:

    from django.db import models
    
    class Users(models.Model):
        id = models.IntegerField(primary_key=True)
        name = models.CharField(max_length=50)
        age = models.IntegerField()
    
        class Meta:
            db_table = 'users'
    
    
  • 执行命令

    app注册了

    python manage.py makemigrations
    python manage.py migrate
    
  • 对标数据的操作

    在Django中,可以通过ORM(对象关系映射)来实现对数据库表的增删改查和多表之间的查询。ORM是一种将对象和关系数据库之间的数据进行映射的技术,它将数据库中的表映射为Python中的类,将表的行映射为类的对象,将表的列映射为类的属性。

    下面是一些常用的ORM操作示例:

    • 添加数据

      user = Users(name='Tom', age=20)
      user.save()
      
    • 修改数据

      user = Users.objects.get(id=1)
      user.name = 'Jack'
      user.save()
      
    • 删除数据

      user = Users.objects.get(id=1)
      user.delete()
      
    • 查询数据

      # 查询所有数据
      users = Users.objects.all()
      
      # 根据条件查询数据
      users = Users.objects.filter(name='Tom')
      
      # 查询单条数据
      user = Users.objects.get(id=1)
      
    • 多表查询

      # 多表关联查询
      class Book(models.Model):
          name = models.CharField(max_length=50)
          author = models.ForeignKey(Users, on_delete=models.CASCADE)
      
      books = Book.objects.filter(author__name='Tom')
      
      # 聚合查询
      from django.db.models import Count
      users = Users.objects.annotate(book_count=Count('book'))
      

      在上面的示例中,我们定义了一个Book类,并且使用ForeignKey字段关联了Users类。在多表查询中,可以通过双下划线__来进行关联查询,如author__name表示查询author字段中name为Tom的数据。另外,聚合查询可以使用annotate方法来完成,例如查询每个用户对应的书籍数量。

    • 跨表查询

      # 一对一关联查询
      class UserProfile(models.Model):
          user = models.OneToOneField(Users, on_delete=models.CASCADE)
          address = models.CharField(max_length=100)
      
      user_profile = UserProfile.objects.filter(user__name='Tom')
      
      # 多对多关联查询
      class Group(models.Model):
          name = models.CharField(max_length=50)
          members = models.ManyToManyField(Users)
      
      group = Group.objects.filter(members__name='Tom')
      

      在上面的示例中,我们定义了一个UserProfile类,与Users类通过一对一关联。在查询中,可以使用双下划线__来进行跨表查询,例如查询与名为Tom的用户关联的UserProfile数据。另外,多对多关联也可以使用同样的方式来查询,例如查询名为Tom的用户所在的Group数据。

    • 原生SQL查询

      from django.db import connection
      
      cursor = connection.cursor()
      cursor.execute('SELECT * FROM users')
      result = cursor.fetchall()
      

      如果需要执行一些复杂的查询,ORM可能无法满足需求,这时可以使用原生SQL查询。在Django中,可以通过connection对象获取数据库连接,并执行原生SQL语句,获取查询结果。但是需要注意,使用原生SQL查询可能会导致一些安全问题,所以在使用时需要谨慎。

前后端分离

Django和Vue的前后端分离开发可以通过RESTful API来实现,即前端通过HTTP请求访问后端提供的API接口,获取数据并展示在页面上。

具体实现步骤如下:

  • 在Django中定义API接口,通常使用Django的视图函数或基于类的视图来实现。例如,定义一个返回所有用户数据的API接口:

    from django.http import JsonResponse
    from .models import Users
    
    def get_users(request):
        users = Users.objects.all().values()
        return JsonResponse(list(users), safe=False)
    
    
  • 在Vue中使用Axios或其他HTTP库来发送请求,获取API接口返回的数据,并展示在页面上。例如,在Vue中使用Axios获取上面定义的API接口返回的数据:

<template>
  <div>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }} - {{ user.age }}</li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      users: []
    }
  },
  mounted() {
    axios.get('http://localhost:8000/api/get_users')
      .then(response => {
        this.users = response.data
      })
  }
}
</script>

  • 解决跨域

    由于Vue和Django通常运行在不同的服务器上,会导致跨域问题。为了解决跨域问题,可以在Django中安装django-cors-headers库,并在settings.py文件中进行配置:

    INSTALLED_APPS = [
        # ...
        'corsheaders',
        # ...
    ]
    
    MIDDLEWARE = [
        # ...
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        # ...
    ]
    
    CORS_ORIGIN_ALLOW_ALL = True
    
    

权限

Django提供了内置的权限系统,可以方便地实现用户权限控制。下面是实现用户权限的步骤:

  • 定义权限

    在Django中,可以通过Permission模型类来定义权限。例如,定义一个可以查看用户列表的权限:

    from django.contrib.auth.models import Permission
    
    permission = Permission.objects.create(
        codename='view_users',
        name='Can view users',
        content_type=ContentType.objects.get_for_model(Users)
    )
    

    在上面的示例中,使用Permission模型类创建了一个名为view_users的权限,表示可以查看用户列表。其中,content_type参数指定了权限所属的模型,这里使用get_for_model方法获取了Users模型的ContentType。

  • 给用户分配权限

    可以通过Django的内置用户模型User来管理用户,并通过给用户分配权限来控制用户的访问权限。例如,给名为Tom的用户分配view_users权限:

    from django.contrib.auth.models import User, Permission
    
    user = User.objects.get(username='Tom')
    permission = Permission.objects.get(codename='view_users')
    user.user_permissions.add(permission)
    

    在上面的示例中,通过User模型类获取名为Tom的用户,再通过Permission模型类获取view_users权限,并通过user_permissions属性将权限分配给用户。

  • 在视图中控制权限

    在Django的视图函数或基于类的视图中,可以通过装饰器来控制用户的访问权限。例如,定义一个需要view_users权限才能访问的视图:

    from django.contrib.auth.decorators import permission_required
    from django.views.generic import ListView
    from .models import Users
    
    @permission_required('app.view_users')
    class UsersListView(ListView):
        model = Users
        template_name = 'user_list.html'
    
    

    在上面的示例中,使用permission_required装饰器来限制只有拥有view_users权限的用户才能访问UsersListView视图。如果用户没有权限,则会跳转到登录页面或403错误页面。

    通过以上步骤,就可以使用Django的内置权限系统来实现用户权限控制。需要注意的是,权限控制是基于视图的,所以需要在视图中显式地控制用户的访问权限。

DRF组件,rest-framework

restful:资源状态转换
  • restful规范: 通过POST,GET,DELETE,PATCH,PUT来表明动作
FCBV:Function Base View

通过接口映射函数返回视图

CBV:Class Base View

View:as_view->dispatch

def view(request, *args, **kwargs):
	self = cls(**initkwargs)
    return self.dispatch(request, *args, **kwargs)

def dispatch(self, request, *args, **kwargs):
    # request.method.lower()调用method转换为小写的方法
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        return handler(request, *args, **kwargs)

  • Django的CBV(Class-Based Views)是基于类的视图,与基于函数的视图(FBV)相比,它具有更好的代码复用性和可扩展性。CBV的核心思想是将视图逻辑分散到不同的类中,并将这些类组合在一起以实现具体的视图。

    CBV通过继承Django提供的预定义视图类来实现。Django提供了许多不同类型的预定义视图类,包括通用视图类和模型视图类。通用视图类用于执行通用任务,例如显示表单、列表和详细信息页面。模型视图类用于执行与模型相关的任务,例如显示模型列表、详细信息页面和表单。

    下面是一些常用的CBV类:

    TemplateView:用于显示静态模板页面。
    ListView:用于显示模型列表页面。
    DetailView:用于显示模型详细信息页面。
    FormView:用于显示表单页面。
    CreateView:用于创建模型实例。
    UpdateView:用于更新模型实例。
    DeleteView:用于删除模型实例。
    
使用CBV的步骤如下:
  1. 创建视图类

    首先,需要创建一个继承自Django提供的预定义视图类的视图类。例如,下面是一个继承自ListView的视图类:

    from django.views.generic import ListView
    from .models import MyModel
    
    class MyModelListView(ListView):
        model = MyModel
    

    在上述代码中,MyModelListView继承自Django提供的ListView类,并定义了model属性为MyModel。

  2. 定义URL

    接下来,需要定义一个URL模式,将URL映射到视图类。例如,下面是一个将URL映射到MyModelListView的URL模式:

    from django.urls import path
    from .views import MyModelListView
    
    urlpatterns = [
        path('mymodels/', MyModelListView.as_view(), name='mymodel-list'),
    ]
    

    在上述代码中,将URL /mymodels/ 映射到 MyModelListView,并为它定义了一个名称为 mymodel-list 的命名URL。

DRF

Django REST framework(简称DRF)是一个用于构建Web API的强大框架。它基于Django,使构建RESTful API变得更加容易和快速。下面是DRF的一些主要特点:

  1. 序列化:DRF提供了一种方便的方法来将模型实例转换为JSON等常见格式。
  2. 视图:DRF提供了一组基于类的视图,可以轻松地创建API视图。
  3. 认证和权限:DRF提供了一组内置的身份验证和权限类,可以轻松地保护API端点。
  4. 分页:DRF提供了内置的分页支持,可以轻松地处理大量数据。
  5. 测试:DRF提供了一组内置的测试工具,可以轻松地测试API端点。

下面是使用DRF创建API的一些基本步骤:

  1. 安装DRF

    pip install djangorestframework
    
  2. 创建序列化器:

    序列化器用于将模型实例转换为JSON等常见格式。可以通过继承serializers.Serializer来创建序列化器。例如,下面是一个简单的序列化器:views.py

    from rest_framework import serializers
    from .models import MyModel
    
    # 序列化器
    class MyModelSerializer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        name = serializers.CharField(max_length=100)
    
        def create(self, validated_data):
            return MyModel.objects.create(**validated_data)
    
        def update(self, instance, validated_data):
            instance.name = validated_data.get('name', instance.name)
            instance.save()
            return instance
    

    在上述代码中,MyModelSerializer继承自serializers.Serializer,并定义了id和name字段。create()和update()方法用于创建和更新模型实例。

  3. 创建视图

    视图用于处理API请求。可以使用DRF提供的基于类的视图来创建视图。例如,下面是一个使用DRF的ListCreateAPIView视图:

    from rest_framework import generics
    from .models import MyModel
    from .serializers import MyModelSerializer
    
    class MyModelList(generics.ListCreateAPIView):
        queryset = MyModel.objects.all()
        # 序列化instance; 反序列化data, many是一个还是多个
        serializer_class = MyModelSerializer(instance=queryset, many=True)
        return HttpResponse(serializer_class.data)
    
    

    在上述代码中,MyModelList继承自generics.ListCreateAPIView,并定义了queryset和serializer_class属性。

  4. 定义URL

    接下来,需要定义一个URL模式,将URL映射到视图类。例如,下面是一个将URL映射到MyModelList的URL模式:

    
    from django.urls import path
    from .views import MyModelList
    
    urlpatterns = [
        path('mymodels/', MyModelList.as_view(), name='mymodel-list'),
    ]
    
    

    在上述代码中,将URL /mymodels/ 映射到 MyModelList,并为它定义了一个名称为 mymodel-list 的命名URL。

ApiView
def dispatch(self, request, *args, **kwargs):
	#创建新的request对象
	request = self.initialize_request(request, *args, **kwargs)
	self.request = request
	self.initial(request, *args, **kwargs)
	if request.method.lower() in self.http_method_names:
	# 传递用的新的request
	# request.method.lower()自己重写的方法:get(request),request是新的request
		handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
     else:
     	handler = self.http_method_not_allowed
		response = handler(request, *args, **kwargs)

序列化器

views.py中

class MyModelSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(max_length=32)
    password = serializers.CharField(max_length=64)
    age = serializers.IntegerField()
    
    def create(self, validated_data):
         return UserInfo.objects.create(**validated_data)
       
    # instance编辑对象, vali:编辑数据
    def update(self, instance, validated_data):
         instance.name = validated_data.get('name', instance.name)
         instance.save()
         return instance

from rest_framework.response import Response
class drfView(APIView):
    def get(self, request):
        users = UserInfo.objects.all()

        serializer_class = MyModelSerializer(instance=users, many=True)
        # serializer_class = MyModelSerializer(data=request.data, many=True)
        # serializer_class.save()
        print("get====")
        return_data = {
            "data": serializer_class.data,
            "msg": "成功",
            "code": 200
        }
        print(return_data)
        return Response(return_data, status=rest_framework.status.HTTP_200_OK)

+++++++++源码

serializer_class = MyModelSerializer(data=request.data)
serializer_class.save()

def save(self, **kwargs):
 validated_data = {**self.validated_data, **kwargs}

	# 重写update 和 create方法
	if self.instance is not None:
		self.instance = self.update(self.instance, validated_data)
        assert self.instance is not None, (
                '`update()` did not return an object instance.'
            )
	else:
		self.instance = self.create(validated_data)
        assert self.instance is not None, (
                '`create()` did not return an object instance.'
            )

   	return self.instance
ModelSerializer

Django REST framework提供了ModelSerializer类,它是一个方便的抽象类,用于快速实现基于Django模型的序列化器。ModelSerializer类自动根据模型定义生成序列化器字段,因此可以大大简化序列化器的编写。

下面是一个使用ModelSerializer的示例:

from rest_framework import serializers
from myapp.models import MyModel

class MyModelSerializer(serializers.ModelSerializer):
    # id = serializers.IntegerField(read_only=True)
    class Meta:
        model = MyModel
        fields = '__all__'
        # fields = ['title', '']
        # exclude = ['id'] 排除

在上面的示例中,我们定义了一个名为MyModelSerializer的序列化器,并指定了Meta类中的model属性为MyModel。我们还指定了fields属性为’all’,这表示包括所有模型字段。

现在我们可以在视图中使用这个序列化器来序列化和反序列化MyModel实例,如下所示:

from rest_framework import generics
from myapp.models import MyModel
from myapp.serializers import MyModelSerializer

class MyModelList(generics.ListCreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

class MyModelDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

在上面的示例中,我们使用MyModelSerializer来序列化和反序列化MyModel实例。我们还定义了两个视图:MyModelList和MyModelDetail,它们分别用于列出和操作单个MyModel实例。在这些视图中,我们指定了queryset和serializer_class属性,以便Django REST framework知道要使用哪个模型和序列化器来处理请求。

总之,ModelSerializer是一个非常方便的类,它可以大大简化序列化器的编写,同时提供了许多有用的功能,例如自动验证和模型关系处理。

实例

结果工具类

class Result:
    SUCCESS = 200  # 请求成功
    BAD_REQUEST = 400  # 请求无效
    UNAUTHORIZED = 401  # 未授权
    FORBIDDEN = 403  # 禁止访问
    NOT_FOUND = 404  # 请求资源不存在
    INTERNAL_SERVER_ERROR = 500  # 服务器内部错误

    @classmethod
    def success(cls, data=None, msg='请求成功'):
        return {
            'code': cls.SUCCESS,
            'msg': msg,
            'data': data
        }

    @classmethod
    def bad_request(cls, errors=None, msg='请求无效'):
        return {
            'code': cls.BAD_REQUEST,
            'msg': msg,
            'errors': errors
        }

    @classmethod
    def unauthorized(cls, errors=None, msg='未授权'):
        return {
            'code': cls.UNAUTHORIZED,
            'msg': msg,
            'errors': errors
        }

    @classmethod
    def forbidden(cls, errors=None, msg='禁止访问'):
        return {
            'code': cls.FORBIDDEN,
            'msg': msg,
            'errors': errors
        }

    @classmethod
    def not_found(cls, errors=None, msg='请求资源不存在'):
        return {
            'code': cls.NOT_FOUND,
            'msg': msg,
            'errors': errors
        }

    @classmethod
    def internal_server_error(cls, errors=None, msg='服务器内部错误'):
        return {
            'code': cls.INTERNAL_SERVER_ERROR,
            'msg': msg,
            'errors': errors
        }


views.py

class drfView(APIView):
    def get(self, request):
        users = UserInfo.objects.all()
        serializer_class = UserMyModelSerializer(instance=users, many=True)
        return_data = {
            "data": serializer_class.data,
            "msg": "成功",
            "code": 200
        }
        print(return_data)
        return Response(return_data, status=rest_framework.status.HTTP_200_OK)

    def post(self, request):
        # 获取请求数据
        print("data", request.data)
        ums = UserMyModelSerializer(data=request.data)
        if ums.is_valid():
            ums.save()
            return Response(ums.data)
        else:
            return Response(ums.errors)

    def put(self, request, id):
        # 获取请求数据
        print(request.data)
        update_obj = UserInfo.objects.get(pk=id)
        ums = UserMyModelSerializer(instance=update_obj, data=request.data)
        if ums.is_valid():
            ums.save()
            return Response(Result.success(ums.data))
        else:
            return Response(Result.bad_request(ums.errors))

新建一个序列化,专门做序列化器

from rest_framework import serializers
from .models import UserInfo

# 序列化器
class MyModelSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(max_length=32)
    password = serializers.CharField(max_length=64)
    age = serializers.IntegerField()
    def create(self, validated_data):
        return UserInfo.objects.create(**validated_data)

    # instance编辑对象, vali:编辑数据
    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.save()
        return instance
# ModelSerializer
class UserMyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo
        fields = '__all__'

    # def update(self, instance, validated_data):
    #     # 更新对象的价格
    #     instance.price = round(validated_data.get('price', instance.price), 2)
    #     # 保存对象并返回
    #     instance.save()
    #     return instance
    # def to_representation(self, instance):
    #     # 自定义返回格式
    #     return {
    #         "msg": "",
    #         "code": 200,
    #         "data": instance
    #     }
    # def update(self, instance, validated_data):
    #     try:
    #         instance = super().update(instance, validated_data)
    #     except:
    #         return {
    #             'msg': '更新书本失败',
    #             'code': 400,
    #             'errors': '更新书本失败'
    #         }
    #     return {
    #         'msg': '更新书本成功',
    #         'code': 200,
    #         'data': instance
    #     }

urls.py

urlpatterns = [
    # path('admin/', admin.site.urls),
    # www.xxx.com/index -> 执行函数
    path('index/', views.index),
    path('testpost1/', views.testpost1),

    # 序列化器
    # put,delete
    path('drfView/<int:id>', views.drfView.as_view()),
    # post, get
    path('drfView', views.drfView.as_view())
]
GenericAPIView[通用视图类]
简单版
class drfGenApiView(GenericAPIView):
	# 增加可维护性
    queryset = UserInfo.objects.all()
    serializer_class = UserMyModelSerializer
    
    
    
    def get(self, request, pk=None):
        # users = UserInfo.objects.all()
        # serializer_class = UserMyModelSerializer(instance=users, many=True)
        # serializer = self.get_serializer_class()(instance=self.get_queryset(), many=True)
        if pk is None:
            serializer = self.get_serializer(instance=self.get_queryset(), many=True)  # 合二为一
        else:
            serializer = self.get_serializer(instance=self.get_object(), many=False)
        return_data = Result.success(serializer.data)
        print(return_data)
        return Response(return_data, status=rest_framework.status.HTTP_200_OK)

    def post(self, request):
        # 获取请求数据
        # print("data", request.data)
        # ums = UserMyModelSerializer(data=request.data)
        ums = self.get_serializer(data=request.data)
        if ums.is_valid():
            ums.save()
            return Response(ums.data)
        else:
            return Response(ums.errors)
视图混合类

视图混合类是 Django REST framework 提供的一个功能强大的工具,可以帮助开发人员快速构建复杂的视图。它们提供了一些常见的操作,如列表、创建、更新和删除,并允许您轻松地将这些操作组合在一起,以构建各种不同类型的视图。

以下是一些常用的视图混合类及其用途:

  • ListModelMixin:提供了一个 list() 方法,用于检索所有对象的列表。
  • CreateModelMixin:提供了一个 create() 方法,用于创建新的对象。
  • RetrieveModelMixin:提供了一个 retrieve() 方法,用于检索单个对象。
  • UpdateModelMixin:提供了一个 update() 方法,用于更新单个对象。
  • DestroyModelMixin:提供了一个 destroy() 方法,用于删除单个对象。
  • GenericAPIView:提供了一些通用的方法,如 get_object()get_queryset(),以帮助您检索和操作对象。

使用这些混合类,您可以轻松地构建各种不同类型的视图。例如,如果您需要一个列表视图和一个创建视图,您可以将 ListModelMixinCreateModelMixin 添加到您的视图类中,如下所示:

from rest_framework import generics, mixins
from .models import Book
from .serializers import BookSerializer

class BookListCreateView(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

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

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

在上面的代码中,我们将 ListModelMixinCreateModelMixin 添加到我们的 BookListCreateView 视图类中,并实现了 get()post() 方法来处理 GETPOST 请求。在 get() 方法中,我们调用 list() 方法来检索所有书籍,并在 post() 方法中调用 create() 方法来创建新的书籍。

需要注意的是,您还需要将 GenericAPIView 添加到视图类中,以便可以使用通用的方法,如 get_object()get_queryset()

视图混合类的好处在于,它们允许您轻松地构建复杂的视图,而无需编写大量的重复代码。它们还提供了一些预定义的方法和属性,可帮助您快速构建常见的操作。

详解

GenericAPIView 是 Django REST framework 中的一个视图类,它提供了一组通用的 API 视图功能,可以帮助开发人员更快速、更简单地编写视图函数或类。下面我们来详细介绍一下 GenericAPIView 的使用。

首先,我们需要导入 GenericAPIView 类和一些辅助类和函数:

from rest_framework import generics
from rest_framework import mixins
from rest_framework import filters
from rest_framework.pagination import PageNumberPagination
from .models import Book
from .serializers import BookSerializer

其中,generics 模块提供了一些通用的 API 视图类,包括 GenericAPIViewmixins 模块提供了一组通用的视图操作,例如 ListModelMixinCreateModelMixinfilters 模块提供了一些常用的过滤器类,例如 SearchFilterPageNumberPagination 是一个分页器类,用于分页数据;Book 是我们的数据模型类;BookSerializer 是我们的数据序列化器类。

接下来,我们可以创建一个视图类,继承自 GenericAPIView 和一些辅助类和函数,例如:

class BookListCreateView(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [filters.SearchFilter]
    search_fields = ['name', 'author']
    pagination_class = PageNumberPagination

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

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

在上面的代码中,我们创建了一个名为 BookListCreateView 的视图类,它继承自 GenericAPIViewListModelMixinCreateModelMixin。这意味着我们可以在这个视图类中使用 GETPOST 请求方法,并且可以使用 ListModelMixinCreateModelMixin 提供的方法来实现对数据的读取和创建操作。

在视图类中,我们定义了一些属性和方法:

  • queryset:定义了要查询的数据集,这里我们查询所有的书本数据。
  • serializer_class:定义了要使用的数据序列化器类,这里我们使用了 BookSerializer
  • filter_backends:定义了要使用的数据过滤器类,这里我们使用了 SearchFilter
  • search_fields:定义了要搜索的字段列表,这里我们搜索了书名和作者名。
  • pagination_class:定义了要使用的分页器类,这里我们使用了 PageNumberPagination
  • get() 方法:处理 GET 请求,返回查询到的书本数据列表。
  • post() 方法:处理 POST 请求,创建一个新的书本数据。

当客户端发送一个 GET 请求时,Django REST framework 会自动调用 list() 方法,该方法使用 ListModelMixin 提供的查询数据和序列化数据的方法,最终返回查询到的书本数据列表。当客户端发送一个 POST 请求时,Django REST framework 会自动调用 create() 方法,该方法使用 CreateModelMixin 提供的创建数据和序列化数据的方法,最终创建一个新的书本数据。

需要注意的是,视图类中的属性和方法可以根据您的具体需求进行修改和扩展,例如添加更多的请求方法、使用不同的数据过滤器、使用不同的分页器等等。

其他条件至少包含两个查询条件来查询

如果您需要根据多个条件进行查询,您可以使用 Django REST framework 提供的 Filtering 功能。Filtering 可以通过查询字符串参数来指定查询条件,例如 ?field1=value1&field2=value2

首先,您需要在您的序列化器类中定义要用于过滤的字段。例如,如果您希望根据书名和作者名进行查询,您可以将它们添加到您的 BookSerializer 中:

示例代码:

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'name', 'author']
        read_only_fields = ['id']

接下来,您需要在您的视图类中添加一个过滤器,并将其与查询字符串参数相关联。例如,如果您希望使用 nameauthor 字段进行过滤,您可以添加一个 DjangoFilterBackend 过滤器,并将 nameauthor 字段添加到 filter_fields 列表中:

from rest_framework import generics, filters
from django_filters.rest_framework import DjangoFilterBackend
from .models import Book
from .serializers import BookSerializer

class BookListCreateView(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filter_fields = ['name', 'author']
    search_fields = ['name', 'author']

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

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

在上面的代码中,我们添加了一个名为 DjangoFilterBackend 的过滤器,并将其与 filter_backends 属性相关联。我们还将 nameauthor 字段添加到 filter_fields 列表中,以指定这些字段可用于过滤。最后,我们还添加了 SearchFilter 过滤器,以便支持搜索功能。

现在,您可以使用查询字符串参数来指定要使用的过滤条件。例如,如果您要查询所有书名为 “Python” 的书籍,您可以发送以下请求:

GET /books/?name=Python
# 如果您要查询作者名为 "Guido van Rossum" 的所有书籍,您可以发送以下请求:
GET /books/?author=Guido van Rossum
# 如果您要同时查询书名为 "Python" 和作者名为 "Guido van Rossum" 的所有书籍,您可以发送以下请求:
GET /books/?name=Python&author=Guido van Rossum

需要注意的是,DjangoFilterBackend 需要安装 django-filter 库才能使用。您可以通过运行 pip install django-filter 来安装它。

自定义Mixin

"""
Basic building blocks for generic class based views.

We don't bind behaviour to http method handlers yet,
which allows mixin classes to be composed in interesting ways.
"""
from rest_framework import status
from rest_framework.response import Response
from rest_framework.settings import api_settings
from app01.Result import Result

class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}


class ListModelMixin:
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        # 自定义结果集
        return Response(Result.success(serializer.data))


class RetrieveModelMixin:
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)


class UpdateModelMixin:
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)


class DestroyModelMixin:
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

viewset
path('drfViewsetinGenApiView', views.drfViewsetinGenApiView.as_view(actions={
        "get": "list",
        "post": "create"
    }))
class drfViewsetinGenApiView(GenericViewSet, ListModelMixin, CreateModelMixin):
    queryset = UserInfo.objects.all()
    serializer_class = UserMyModelSerializer
    # 条件查询
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filter_fields = ['id', 'name', 'age']
    search_fields = ['id', 'name', 'age']
	# 分页查询
    pagination_class = PageNumberPagination
    

    # 重写ListModelMixin的list函数
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        # 接受前端传递的页码参数,没有page就查询全部
        # 可以实现单表的分页+条件查询
        page_size = request.query_params.get('page')
        if page_size is not None:
            self.pagination_class.page_size = int(page_size)
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(Result.success(serializer.data))
}))

```python
class drfViewsetinGenApiView(GenericViewSet, ListModelMixin, CreateModelMixin):
    queryset = UserInfo.objects.all()
    serializer_class = UserMyModelSerializer
    # 条件查询
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filter_fields = ['id', 'name', 'age']
    search_fields = ['id', 'name', 'age']
	# 分页查询
    pagination_class = PageNumberPagination
    

    # 重写ListModelMixin的list函数
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        # 接受前端传递的页码参数,没有page就查询全部
        # 可以实现单表的分页+条件查询
        page_size = request.query_params.get('page')
        if page_size is not None:
            self.pagination_class.page_size = int(page_size)
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(Result.success(serializer.data))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值