安装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中使用已经存在的数据库表,需要进行以下步骤:
- 在Django的settings.py文件中,配置数据库连接信息,包括数据库类型、数据库名称、数据库用户名、数据库密码、数据库主机和端口等信息。
- 在models.py文件中,定义一个类,该类对应已经存在的数据库表,并且使用Meta类指定该类对应的数据库表名。
- 在该类中定义字段,每个字段对应数据库表中的一个列。
例如,假设已经存在一个名为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的步骤如下:
-
创建视图类
首先,需要创建一个继承自Django提供的预定义视图类的视图类。例如,下面是一个继承自ListView的视图类:
from django.views.generic import ListView from .models import MyModel class MyModelListView(ListView): model = MyModel
在上述代码中,MyModelListView继承自Django提供的ListView类,并定义了model属性为MyModel。
-
定义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的一些主要特点:
- 序列化:DRF提供了一种方便的方法来将模型实例转换为JSON等常见格式。
- 视图:DRF提供了一组基于类的视图,可以轻松地创建API视图。
- 认证和权限:DRF提供了一组内置的身份验证和权限类,可以轻松地保护API端点。
- 分页:DRF提供了内置的分页支持,可以轻松地处理大量数据。
- 测试:DRF提供了一组内置的测试工具,可以轻松地测试API端点。
下面是使用DRF创建API的一些基本步骤:
-
安装DRF
pip install djangorestframework
-
创建序列化器:
序列化器用于将模型实例转换为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()方法用于创建和更新模型实例。
-
创建视图
视图用于处理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属性。
-
定义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()
,以帮助您检索和操作对象。
使用这些混合类,您可以轻松地构建各种不同类型的视图。例如,如果您需要一个列表视图和一个创建视图,您可以将 ListModelMixin
和 CreateModelMixin
添加到您的视图类中,如下所示:
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)
在上面的代码中,我们将 ListModelMixin
和 CreateModelMixin
添加到我们的 BookListCreateView
视图类中,并实现了 get()
和 post()
方法来处理 GET
和 POST
请求。在 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 视图类,包括 GenericAPIView
;mixins
模块提供了一组通用的视图操作,例如 ListModelMixin
和 CreateModelMixin
;filters
模块提供了一些常用的过滤器类,例如 SearchFilter
;PageNumberPagination
是一个分页器类,用于分页数据;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
的视图类,它继承自 GenericAPIView
、ListModelMixin
和 CreateModelMixin
。这意味着我们可以在这个视图类中使用 GET
和 POST
请求方法,并且可以使用 ListModelMixin
和 CreateModelMixin
提供的方法来实现对数据的读取和创建操作。
在视图类中,我们定义了一些属性和方法:
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']
接下来,您需要在您的视图类中添加一个过滤器,并将其与查询字符串参数相关联。例如,如果您希望使用 name
和 author
字段进行过滤,您可以添加一个 DjangoFilterBackend
过滤器,并将 name
和 author
字段添加到 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
属性相关联。我们还将 name
和 author
字段添加到 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))