全称django rest framework,语言:python
用于构建web API,需要有django环境
python manage.py startproject tutorial//创建项目
python manage.py startapp user //创建应用目录
对于drf的操作可以参考django文档 (建议了解基础的drf之后再看文档)The web framework for perfectionists with deadlines | Django (djangoproject.com)
位置:
视图文件-user/views.py
路由文件-config/urls.py
配置文件-settings.py
数据库表类 user/models.py。数据库-model,前后端分离,api设计规范-restful表征状态转移(面向资源开发)+rpc。
结构:
模型-视图-url控制器-serializer(序列器)
restful-api规范,基于请求资源,通过请求方式判断请求类型,例如post,get,put,delete,patch.增删改查查。/student get,/student delete.
FBV,CBV(fbv,file_name.function_name)
视图:view-django
继承类之后的方法名称选项范围为以下:
请求方法(类中定义方法的名称不能不一样):get post put delete patch head options trace
#views.py
class DogView(view):
def get(self,request):
return HttpResponse()
#urls.py
path("path",views.DogView.as_view())#本质上是fbv
#as_view做了什么?根据请求方法分发(dispatch())类方法。类方法由我们自己定义。
#others
super().**调用父类的方法
视图:apiview-drf
相对于view,重新包装了as_view和dispatch。定义方法和view一样。
优化了request.post/data-反序列化字典和csrf,认证、权限
request.data,request.query_params,request._request(django原生对象)
序列化器-serializers.Serializer
定义:模型类转json=序列化。针对模型写序列化器。序列化与反序列化:序列化,让数据变成前端可读的样式,反序列化,让数据变成能存储进数据库的样式。JSON的python对象和字符串转换。
from rest_framework.reponse import Response
class Dog(models.Model):
name = models.charField(max_length=20)
class DogSerializers(serializers.Serializer):
dogname = serializers.CharField(max_length=20,source="name")#source是数据库字段名称
class DogView(APIView):
def get(self,request):
dogs = Dog.objects.all()
serializer=DogSerializers(instance=dogs,many=True)#data是反序列化,instance是序列化(默认)
return Response(serializer.data)
def post(self,request):
serializer=DogSerializers(data=request.data)#反序列化
serializer.is_valid(raise_exception=false)
if(serializer.is_valid):
newBook = Dog.objects.create(**serializer.validated_data)
return Reponse(serializer.data)#自动被序列化的数据
else:
return Response(serializer.errors)#errors返回错误的字段的字典
视图:view-get,post,viewdetail-get-delete-put.
book.objects.get(pk=id)返回模型类对象
更新:serializer(instance=a,data=b)基于a更新
Book.objects.filter(pk=id).update(**serializer.validated_data)
serializer.save()
save()方法写在序列器create()里面
serializer本身有save()方法,所以是重写,save()可以重写为update或者create()
更新完返回值需要重新获得相关id并且重新定义属性instance--serializer.data
-->将保存逻辑写在序列器中。
class DogSerializers(serializers.Serializer):
dogname = serializers.CharField(max_length=20,source="name")#source是数据库字段名称
def create(self,validate_data):#save()有instance,调用update,没有调用create()
return Dog.objects.create(**self.validated_data)
class DogView(APIView):
def get(self,request):
dogs = Dog.objects.all()
serializer=DogSerializers(instance=dogs,many=True)#data是反序列化,instance是序列化(默认)
return Response(serializer.data)
def post(self,request):
serializer=DogSerializers(data=request.data)#反序列化
serializer.is_valid(raise_exception=false)
if(serializer.is_valid):
serializer.save()
return Reponse(serializer.data)#自动被序列化的数据
else:
return Response(serializer.errors)#errors返回错误的字段的字典
-->分写两个视图
#urls.py
path("app/dog/",views.DogViews.as_view())
re_path("app/dog/(\d+)",views.DogDetailView.as_view())
#views.py
class DogDetailView(APIView):
def get(self,request,pk):
dog = Dog.objetcs.get(pk=pk)#模型类对象
serilaizer=DogSerializer(instance=dog,many=false)
return serializer.data
def put(self,request,pk):
dog = Dog.objects.get(pk=pk)
serilaizer=DogSerializer(instance=dog,data=request.data)
if(seriliazer.is_valid()):
serilaizer.save()
Dog.objects.filter(pk=pk).update(**serilaizer.validated_data)
new = Dog.obejcts.get(pk=pk)
serializer.instance=new
return serializer.data#返回序列化instance的值(create也会给instance赋值,前提是create要return),否则validated_data
else:
return Reponse(serilaizer.errors)
-->把更新逻辑写在序列器中
#urls.py
path("app/dog/",views.DogViews.as_view())
re_path("app/dog/(\d+)",views.DogDetailView.as_view())
#serializer
class DogSerializers(serializers.Serializer):
dogname = serializers.CharField(max_length=20,source="name")#source是数据库字段名称
def create(self,validate_data):#save()有instance,调用update,没有调用create()
de update():
....
#views.py
class DogDetailView(APIView):
def get(self,request,pk):
dog = Dog.objetcs.get(pk=pk)#模型类对象
serilaizer=DogSerializer(instance=dog,many=false)
return serializer.data
def put(self,request,pk):
dog = Dog.objects.get(pk=pk)
serilaizer=DogSerializer(instance=dog,data=request.data)
if(seriliazer.is_valid()):
serilaizer.save()
return serializer.data#返回序列化instance的值(create也会给instance赋值,前提是create要return),否则validated_data
else:
return Reponse(serilaizer.errors)
def delete():
objects.get().delete()
序列器-ModelSerializer
在此之前用的是APIView,和serilaizer(字段需要自己一一对应创建)。
Dog类(models.Model).class DogSerailizers(serializers.ModelSerializer): ModelSerializer可以根据模型表自动创建。并且,内部已经有了create,update方法。可以直接用save()。
class XXserilaizer(ModelSerializer)
data =serializers.DateField(source="Dog_date")
class meta:
model = Dog
fields=["",""]//只针对选择的字段做序列化
exclude=["Dog_date"]//排除
视图-genericAPIview
增加了几个方法。请求分发还是和原来一样可以用。
1.get_serilaizer_class
2.get_serializer
3.get_queryset()
4.get_object()
class bookview(genericAPIView)
queryset=--.objects.all()#名称不能更改
serializer_class=--Serializers#名称不能更改
def get(self,request):
self.get_queryset()
self.get_serializer_class()()==self.get_serializer(instance=self.get_queryset(),many=true)
return response(serializer.data)
self.get_object()//自动获取pk,有名传参,路由urls(?p<pk>)
migrate.migrations是关于新建数据库
视图多继承-mixin(视图)
多继承,封装view函数逻辑。使用的同时要继承genericAPIView,也要写函数名。
class xx(listmodelMixin,GenericAPiView,createModelMixin,retrieveModelView,destroyModelView)
get
return self.list()
post
return self.create()
get
self.retrieve()
self.update()
...destroy()
依旧重复
视图-ListCreateAPIView()
可以包括list/createmixin,genericAPiview,def get ,post方法。
只用写queryset和serializer_class就行
视图-Retrieve--DestroyAPiView
视图-viewset
一个类下无法写两个get
尝试自主命名5个视图写在一起(通过urls分开5个视图)
as_view()将self.method在分发dispatch逻辑前修改
urls-
path(----,views.---Views.as_view({"get":"自定义方法"}))
re_path()
但是继承的是APIVIEW,没有genericView,
GenericViewSet
加上mixin,能分发不同视图方法(比如两个get)。--直接在urls.py文件里,将视图方法写在路由中就行。List(),update(),retrieve(),destroy(),create()
分发逻辑修改。
路由需要随着listapiview修改path url。
classview需要继承genericviewset,还有listapiview
modelviewset
路由文件和上面一样需要写---,这个类封装了genericviewset,还有listapiview等增删改查查mixin。
queryset=
serializer_class=
越封装越不灵活
router
router=router.defaultRouter
router.register(“dog”, views.DogView,base_name="animal")
urlpatterns += router.urls
联表存储
输入外键:
creator = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(),required=false)
输入集合:
creator=UserSerializer(many=True,read_only=True)
数据库创建
根据模型model文件创建数据库
python manage.py makemigrations
创建迁移文件,这时候还没有写入数据库,只是对比旧模型发现新的字段更改或者新的表。
python manage.py sqlmigrate appname 0001
可以查看下migrations 0001会对应于什么样子的SQL命令
python manage.py showmigrations
可以查看当前项目所有的app及对应的已经生效的migration文件,[x]表示migrte通过,[]表示未通过
可以直接手动删除文件,撤销更改,但是后面的文件是依赖前面的,不能删除中间而不删除最后的文件。
python manage.py migrate
将改动迁移到数据库,完成建表、修改字段等操作,操作成功后会在数据库django_migrations表中添加一条数据,表示migration文件已迁移
queryset-django数据类型
filter(),count(),values(),aggregate(),annotate()
aggregate是聚合,可以算sum,max,min,count
annotate是注释,更合理的名字是分组,会根据对象自动分组,annotate(count("id")),自动生成名字id__count,也可以annotate(total=count("id"))
__year,__date,__day,__month,__in,__lt,__gt,__gte。给字段加后缀会节省很多操作。