Django REST framework

RESTful规范

你的项目接口是按照RESTful规范写的,那么它就是RESTful API。

设计指南:

用HTTP协议的四个请求方法表示四个动作。

GET:查询/获取资源

POST:创建资源

PUT:更新

DELETE:删除

十个设计规范:

	Https

	版本号

	api

	URL尽量不要用动词

	错误提示

	状态码

		1xx

		2xx

		3xx

		4xx

		502:网关不可用

		503:服务不可用

		504:网关超时

		505:版本不支持

	超链接表示表的关系

	过滤信息

	分页

浏览器的同源策略

什么是同源:

域名/ip + 端口 + 协议

http协议默认端口:80

https协议默认端口:443

浏览器对于非同源的请求会拒绝接受响应信息。

前后端分离的项目一般都会涉及到跨域问题

JSONP跨域(之前的解决方案)

不足:

只能GET请求

前端和后端都要支持

原理:

利用的就是浏览器对加载静态资源不做限制,比如

jQuery版JSONP

$.getJSON("http://127.0.0.1:8000/index/?callback=?", function(res){
console.log(res);
})

CORS跨域

简单请求和非简单请求

简单请求同时满足两大类条件:

1请求方法:

HEAD、GET、POST

2.请求头

Accept

Accept-Language

Content-Language

Last-Event-ID

Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

如果发送的是PUT或DELETE请求就是费简单请求

再比如发送的是 Content-Type:application/json也是非简单请求

简单请求的处理方案:

在响应头加一个Access-Control-Allow-Origin * --》 允许任何源给我发跨域请求

在响应头加一个Access-Control-Allow-Origin 127.0.0.1:8000 --》只允许 127.0.0.1:8000 给我发跨域请求

非简单请求:

浏览器会提前发一个 OPTIONS的预检请求

在响应头加一个Access-Control-Allow-Methods:‘PUT, DELETE’ --》允许浏览器给我发PUT和DELETE的跨域请求

在响应头加一个Access-Control-Allow-Headers: ‘Content-Type’ --》 允许浏览器给我发请求头中修改Content-Type字段

使用django-cors-headers包

pip install django-cors-headers

在中间件中注册

MIDDLEWARE = [
‘corsheaders.middleware.CorsMiddleware’, # 添加中间件
‘django.middleware.security.SecurityMiddleware’,
‘django.contrib.sessions.middleware.SessionMiddleware’,
‘django.middleware.common.CommonMiddleware’,
# ‘django.middleware.csrf.CsrfViewMiddleware’,
‘django.contrib.auth.middleware.AuthenticationMiddleware’,
‘django.contrib.messages.middleware.MessageMiddleware’,
‘django.middleware.clickjacking.XFrameOptionsMiddleware’,
]
在Django的settings.py中配置:

CORS_ORIGIN_ALLOW_ALL = True # 允许任何网站都来发跨域请求
1
配置可跨域访问的白名单:

CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
# ‘<YOUR_DOMAIN>[:PORT]’,
‘127.0.0.1:8080’
)

Django REST framework

1.安装:

pip install djangorestframework

2.使用:

注册app (不是必须)注册之后能够在页面的视图中看到
INSTALLED_APPS = [
#…
‘corsheaders’,
‘rest_framework’
]
常规的django操作
1创建超级用户

python manage.py createsuperuser
Username (leave blank to use ‘administrator’): root
Email address:直接回车表示不填写
Password:密码
Password (again):密码
Superuser created successfully.
2修改时区和后台显示语言

LANGUAGE_CODE = ‘en-us’

LANGUAGE_CODE = ‘zh-hans’

TIME_ZONE = ‘UTC’

TIME_ZONE = ‘Asia/Shanghai’
1
2
3.注册model到admin中 以便于后台管理
from django.contrib import admin
from myJsonApi import models

admin.site.register(models.Book)
admin.site.register(models.Author)
admin.site.register(models.Publisher)

导入APIView from rest_framewor.views import APIView, CBV继承它
1 自己写一个序列化的工具类 BookSerializer
from rest_framework import serializers
from myJsonApi import models

class AuthorSerializers(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=32)

class PublisherSerializers(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=32)

相当于django的form和ModelForm

class BookSerializers(serializers.Serializer):
# required=False指的是不是必填项(保存数据时数据库自动生成id的时候)
id = serializers.IntegerField(required=False)
# 对长度进行校验
title = serializers.CharField(max_length=32)
# 等号前面填写的就是数据库中写的字段名
pub_date = serializers.DateField()
# sourse="get_category_display"是拿到数据库中存的展示的值
# 例如 CHOICES为1代表的值时Python
# CHOICES = ((1, ‘Python’), (2, ‘Go’), (3, ‘Linux’))
category = serializers.CharField(source=“get_category_display”, read_only=True)
post_category = serializers.CharField(write_only=True)
# read_only=True是给前端发数据的时候用的
# 调用前面定义好的类来处理出版社,(外键)
publisher = PublisherSerializers(read_only=True)
post_publisher = serializers.IntegerField(write_only=True)
# many=True,代表的是可以展示多个
# 调用前面定义好的类来处理作者,(多对多字段)
author = AuthorSerializers(many=True, read_only=True)
# write_only = True是在后端收到前端数据的时候用的
# 意味着前端传值的时候关键字变为自己定义的post_author
# ListField可以传数组即多个值
post_author = serializers.ListField(write_only=True)
1.2 在视图中调用
from rest_framework.views import APIView
from rest_framework.response import Response
from myJsonApi.Serializers import BookSerializers

class BookList(APIView):
def get(self, request):
# 查询出数据
books = models.Book.objects.all()
# 进行序列化
books_json = BookSerializers(books, many=True)
# 返回json格式的数据
return Response(books_json.data)
post新增数据
在BookSerializers中
def create(self, validated_data):

validated_data是校验过的数据

book_obj = models.Book.objects.create(
title=validated_data.get(‘title’),
pub_date=validated_data[‘pub_date’],
category=validated_data[‘post_category’],
publisher_id=validated_data[‘post_publisher’], # 1
)
book_obj.authors.set(validated_data[‘post_authors’])
return book_obj
在视图中class BookList(APIView):
def post(self, request):

获取数据(因为APIView对request进行增强,将数据赋值到了request.data)

对数据进行有效性校验

ser_obj = BookSerializers(data=request.data)
if ser_obj.is_valid():

.save()# 调用的是BookSerializer类中的create方法,需要自己去实现

拿到序列化的数据去数据库创建新记录

ser_obj.save()
else:

校验失败则返回错误原因

return Response(ser_obj.errors)
return Response(“ok”)

对单本书的增删改查

在ModelSerializers中

“”"
专门用来做序列化的工具类
“”"

from rest_framework import serializers
from bms import models

class PublisherSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField()

class AuthorSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField()

class BookModelSerializer(serializers.ModelSerializer):
# SerializerMethodField 会自动去找 get_字段名 的方法执行
category_info = serializers.SerializerMethodField(read_only=True)
publisher_info = serializers.SerializerMethodField(read_only=True)
authors_info = serializers.SerializerMethodField(read_only=True)

def get_category_info(self, book_obj):
    # obj ==》 当前被序列化的那个书籍对象
    return book_obj.get_category_display()

def get_publisher_info(self, book_obj):
    # book_obj.pulisher  ==> 得到和我这本书关联的出版社对象

    # return {
    #     "id": book_obj.publiser.id,
    #     "name": book_obj.publiser.name
    # }
    # ser_obj = PublisherSerializer(book_obj.publisher)
    # return ser_obj.data
    return PublisherSerializer(book_obj.publisher).data

def get_authors_info(self, book_obj):
     # 这里的.all()和 many=True是指有多个作者的时候这样写
    return AuthorSerializer(book_obj.authors.all(), many=True).data

class Meta:
    model = models.Book
    fields = "__all__"
    # depth = 1  # 所有有关系的字段都变成 read_only
    # exclude = []  # 排除某个字段
    extra_kwargs = {  # 每个字段的一些额外参数
        'publisher': {'write_only': True},
        'authors': {'write_only': True},
        'category': {'write_only': True},
    }

在视图中使用BookModelSerializer

from 你的app.你的py文件写的名字 import BookModelSerializer

class BookDetailView(APIView):
“”“这是书籍详情相关的接口 支持:GET/PUT/DELETE”""
def get(self, request, pk):
“”“获取具体某本书的信息”""
# 1. 根据pk去查询具体的那本书籍对象
book_obj = models.Book.objects.filter(pk=pk).first()
if book_obj:
# 2. 将书籍对象 序列化成 json格式的数据
ser_obj = BookModelSerializer(book_obj)
# 3. 返回响应
return Response(ser_obj.data)
else:
return Response(“无效的书籍id”)

def put(self, request, pk):
    """修改具体某一本书"""
    # 1. 根据pk去查询具体的那本书籍对象
    book_obj = models.Book.objects.filter(pk=pk).first()
    if book_obj:
        # 2. 获取用户 发送过来的数据并且更新对象
        ser_obj = BookModelSerializer(instance=book_obj, data=request.data, partial=True)  # form组件中也有类似的实现
        if ser_obj.is_valid():
            # 3. 保存并返回修改后的数据
            ser_obj.save()
            return Response(ser_obj.data)
        else:
            return Response(ser_obj.errors)
    else:
        return Response("无效的书籍id")

def delete(self, request, pk):
    """删除具体某一本书"""
    # 1. 根据pk去查询具体的那本书籍对象
    book_obj = models.Book.objects.filter(pk=pk)
    if book_obj:
        # 删除书籍对象
        book_obj.delete()
        return Response("删除成功")
    else:
        return Response("无效的书籍id")
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值