drf-->ModelSerializer:mysql
相关: 1.setting配置; 2.路由分发,路由相关; 3.自定义异常处理; 4.model相关; 5.serializers序列化相关; 6.view相关;
settings.pylinux
INSTALLED_APPS = [ ... 'rest_framework', ] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'dg_proj', 'USER': 'root', 'PASSWORD': '123', } } LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False
MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
项目名下__init__文件中git
import pymysql
pymysql.install_as_MySQLdb()
路由相关sql
# 主路由 from django.conf.urls import url, include from django.contrib import admin from django.views.static import serve from django.conf import settings urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^api/', include('api.urls')), url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}), ] #子路由 urlpatterns = [ url(r'^books/$', views.Book.as_view()), url(r'^books/(?P<pk>.*)/$', views.Book.as_view()), url(r'^v2/books/$', views.V2Book.as_view()), url(r'^v2/books/(?P<pk>.*)/$', views.V2Book.as_view()), ]
model.py数据库
基表:存储有关数据库的信息的底层表,在数据库中独创的对象 class BaseModel(models.Model): is_delete = modles.BooleanField(default=0) create_time = models.DateTimeField(auto_now_add=True) #做为基表的model不能再数据库中造成对应的表***** class Meta: abstract = True
class Book(BaseModel): name = models.CharField(max_length=64) price = models.DecimalField(max_digits=5, decimal_places=2) img = models.ImageField(upload_to='img', default='img/default.jpg') publish = models.ForeignKey( to='Publish', db_constraint=False, # 断关联 related_name='books', # 反向查询字段:publish_obj.books 就能访问全部出版的书 on_delete=models.DO_NOTHING, # 设置连表操做关系 ) authors = models.ManyToManyField( to='Author', db_constraint=False, related_name='books' ) # 序列化插拔式属性 - 完成自定义字段名完成连表查询 @property def publish_name(self): return self.publish.name @property def author_list(self): return self.authors.values('name', 'age', 'detail__mobile').all() class Publish(BaseModel): """name、address、is_delete、create_time""" name = models.CharField(max_length=64) address = models.CharField(max_length=64) class Meta: db_table = 'publish' verbose_name = '出版社' verbose_name_plural = verbose_name def __str__(self): return self.name class Author(BaseModel): """name、age、is_delete、create_time""" name = models.CharField(max_length=64) age = models.IntegerField() class Meta: db_table = 'author' verbose_name = '做者' verbose_name_plural = verbose_name def __str__(self): return self.name class AuthorDetail(BaseModel): """mobile, author、is_delete、create_time""" mobile = models.CharField(max_length=11) author = models.OneToOneField( to='Author', db_constraint=False, related_name='detail', on_delete=models.CASCADE, ) class Meta: db_table = 'author_detail' verbose_name = '做者详情' verbose_name_plural = verbose_name def __str__(self): return '%s的详情' % self.author.name
admin.pydjango
from . import models admin.site.register(models.Book) admin.site.register(models.AuthorDetail) admin.site.register(models.Author) admin.site.register(models.Publish)
django 脚本化启动api
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "drfday1.settings") django.setup()
exception.py:自定义异常处理器服务器
from rest_framework.views import excepthon_handler as drf_excepthon_handler from rest_framework.views import Response from rest_framework import status def exception_handler(exc,context): #drf的 exception_handler作基础处理 response = drf_exception_handler(exc,conteax) if response is None: print('%s-%s-%s'%(context['view'],context['request'].method,exc)) return Response({ 'detail':'服务器错误' },status=status.HTTP_500_INTERNAL_SERVER_ERROR,exception=True) return response
Serializer.pyide
from rest_frameword.serializers import ModelSerializer,serializerMethodField from . import models from rest_frameword.excepthon import ValidationError #序列化 class BookModelSerializer(ModelSerializer): class Meta: #(*****) #序列化类关联的model类 model = models.Book #参与序列化的字段 fields = ('name','price','publish','author') #(***) #全部字段 fields = '__all__' #exclude 是除过fields查出的全部字段,与fields不能共存 exclude = ('id','img') #连表查询深度 depth=1 #反序列化 class BookModelDeserializer(ModelSerializer): class Meta: model = models.Book # fields = ('name','price','publish','authors') # extra_kwargs 用来完成反序列化字段的 系统校验规则 fields = '__all__' extra_kwargs ={ 'name':{ 'write_only':True, 'min_length':1, 'error_messages':{ 'required': '必填项', 'min_length': '不够', } } } 单个字段的验证 1.在序列化器里定义校验字段的钩子方法 validate_字段 2.获取字段的数据 3.验证不经过,抛出异常 raise serializers.ValidationError("校验不经过的说明") 4.验证经过,直接返回字段数据 def validate_title(self,value): # 判断value是否含有敏感字段 if "xx" in value: # 存在敏感字段,抛出异常并附上自定义的缘由 raise serializers.ValidationError("该字段含有敏感词") # 不存在,则直接返回 return value 多个字段的验证 1.在序列化器定义validate方法 2.attrs是全部数据组成的字典 3.不符合抛出异常 raise serializers.ValidationError("校验不经过的说明") def validate(self, attrs):# arrrs是数据组成的字典 # 判断linux的数是否在linux分类 if "linux" in attrs.get('title') and attrs['category_post'] == 2: return attrs else: raise serializers.ValidationError("图书与分类不一致") 自定义验证器 使用:在字段添加 validators=[自定义验证器,] def my_validate(value): if "xxx" in value: raise serializers.ValidationError("该字段包含敏感词!!!") else: return value title = serializers.CharField(max_length=32,validators=[my_validate,]) # 使用自定义验证器 #序列化与反序列化整合版 (终极版本) class V2BookModelSerializer(ModelSerializer): """ 1) fields中设置全部序列化与反序列化字段 2) extra_kwargs划分只序列化或只反序列化字段 write_only:只反序列化 read_only:只序列化 自定义字段默认只序列化(read_only) 3) 设置反序列化所需的 系统、局部钩子、全局钩子 等校验规则 """ class Meta: model = models.Book fields = ('name','price','img','author_list','publish_name','publish','authors') extra_kwargs = { 'name':{ 'required':True, 'min_length':3, 'error_messages':{ 'required':'必填项', 'min_length':'最少3' } }, 'publish':{'write_only':True}, 'authors':{'write_only':True}, 'img':{'read_only':True}, 'author_list':{'read_only':True}, 'publish_name':{'read_only':True}, } #单字段校验 def validate_name(self,value): if 'xx' in value.lower(): raise ValidationError('书名不符合规则') return value #多字段校验 def validate(self,attrs): publish = attrs.get('publish') name = attrs.get('name') if models.Book.objects.filter(name=name,publish=publish): raise ValidationError('这本书已存在') return attrs
views.py:post
from . importo models,serializers from rest_framework.views import APIView from rest_framework.response import Pesponse class Books(APIView):# 继承rest_framework的APIView def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: try: book_obj = models.Book.objects.get(pk=pk,is_delete=False) book_data = serializers.BookModelSerializer(book_obj).data except: return Response({ 'status':1, 'msg':'没有这本书' }) else: book_query = models.Book.objects.all().filter(is_delete=False) book_data = serializers.BookModelSerializer(book_query,many=True).data return Response({ 'status':0, 'msg':'ok', 'results':book_data }) def post(self,request,*args,**kwargs): request_data = request.data book_ser = serializers.BookModelDeserializer(data=request_data) # 当校验失败,立刻终止当前视图方法,抛异常返回给前台 book_ser.is_valid(raise_exception=True) book_obj = book_ser.save()# 调用 create return Response({ 'status': 0, 'msg': 'ok', 'results': serializers.BookModelSerializer(book_obj).data }) class V2books(APIView): #查 def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: try: book_obj = models.Book.objects.filter(pk=pk,is_delete=False) book_data = serializers.V2BookModelSerializer(book_obj).data except: return Response({ 'status': 1, 'msg': '书籍不存在' }) else: book_list = models.Book.objects.all().filter(is_delete=False) book_data = serializers.V2BookModelSerializer(book_list,many=True).data return Response({ 'status': 0, 'msg': 'ok', 'results': book_data }) # 单增:传的数据是与model对应的字典 # 群增:传的数据是 装多个 model对应字典 的列表 def post(self,request,*args,**kwargs): request_data = request.data if isinstance(request_data,dict): many = False elif isinstance(request_data, list): many = True else: return Response({ 'status': 1, 'msg': '数据有误', }) book_ser = serializers.V2BookModelSerializer(data=request_data,many=many) book_ser.is_valid(raise_exception=True) book_result = book_ser.save() return Response({ 'status': 0, 'msg': 'ok', 'results': serializers.V2BookModelSerializer(book_result, many=many).data }) # 单删:有pk # 群删:有pks | {"pks": [1, 2, 3]} def delete(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: pks = [pk] else: pks = request.data.get('pks') if models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True): return Response({ 'status': 0, 'msg': '删除成功', }) return Response({ 'status': 1, 'msg': '删除失败', })
orm之 断关联多表关系
1、外键位置: 一对多 - 外键放多的一方 一对一 - 从逻辑正反向考虑,如做者表与做者详情表,做者删除级联删除详情,详情删除做者依旧存在,因此建议外键在详情表中 多对多 - 外键在关系表中 2、ORM正向方向连表查找: 正向:经过外键字段 eg: author_detial_obj.author 反向:经过related_name的值 eg:author_obj.detail 注:依赖代码见下方 3、连表操做关系: 1)做者删除,详情级联 - on_delete=models.CASCADE 2)做者删除,详情置空 - null=True, on_delete=models.SET_NULL 3)做者删除,详情重置 - default=0, on_delete=models.SET_DEFAULT 4)做者删除,详情不动 - on_delete=models.DO_NOTHING 注:拿做者与做者详情表举例 4、外键关联字段的参数 - 如何实现 断关联、目前表间操做关系、方向查询字段 i)做者详情表中的 author = models.OneToOneField( to='Author', related_name='detail', db_constraint=False, on_delete=models.CASCADE ) ii)图书表中的 publish = models.ForeignKey( to='Publish', related_name='books', db_constraint=False, on_delete=models.DO_NOTHING, ) authors = models.ManyToManyField( to='Author' related_name='books', db_constraint=False, ) 注: 1.ManyToManyField不能设置on_delete,OneToOneField、ForeignKey必须设置on_delete(django1.x系统默认级联,可是django2.x必须手动明确) 2.db_constraint db_constraint 惟一约束 db_constraint = True 方便查询 约束字段 db_constraint = fales(*) 不约束字段 同时也能够查询,就是保留跨表查询的便利 3.on_delete 外键的删除 1.on_delete = CASCADE:这就是默认的选项,级联删除,你无需显性指定它 2.on_delete = PROTECT:保护模式,若是采用该选项,删除的时候,会抛出ProtectedError错误 3.on_delete = SET_NULL:置空模式,删除的时候,外键字段被设置为空 注:前提就是blank=True, null=True,定义该字段的时候,容许为空 4.on_delete = SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值, 5.on_delete = DO_NOTHING: 该模式做者删除,详情不动 4 related_name = 'xxx' 子表在主表中对应的外键属性,反向引用