DRF序列化、认证、跨域问题

初级

#models.py
from django.db import models
class User(models.Model):
    user = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    user_detail = models.OneToOneField(to='UserDetail', on_delete=models.SET_NULL, null=True, db_constraint=False)

    def account_msg(self):
        return self.user + ":" + self.password
class UserDetail(models.Model):
    phone_num = models.CharField(max_length=11)
    info = models.TextField()
    
# 自定义序列化类:为具体的类提供序列化
# objectjson.py
from rest_framework import serializers
class UserJson(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(source='user')
    password = serializers.CharField()
    account = serializers.CharField(source='account_msg')
    # user_detail = serializers.CharField()
    # user_phone_num = serializers.CharField(source='user_detail.phone_num')
    detail = serializers.SerializerMethodField()
    def get_detail(self, object):
        return {'phone': object.user_detail.phone_num, 'info': object.user_detail.info}#自定义返回的数据格式
      
#views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from app import objectjson, models
class Users(APIView):
    def get(self, request):
        user_list = models.User.objects.all()
        user_data = objectjson.UserJson(user_list, many=True).data
        return Response({
            'status': 0,
            'message': 'ok',
            'results': user_data
        })

#urls.py
urlpatterns = [
    url(r'^users/', views.Users.as_view()),
]

高级

#models.py
class Book(models.Model):
    name = models.CharField(max_length=20)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    author = models.ManyToManyField('Author', db_constraint=False)
class Author(models.Model):
    name = models.CharField(max_length=20)
    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.SET_NULL, null=True, db_constraint=False)
class AuthorDetail(models.Model):
    age = models.IntegerField()
    telephone = models.BigIntegerField()
# 自定义序列化类:为具体的类提供序列化
# objectjson.py
class AuthorDetailJson(serializers.ModelSerializer):
    class Meta:
        model = models.AuthorDetail
        # fields ='__all__' #对外提供所有字段
        exclude = ['id']  # 和fields两者取一,代表除id字段不提供
class AuthorJson(serializers.ModelSerializer):
    class Meta:
        model = models.Author
        fields = ['id', 'name', 'detail']  # 自定义的detail字段也要声明也要提供哪些字段
        # fields = '__all__'
    detail = serializers.SerializerMethodField()
    # exclude = ['author_detail']
    def get_detail(self, object):
        detail_data = AuthorDetailJson(object.author_detail).data
        return detail_data
class BookJson(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        exclude = ['author']
        # fields = '__all__'
        # depth = 2
    authors = serializers.SerializerMethodField()
    def get_authors(self, object):
        author_list = object.author.all()
        author_data = AuthorJson(author_list, many=True).data
        return author_data
 #views.py
class Books(APIView):
    def get(self, request):
        book_list = models.Book.objects.all()
        book_data = objectjson.BookJson(book_list, many=True).data
        return Response({
            'status': 0,
            'message': 'ok',
            'results': book_data
        })
  
#urls.py
urlpatterns = [
    url(r'^books/', views.Books.as_view()),
]

校验

# objectjson.py
class BookJson(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'
        #单个字段校验
    name = serializers.CharField(min_length=3, max_length=5, error_messages=
    {
        'min_length': '太短了', 'max_length': '太长了'
    })

    # 局部钩子
    def validate_name(self, value):
        from rest_framework.exceptions import ValidationError
        book_object = models.Book.objects.filter(name=value)
        if book_object:
            raise ValidationError('书名已经存在')
        if 'sb' in value:
            raise ValidationError('不能出现敏感词汇')
        return value
# views.py
class Books(APIView):
    def post(self, request):
        book = request.data
        book_json = objectjson.BookJson(data=book)  # 必须明确data
        if book_json.is_valid():
            book_json.save()
            return Response({
                'status': 0,
                'message': 'ok',
                'results': book_json.data
            })
        return Response({
            'status': 1,
            'msg': book_json.errors
        })

全局钩子

# 全局钩子校验
def validate(self, attrs):
    from rest_framework.exceptions import ValidationError
    pwd = attrs.get('pwd')
    re_pwd = attrs.get('re_pwd')
    if pwd == re_pwd:
        return attrs
    else:
        raise ValidationError('密码校验失败')
了解

数据删改查

# views.py
class Book(APIView):
    def get(self, request, id):
        book = models.Book.objects.filter(pk=id).first()
        book_data = objson.BookJson(book).data
        return Response({
            'status': 0,
            'msg': 'ok',
            'results': book_data
        })

    def put(self, request, id):
        book = models.Book.objects.filter(pk=id).first()
        book_json = objson.BookJson(data=request.data, instance=book)  # 通过instance标识修改的对象
        if book_json.is_valid():
            book_json.save()  # 同样用save更新到数据库
            return Response({
                'status': 0,
                'msg': 'ok',
                'results': book_json.data
            })
        return Response({
            'status': 1,
            'msg': book_json.errors,
        })

    def delete(self,request,id):
        models.Book.objects.filter(pk=id).delete()  # 删除操作直接用ORM操作数据库
        return Response({
            'status': 2,
            'msg': 'delete success',
        })

基于ORM操作增删改

class Books(APIView):
  #获取所有书籍
    def get(self, request):
        book_list = models.Book.objects.all()
        book_data = objectjson.BookJson(book_list, many=True).data
        return Response({
            'status': 0,
            'message': 'ok',
            'results': book_data
        })
        #增加书籍
    def post(self, request):
        name = request.data.get('name')
        price = request.data.get('price')
        author = request.data.get('author')
        book_object = models.Book.objects.create(name=name, price=price)
        book_object.author.add(*author)
        book_data = objectjson.BookJson(book_object).data
        return Response({
            'status': 0,
            'message': 'ok',
            'results': book_data
        })
      
      
class Book(APIView):
  #获取一本书籍
    def get(self, request, id):
        book = models.Book.objects.filter(pk=id).first()
        book_data = objectjson.BookJson(book).data
        return Response({
            'status': 0,
            'message': 'ok',
            'results': book_data
        })
        #修改书籍
    def put(self, request, id):
        book_object = models.Book.objects.filter(pk=id).first()  # type:models.Book
        name = request.data.get('name')
        price = request.data.get('price')
        author = request.data.get('author')
        book_object.name = name
        book_object.price = price
        book_object.author = author
        book_object.save()
        book_data = objectjson.BookJson(book_object).data
        return Response({
            'status': 0,
            'message': 'ok',
            'results': book_data
        })
        #删除书籍
    def delete(self, request, id):
        models.Book.objects.filter(pk=id).delete()
        return Response({
            'status': 0,
            'message': 'ok',
            'results': 'delete success'
        })

Django跨域问题

什么是跨域

'''
通常情况下,A网站访问B服务器资源时,不满足以下三个条件其一就是跨域访问
1.协议不同
2.端口不同
3.主机不同
'''

Django解决跨域

'''
安装django-cors-headers模块

在settings.py中配置
# 注册app
INSTALLED_APPS =[
    ...
    'corsheaders'
]
#添加中间件
MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware'
]
#允许跨域源
CORS_ORIGIN_ALLOW_ALL = True
'''

认证组件

# views.py

class Auth:
      def authenticate(self,request):
          #完全具备认证功能
        pass
class Book(APIView):
      authentication_classes = [Auth,]

认证源码流程

"""
1.views.Books.as_view()2.view = super(APIView, cls).as_view(**initkwargs)  分发给dispatch
3.def dispatch(self, request, *args, **kwargs):  
4. 
request = self.initialize_request(request, *args, **kwargs) 封装request
self.initial(request, *args, **kwargs)  三大认证
5.self.perform_authentication(request) 转向Request类的user
6.request.py的Request的user  self._authenticate()
7.self.authenticators  self是drf的request对象
8.drf的request对象的init方法 authenticators是初始化参数
9.在哪初始化的: request = def initialize_request(self, request, *args, **kwargs)
10.self.get_authenticators() 需要 self.authentication_classes
11.self代表APIView类或子类对象,在自定义Books(APIView)中提供
"""
原文地址:https://www.cnblogs.com/ShenJunHui6/p/10878814.html