一、实现前后端分离,前后端数据交互均已json字符串形式

   路由模式,FBV. ==> url(r'^books/', views.books),

1)使用原生的json模型

# 请求 http://127.0.0.1:8000/books/
# [{"name": "python", "price": 20}, {"name": "linux", "price": 30}]
import json
def books(request):
    ll = [{'name':'python','price':20},
           {'name':'linux','price':30}]
    return HttpResponse(json.dumps(ll))

2)使用JsonResponse。默认safe=True

from django.http import JsonResponse
def books(request):
    ll = [{'name':'python','price':20},
           {'name':'linux','price':30}]
    return JsonResponse(ll,safe=False)

 注意在返回数据时,如果是列表类型需要加上fafe=False,其他则不用

3)在传输json数据时,如果传输中文会出现乱码的情况。需要加参数 ensure_ascii=False

import json
dic = {'name':'你好'}
print(json.dumps(dic,ensure_ascii=False))

4)在JsonResponse中使用需要加参数。json_dumps_params={'ensure_ascii':False}

from django.http import JsonResponse
def books(request):
    ll = [{'name':'python开心','price':20},
           {'name':'linux','price':30}]
    return JsonResponse(ll,safe=False,json_dumps_params={'ensure_ascii':False})

 二、使用djangorestframework,基于drf写resful的接口,写django框架以CBV模式

1)pip安装

pip install djangorestframework -i http://pypi.douban.com/simple

 2) 原生的CBV模式。执行过程,as_view() ==>dispatch ==>响应到具体的函数

url的写法。url(r'^books/', views.Book.as_view()。  类+as_view

from  django.views import View
class Book(View):
    def get(self,resquest):
        return HttpResponse('get')
    def post(self,resquest):
        return HttpResponse('post')

可根据请求模式自动判断该执行类的哪个方法

 会识别到方法是否在这里面  http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

3)使用psotman工具模拟发生请求

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^books/', views.Book.as_view()),
]

FBV模式视图函数

from rest_framework.views import APIView
class Book(APIView):
def get(self,request):
print(request.method) # GET
print(request._request.method) # GET
return HttpResponse('get')
def post(self,request):
print(request.method)
print(request._request.method)
print(request.POST) # 如果传json格式,这里面没有
print(request.data)
return HttpResponse('post')

 

传json格式

 三、restful的序列化组件

先生成数据库

from django.db import models

# Create your models here.
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)

    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    authors=models.ManyToManyField(to='Author')

    def test(self):
        return 'ttttttt'
    def __str__(self):
        return self.name


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)


class AuthorDatail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

    def __str__(self):
        return self.name
models.py

1)第一种,自己写序列化组件

 url(r'^books/', views.Book.as_view())

from rest_framework.views import APIView
from app01 import models
from django.http import JsonResponse

class Book(APIView):
    def get(self, request):
        response={'status':100,'msg':None}  # restful接口
        books = models.Book.objects.all()
        # 第一种常用写法
        # ll = []
        # for book in books:
        #     ll.append({'name':book.name,'price':book.price}.....)

        # 第二种 列表推导式
        ll = [ {'name':book.name,'price':book.price} for book in books ]
        response['msg']='查询成功'
        response['data']=ll     # 把查询到的数据列表赋予返回的字典
        return JsonResponse(response,safe=False)

    def post(self, request):
        return HttpResponse('post')

 2)第二种,使用Django的序列化组件

from rest_framework.views import APIView
from app01 import models
from django.core import serializers # django的序列号组件
class Book(APIView):
    def get(self, request):
        books = models.Book.objects.all()
        ret = serializers.serialize("json",books)
        return HttpResponse(ret)

    def post(self, request):
        return HttpResponse('post')

 3)使用drf定制序列化组件

 3.1)为了避免代码杂乱,序列号组件写在外部

查看models模型库

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)

    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    authors=models.ManyToManyField(to='Author')

    def test(self):
        return 'ttttttt'
    def __str__(self):
        return self.name


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)


class AuthorDatail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()

    def __str__(self):
        return self.name
models.py

 引入:from rest_framework import serializers

from rest_framework import serializers

class BookSer(serializers.Serializer):
    nid = serializers.IntegerField()
    name = serializers.CharField()
    price = serializers.CharField()
    # publish_date=serializers.DateField()
    publish_date = serializers.CharField()
    publish = serializers.CharField()
myserial.py

视图views写法

from rest_framework.views import APIView
from app01 import models
from app01 import myserial
from django.http import JsonResponse

class Book(APIView):
    def get(self, request):
        books = models.Book.objects.all()
        ret = myserial.BookSer(books,many=True)     # many=True 序列化多条数据
        return JsonResponse(ret.data,safe=False)   # data 序列化的字典方法

    def post(self, request):
        return HttpResponse('post')

备注:使用sqlite时,日期序列化出来为null,使用mysql则不会

3.2)增加查询信息

from rest_framework.views import APIView
from app01 import models
from app01 import myserial
from django.http import JsonResponse

class MyResponse():
    def __init__(self):
        self.status=100
        self.msg=None
    @property
    def get_dic(self):
        return self.__dict__

class Book(APIView):
    def get(self, request):
        response = MyResponse()
        books = models.Book.objects.all()
        ret = myserial.BookSer(books,many=True)     # many=True 序列化多条数据
        response.msg = "查询成功"
        response.data=ret.data
        return JsonResponse(response.get_dic,safe=False)   # data 序列化的字典方法

    def post(self, request):
        return HttpResponse('post')

 3.3)如果要想查询到publish指向邮箱

 publish = serializers.CharField(source='publish.email')

from rest_framework import serializers

class BookSer(serializers.Serializer):
    nid = serializers.IntegerField()
    name = serializers.CharField()
    price = serializers.CharField()
    # publish_date=serializers.DateField()
    publish_date = serializers.CharField()
    publish = serializers.CharField(source='publish.email')
myserial.py

 3.4)定制序列号组件时,如果让左边的名字随便定义

from rest_framework import serializers

class BookSer(serializers.Serializer):
    nid = serializers.IntegerField()
    xxx = serializers.CharField(source='name')
    price = serializers.CharField()
    # publish_date=serializers.DateField()
    publish_date = serializers.CharField()
    publish = serializers.CharField(source='publish.email')
myserial.py

 3.5)利用source调用models里面的方法

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)

    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    authors=models.ManyToManyField(to='Author')

    def test(self):
        return 'ttttttt'
    def __str__(self):
        return self.name
models.py Book

调用Book类的test方法

from rest_framework import serializers

class BookSer(serializers.Serializer):
    nid = serializers.IntegerField()
    xxx = serializers.CharField(source='name')
    price = serializers.CharField()
    # publish_date=serializers.DateField()
    publish_date = serializers.CharField()
    publish = serializers.CharField(source='publish.email')
    yyy = serializers.CharField(source='test')
myserial.py

3.6)查询多对多,有多个值时

from rest_framework import serializers
class BookSer(serializers.Serializer):
    # 下面是查询多个作者
    # authors=serializers.CharField(source='authors.all') # 如果查询多个作者,是查询为query的对象
    # SerializerMethodField,可以写一个方法,方法返回值,会赋值给authers
    authors=serializers.SerializerMethodField()
    def get_authors(self,obj):
        # obj 当前book对象
        authors=obj.authors.all()
        #ll = [ author.name for author in authors ]
        ll = [ {'name':author.name,'age':author.age} for author in authors ]
        return ll
myserial.py

 3.7)查询多个值的另一种方法,再加一个类方法

from rest_framework import serializers
class AuthorSer(serializers.Serializer):
    id = serializers.IntegerField(source='nid')
    age=serializers.CharField()
    name=serializers.CharField()

class BookSer(serializers.Serializer):
    aa=serializers.SerializerMethodField()
    def get_aa(self,obj):
        authors=obj.authors.all()
        ser=AuthorSer(authors,many=True)
        return ser.data
myserial.py

 3.8)ModelSerializer组件来查询多个值

 class Meta:fields = '__all__'和exclude = ['nid']

from rest_framework import serializers
from app01 import models
class AuthorSer(serializers.Serializer):
    id = serializers.IntegerField(source='nid')
    age=serializers.CharField()
    name=serializers.CharField()

class BookSer(serializers.ModelSerializer):
    class Meta:
        # 指定要序列化的表模型是book
        model = models.Book
        # __all__ 把所有字段都序列化
        fields = '__all__'
        # fields = ['nid','title','age]  # 可传入指定参数
        # exclude = ['nid'] 除了nid 都查找,exclude和fields 不能同时用
    # 如果不写下面的方法,查询出来的是关联表的id
    publish = serializers.CharField(source='publish.name')
    authors = serializers.SerializerMethodField()
    def get_authors(self,obj):
        authors=obj.authors.all()
        ll = [ {'name':author.name,'age':author.age} for author in authors ]
        return ll
myserial.py

3.9)更方便的深度自动查询。depth指定深度,最多用3层。内部机制for循环,增加数据库压力

from rest_framework import serializers
from app01 import models
class AuthorSer(serializers.Serializer):
    id = serializers.IntegerField(source='nid')
    age=serializers.CharField()
    name=serializers.CharField()

class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'
        depth=2     # 默认是0,所以前面才会写下面的方法

 

四、总结使用resful组件定制序列号组件

1)导入:from rest_framework import serializers

2) 写一个类(名字任意),继承serializers.Serializer

  可随意定制该类的序列化内容

from rest_framework import serializers

class BookSer(serializers.Serializer):
    nid = serializers.IntegerField()
    xxx = serializers.CharField(source='name')
    price = serializers.CharField()
    # publish_date=serializers.DateField()
    publish_date = serializers.CharField()
    publish = serializers.CharField()
    publish_email = serializers.CharField(source='publish.email')
    yyy = serializers.CharField(source='test')
myserial.py

3)如果不值得source,字段名,必须跟数据库列名一致

4)source  ==》既可以指定数据属性,又可以指定方法属性,可以写(publish.name)

5)使用:

  - 查询出要序列化的数据:books = models.Book.objects.all() (多条)

      - ret = myserial.BookSer(books,many=True)  ===》多条(queryset对象),必须指定many=True

      - ---------------------------

  - 查询出要序列化的数据:books = models.Book.objects.all().first() (一条)

      - ret = myserial.BookSer(books,many=False)  ===》1条(book对象),必须指定many=False

 6)aa=serializers.SerializerMethodField()

         - 必须配套一个方法(get_aa(self,obj)),方法的返回结果,会赋给aa

         - 在方法内部可以继续用序列化组件

7)序列化组件之serializers.ModelSerializer

  - 用法同Serializer

      - 不同点

           class BookSer(serializers.ModelSerializer):

                 class Meta:

                        # 指定要序列化的表模型是book

                    model=models.Book

                        fields='__all__'   或 exclude=['nid']

                        depth=1

五、post请求发送数据

1.1)序列化组件的字段校验和反序列化功能

from rest_framework import serializers
from app01 import models
class AuthorSer(serializers.Serializer):
    id = serializers.IntegerField(source='nid')
    age=serializers.CharField()
    name=serializers.CharField()

class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        exclude=['authors']
myserial.py

post函数反序列化组件

from rest_framework.views import APIView
from app01 import models
from app01 import myserial
from django.http import JsonResponse

class MyResponse():
    def __init__(self):
        self.status=100
        self.msg=None
    @property
    def get_dic(self):
        return self.__dict__

class Book(APIView):
    def get(self, request):
        response = MyResponse()
        books = models.Book.objects.all()
        # ret = myserial.BookSer(books,many=True)     # many=True 序列化多条数据
        ret = myserial.BookSer(instance=books,many=True)
        response.msg = "查询成功"
        response.data=ret.data
        return JsonResponse(response.get_dic,safe=False)   # data 序列化的字典方法

    def post(self, request):
        print(request.data)
        ser=myserial.BookSer(data=request.data)
        if ser.is_valid():  # 校验字段
            ser.save()
        else:
            print(ser.errors)
        return HttpResponse('post')
views.py

小结

# 只有:ModelSerializer. 能直接保存
def post(self, request):
    print(request.data)
    # 生成一个序列化对象
    ser=myserial.BookSer(data=request.data)
    # 判断字段是否校验通过
    if ser.is_valid():
        # 通过直接保存
        ser.save()
    else:
        # 错误信息
        print(ser.errors)
    return HttpResponse('post')

 1.2)post提交数据,进行局部校验

from rest_framework import serializers
from app01 import models
class AuthorSer(serializers.Serializer):
    id = serializers.IntegerField(source='nid')
    age=serializers.CharField()
    name=serializers.CharField()
from rest_framework.exceptions import ValidationError
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        exclude=['authors']

    name = serializers.CharField()
    def validate_name(self,value):
        if value.startswith('sb'):
            raise ValidationError('不能以sb开头')
        else:
            return value
myserial.py

视图函数编写,返回校验不通过的错误信息

from rest_framework.views import APIView
from app01 import models
from app01 import myserial
from django.http import JsonResponse

class MyResponse():
    def __init__(self):
        self.status=100
        self.msg=None
    @property
    def get_dic(self):
        return self.__dict__

class Book(APIView):
    def get(self, request):
        response = MyResponse()
        books = models.Book.objects.all()
        ret = myserial.BookSer(instance=books,many=True)
        response.msg = "查询成功"
        response.data=ret.data
        return JsonResponse(response.get_dic,safe=False)

    def post(self, request):
        print(request.data)
        ser=myserial.BookSer(data=request.data)
        if ser.is_valid():
            ser.save()
            return HttpResponse('成功')
        else:
            print(ser.errors)
        return JsonResponse(ser.errors)
views.py

 1.3)全局校验

from rest_framework import serializers
from app01 import models
class AuthorSer(serializers.Serializer):
    id = serializers.IntegerField(source='nid')
    age=serializers.CharField()
    name=serializers.CharField()
from rest_framework.exceptions import ValidationError
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        exclude=['authors']

    name = serializers.CharField()
    # 局部校验
    def validate_name(self,value):
        if value.startswith('sb'):
            raise ValidationError('不能以sb开头')
        else:
            return value
    # 全局校验
    def validate(self, value):
        print(value,type(value))
        name=value.get('name')
        price=value.get('price')
        if name!= price:
            raise ValidationError('他们不相等')
        else:
            return value
myserial.py

小结:

class BookSer(serializers.ModelSerializer):
    class Meta:
        pass
    # 局部校验
    def validate_name(self,value):
        pass
    # 全局校验
    def validate(self, value):
        pass

 六,put修改数据(为了避免日期问题的错误,已换成mysql)

1) 修改数据

 路由: url(r'^books/(?P<id>\d+)/', views.BookDetail.as_view()),

序列化组建编写

from rest_framework import serializers
from app01 import models

from rest_framework.exceptions import ValidationError
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        exclude=['authors']
myserial.py

视图函数编写

from django.shortcuts import render,HttpResponse

# Create your views here.

from rest_framework.views import APIView
from app01 import models
from app01 import myserial
from django.http import JsonResponse

class MyResponse():
    def __init__(self):
        self.status=100
        self.msg=None
    @property
    def get_dic(self):
        return self.__dict__




class BookDetail(APIView):
    def get(self,request,id):
        response=MyResponse()
        ret=models.Book.objects.filter(pk=id).first()
        ser=myserial.BookSer(instance=ret,many=False)
        response.msg='查询成功'
        response.data=ser.data
        return JsonResponse(response.get_dic,safe=False)

    def put(self,request,id):
        # 修改
        response=MyResponse()
        book=models.Book.objects.filter(pk=id).first()
        ser=myserial.BookSer(instance=book,data=request.data)

        if ser.is_valid():
            # 可以新增,可以修改
            ser.save()
            print(ser.data) # 对象的字典
            print(type(ser.instance),ser.instance)
            response.msg='修改成功'
            response.data=ser.data
        else:
            response.msg='修改失败'
            response.status=101
            response.data=ser.errors
        return JsonResponse(response.get_dic,safe=False)
views.py

 2)引入错误信息中文化

from rest_framework import serializers
from app01 import models

class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        exclude=['authors']
    name = serializers.CharField(error_messages={'required':'该字段必填'})
myserial.py

name = serializers.CharField(error_messages={'required':'该字段必填'})

 七、修改数据

class MyResponse():
    def __init__(self):
        self.status=100
        self.msg=None
    @property
    def get_dic(self):
        return self.__dict__

class BookDetail(APIView):
    def get(self,request,id):
        response=MyResponse()
        ret=models.Book.objects.filter(pk=id).first()
        ser=myserial.BookSer(instance=ret,many=False)
        response.msg='查询成功'
        response.data=ser.data
        return JsonResponse(response.get_dic,safe=False)

    def put(self,request,id):
        # 修改
        response=MyResponse()
        book=models.Book.objects.filter(pk=id).first()
        ser=myserial.BookSer(instance=book,data=request.data)

        if ser.is_valid():
            # 可以新增,可以修改
            ser.save()
            print(ser.data) # 对象的字典
            print(type(ser.instance),ser.instance)
            response.msg='修改成功'
            response.data=ser.data
        else:
            response.msg='修改失败'
            response.status=101
            response.data=ser.errors
        return JsonResponse(response.get_dic,safe=False)

    def delete(self,request,id):
        ret=models.Book.objects.filter(pk=id).delete()
        return HttpResponse('删除成功')
views.py

八、项目常规用法

url写法

from django.conf.urls import url
from django.contrib import admin
from django.urls import path
from app import views

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^books/$', views.BookView.as_view({'get':'get_all'})),
    url(r'^books/(?P<pk>\d+)/', views.BookView.as_view({'get':'get_one'})),
]

视图函数

from rest_framework.views import APIView
from rest_framework.viewsets import ViewSetMixin
class BookView(ViewSetMixin,APIView):
    def get_all(self,request):
        return HttpResponse('返回所有')
    def get_one(self,request,pk):
        return HttpResponse('返回一条')

 

posted on 2018-12-24 11:00  可口_可乐  阅读(722)  评论(0编辑  收藏  举报