【一】改项目名
1.选择directory后,会发现,项目后面有个[],意思为他的配置还是02的,有两个解决办法
a.改完文件夹名去选择project项目名会直接给你改项目配置,就不会有中括号
b.在删前要把项目关了,在文件夹里删了他的idea(也就是他的配置文件)然后在文件夹,file--》open就会重新配置,就没有中括号了
但还是发现项目名和配置名还是不一致,且项目能运行,但是我们要保证一致,所以去把这个项目重命名drf002,就不能运行了
解决办法:
0.现在整个项目全局替换drf02,替换成drf002
1.设置里搜索django,如一下配置
2.移除运行里django重新生成一个
但是改了那个项目的就完了
【二】 模块与包及导入规则
1.模块--》就是py文件,在别的py文件把他导入,这个py文件就叫模块
2.脚本--》一个py文件,能直接右键运行
3.包--》文件夹下有__init__.py文件,并且包下可以有很多py文件--》py文件中有很多方法和类
# 重点:导入模块或包的规则
-1 绝对导入--》根指的是 环境变量,如果该路径在环境变量中就可以作为根,导入
-打印环境变量:sys.path
eg: 新建一个lib文件夹,里有个是模块,si模块里有demo方法
form lib.s1 import demo
-2 相对导入
-相当于当前的py文件
eg:在你同级的情况下建一个s1模块,里面写demo方法
from .s1 import demo
print(demo())
['D:\\pycharm\\pxrj\\drf\\drf02',# 项目目录
'D:\\pycharm\\pxrj\\drf\\drf02',
'D:\\python3.10\\python310.zip', 因为有这个所以能直接 import os,time
'D:\\python3.10\\DLLs',
'D:\\python3.10\\lib',
'D:\\python3.10',
'D:\\python3.10\\lib\\site-packages',装第三模块的地方,我梦去看django都在里面所以我们可以直接import django]
"""
# 以后如果我们写包,写第三方包
-可以直接 from 包名 import 即可
# 因为如果给别人用,别人下载完会在 site-packages 在环境变量
# 如果自己用,我们会放在项目根路径, 项目根路径 在环境变量中eg: 新建一个lib文件夹,里有个是模块,si模块里有demo方法
form lib.s1 import demo
"""
【三】断言assert(断定)
####1 断言的使用#####
assert 断不报错的条件(没有达到某条件是真就抛出) ,"报错的字符串"--->抛出AssertionError
如果不用断言,可以用主动报错raise
name="llh"
if name =="llh":
raise Exception("名字不能为llh")
else:
print("对")
####2 使用断言的位置 #####
-断定 某些值一定存在
-断定 某个值必须为 字符串类型 等等等
【四】drf之请求响应
4.1请求-支持的编码格式
1.drf编码,可以支持三种编码格式form-data,urlencoded,json
从request.data中取出请求体的数据
2.后期,有个上传文件接口--》只能接收form-data类型,其他类型不允许,怎么做
-控制某个接口,只能处理,一种编码格式,其他都不行
"""没有用我们指定的会报这个错
{
"detail": "不支持请求中的媒体类型 “application/json”。"
}
"""
3.使用方式1(局部使用)--》在视图类上直接配置,如果不配就会默认三种,如果空列表,就全都禁用
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class Book_View(APIView):
parser_classes = [MultiPartParser]
4.使用方式2(全局使用)--》在setting中,所有视图类都会使用这个解析
由以下的提示可知,我们写配置像下面示例一样去写就行在哪看的
from rest_framework import settings点进这个settings里就可以看
就只写下面这个就行
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
}
5.全局使用了,局部再定制,使用的是局部的,因为优先级局部高
class BookView(APIView):
parser_classes = [JSONParser]
6.优先级使用
-视图定制的
-配置中的
-最后才会使用drf内置的,三种都有
4.2响应
1.postman 返回json--》浏览器会返回好看的页面
2.控制,要求postman只返回json格式,浏览器也是只返回json格式
如何做:
3.局部使用
from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer
class BookView(APIView):
renderer_classes = [JSONRenderer]
4.全局
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
# 'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
5.全局使用了,局部再定制,使用的是局部的,因为优先级局部高
class BookView(APIView):
renderer_classes = [JSONRenderer]
"""优先级和上面一样"""
【五】两个视图基类(APIView,GenericAPIView)
5.1基于APIView+序列化类+Response写5个接口
1.view.py
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Book3, AuthorDetail, Author
from .serializer import BookModelSerialzier, AuthorSerializer
class Book_View(APIView):
def get(self, request):
obj = Book3.objects.all()
if obj:
serializer = BookModelSerialzier(instance=obj, many=True)
return Response(serializer.data)
return Response({"code": 201, "msg": "查询失败"})
def post(self, request):
print(request)
print(type(request.data))
serializer = BookModelSerialzier(data=request.data)
if serializer.is_valid():
# 处理有效的数据(例如保存到数据库)
serializer.save()
# 返回序列化后的数据或响应
return Response(serializer.data)
else:
# 返回错误信息
return Response(serializer.errors, status=400)
class BookDetailView(APIView):
def put(self,request,book_id):
obj=Book3.objects.filter(pk=book_id).first()
if obj:
serializer=BookModelSerialzier(data=request.data,instance=obj)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response({"code": 201, "msg": "修改失败"})
def get(self,request,book_id):
obj = Book3.objects.filter(pk=book_id).first()
if obj:
serializer = BookModelSerialzier(instance=obj)
return Response(serializer.data)
return Response({"code": 201, "msg": "查询失败"})
def delete(self,request,book_id):
res=Book3.objects.filter(pk=book_id).delete()
if res:
return Response({"code": 200, "msg": "删除成功"})
else:
return Response({"code": 201, "msg": "删除失败"})
class AuthorView(APIView):
def get(self,request):
obj=Author.objects.all()
if obj:
serializer=AuthorSerializer(instance=obj,many=True)
return Response(serializer.data)
else:
return Response({"code":1001,"msg":"查询失败"})
def post(self,request):
serializer=AuthorSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
class AuthorDetailView(APIView):
def put(self,request,author_id):
obj=Author.objects.filter(pk=author_id).first()
if obj:
serializer = AuthorSerializer(instance=obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response({"code": 201, "msg": "修改失败"})
def get(self,request,author_id):
obj = Author.objects.filter(pk=author_id).first()
if obj:
serializer = AuthorSerializer(instance=obj)
return Response(serializer.data)
return Response({"code": 201, "msg": "查询失败"})
def delete(self,request,author_id):
res=Author.objects.filter(pk=author_id).delete()
if res:
return Response(status=200)
else:
return Response({"code": 201, "msg": "删除失败"})
2.serializer.py
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Book3, Publish, Author, AuthorDetail
class BookModelSerialzier(serializers.ModelSerializer):
class Meta:
model = Book3
fields = ['id','name', 'price', 'publish', 'authors', 'publish_detail', 'author_list'] # 新增的publish_real 也要注册
extra_kwargs = {'name': {'max_length': 8}, 'price': {'max_value': 100},
'publish': {'write_only': True},
'authors': {'write_only': True},
}
def validate_name(self, name):
if "sb" in name:
raise ValidationError("名字中不能带有sb")
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True)
class AuthorDetailSerializar(serializers.Serializer):
gender = serializers.IntegerField()
phone = serializers.IntegerField()
class AuthorSerializer(serializers.Serializer):
name = serializers.CharField()
age = serializers.IntegerField()
addr = serializers.CharField()
gender = serializers.CharField(write_only=True)
phone = serializers.IntegerField(write_only=True)
author_detail=AuthorDetailSerializar(read_only=True)
def create(self, validated_data):
gender=validated_data.pop('gender')
phone=validated_data.pop('phone')
new_dict={"gender":gender,"phone":phone}
authordetail=AuthorDetail.objects.create(**new_dict)
validated_data["author_detail_id"]=authordetail.id
print(validated_data)
author = Author.objects.create(**validated_data)
return author
def update(self,instance, validated_data):
print(validated_data)
gender=validated_data.pop('gender')
phone=validated_data.pop('phone')
instance.author_detail.gender=gender
instance.author_detail.phone=phone
print(validated_data)
for key in validated_data:
# key是一个字符串,字符串和对象就可以想到反射
setattr(instance, key, validated_data[key])
return instance
3.models.py
from django.db import models
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
city = models.CharField(max_length=32)
class Book3(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True)
authors=models.ManyToManyField(to='Author')
def publish_detail(self):
return {"name":self.publish.name,"addr":self.publish.addr}
def author_list(self):
l=[]
obj=self.authors.all()
for i in obj:
l.append({'name':i.name,'age':i.age})
return l
class AuthorDetail(models.Model):
gender=models.IntegerField(choices=((1,'男'),(2,'女'),(0,'未知')))
phone=models.IntegerField()
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
addr = models.CharField(max_length=32)
author_detail = models.OneToOneField(to=AuthorDetail, on_delete=models.SET_NULL, null=True)
5.1基于GenericAPIView+序列化类+Response写5个接口
1.与APIView不一样的地方
就是多写了两个类属性,以及多了三个get方法
#类属性
queryset = Book.objects.all()
serializer_class = BookModelSerialzier
#在方法内把数据扔进序列化类里
serializer = self.get_serializer(instance=obj, many=True)
#获取多条数据
obj=self.get_queryset()
#获取单条
obj=self.get_object()
#不同的只有视图类,**序列化类和路由跟之前一样**
class Book_View(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerialzier
def get(self, request):
obj=self.get_queryset()
if obj:
serializer = self.get_serializer(instance=obj, many=True)
return Response(serializer.data)
return Response({"code": 201, "msg": "查询失败"})
def post(self, request):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
# 处理有效的数据(例如保存到数据库)
serializer.save()
# 返回序列化后的数据或响应
return Response(serializer.data)
else:
# 返回错误信息
return Response(serializer.errors, status=400)
class BookDetailView(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerialzier
def put(self,request,book_id):
obj=self.get_object()
if obj:
serializer=self.get_serializer(data=request.data,instance=obj)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response({"code": 201, "msg": "修改失败"})
def get(self,request,book_id):
obj=self.get_object()
if obj:
serializer = self.get_serializer(instance=obj)
return Response(serializer.data)
return Response({"code": 201, "msg": "查询失败"})
def delete(self,request,book_id):
res=self.get_object().delete()
if res:
return Response({"code": 200, "msg": "删除成功"})
else:
return Response({"code": 201, "msg": "删除失败"})
【六】5个视图扩展类
# 1 5个视图扩展类---》必须配合GenericAPIView
"""从上面的继承GenericAPIView的类发现,很多代码都是一样的能不能做个封装"""
举个下述类中的源码例子,不难发现是我们之前的步骤做了封装
"""
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)
#create方法负责处理请求数据的验证、序列化、以及创建响应。而perform_create则专注于执行与数据库相关的操作,如保存对象。这种分离使得代码更加清晰和模块化,也更容易维护和扩展。
def perform_create(self, serializer):
serializer.save()
"""
from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, CreateModelMixin,
DestroyModelMixin, ListModelMixin
#2 使用只要继承GenericAPIView,RetrieveModelMixin你想要哪个接口,编写一下 get 、post、delete、get、put--》就能实现某个或某几个接口
"""注意在定义路由的时候,那个路径转换器的名称必须是pk否则会报错"""
"""下面的super可以用self替换,但是self从自身开始找,super从最近父类开始找,都能找到,但是super更快效率更高
"""
**路由和序列化类是一样的**就视图类不同
class Book_View(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookModelSerialzier
def get(self, request):
return super().list(request)
def post(self, request):
return super().create(request)
class BookDetailView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
queryset = Book.objects.all()
serializer_class = BookModelSerialzier
def put(self,request,pk):
return super().update(request,pk)
def get(self,request,pk):
return super().retrieve(request,pk)
def delete(self,request,pk):
return super().destroy(request,pk)
【七】9 个视图子类
#1 就是上面五个视图扩展类的进行组合多出四个就总共九个了
from rest_framework.generics import ListAPIView, CreateAPIView, UpdateAPIView, RetrieveAPIView, DestroyAPIView
from rest_framework.generics import ListCreateAPIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView
#2.使用方法和上面一致,
class Book_View(GenericAPIView,ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerialzier
def get(self, request):
return super().list(request)
def post(self, request):
return super().create(request)
class BookDetailView(GenericAPIView,RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerialzier
def put(self,request,pk):
return super().update(request,pk)
def get(self,request,pk):
return super().retrieve(request,pk)
def delete(self,request,pk):
return super().destroy(request,pk)
【八】视图集
#1.**序列化类是一样的**
**路由和视图都不一样**
"""若视图写完,没弄路由的映射,会报错,根据报错进行解析映射
TypeError: The `actions` argument must be provided when calling `.as_view()` on a ViewSet. For example `.as_view({'get': 'list'})`"""
# # 这个类里就没有 get get post put delete 方法了
# # 这个类里有: list retrieve create update destroy 方法
路由
from app01.views import Book_View,BookDetailView
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', Book_View.as_view({'get': 'list','post':'create'})),
path('books/<int:pk>', BookDetailView.as_view({'get': 'retrieve','put':'update','delete':'destroy'})),
]
视图
from rest_framework.viewsets import ModelViewSet
class Book_View(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerialzier
class BookDetailView(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerialzier