Django restframework安装:
pip install djangorestframework
将django restframework注册到项目中:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'api.apps.ApiConfig',
]
在原生django中我们通过不能路由实现增删改查,例如这样:
http://127.0.0.1:8000/info/get/
http://127.0.0.1:8000/info/add/
http://127.0.0.1:8000/info/update/
http://127.0.0.1:8000/info/delete/
然后在views中定义不同的视图函数来处理请求。而Django restframework只需要一条路由,通过不同的请求方法实现前后端分离,主要的方法为:
http://127.0.0.1:8000/info/
get,获取数据
post,添加
put,更新
delete,删除
在原生django中我们可以通过CBV模式实现类似的功能,事实上django restframework的类视图正是基于django进行的开发,定制,所以可以看到很多地方它们是相似的。
urls.py
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^drf/info/', views.DrfInfoView.as_view()),
]
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
class DrfInfoView(APIView):
def get(self,request,*args,**kwargs):
data = [
{'id': 1, 'title': '震惊了...王阳居然...', 'content': '...'},
{'id': 2, 'title': '震惊了...王阳居然...', 'content': '...'},
{'id': 3, 'title': '震惊了...王阳居然...', 'content': '...'},
{'id': 4, 'title': '震惊了...王阳居然...', 'content': '...'},
]
return Response(data)
models.py
from django.db import models
# Create your models here.
class Category(models.Model):
"""
文章分类
"""
name = models.CharField(verbose_name='分类',max_length=32)
class Article(models.Model):
"""
文章表
"""
status_choices = (
(1, '发表'),
(2, '删除'),
)
status = models.IntegerField(verbose_name='状态', choices=status_choices, default=1)
title = models.CharField(verbose_name='标题',max_length=32)
summary = models.CharField(verbose_name='简介',max_length=255)
content = models.TextField(verbose_name='文章内容')
category = models.ForeignKey(verbose_name='分类',to='Category')
tag = models.ManyToManyField(verbose_name='标签', to='Tag', null=True, blank=True)
class Tag(models.Model):
"""标签"""
title = models.CharField(verbose_name='标签',max_length=32)
django restframework发送的均为json格式数据,所拟需要对数据进行处理,这里用到了django内置的model_to_dict()方法
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^drf/category/$', views.DrfCategoryView.as_view()),
url(r'^drf/category/(?P<pk>\d+)/$', views.DrfCategoryView.as_view()),
]
from api import models
from django.forms.models import model_to_dict
class DrfCategoryView(APIView):
def get(self,request,*args,**kwargs):
"""获取所有文章分类/单个文章分类"""
pk = kwargs.get('pk')
if not pk:
queryset = models.Category.objects.all().values('id','name')
data_list = list(queryset)
return Response(data_list)
else:
category_object = models.Category.objects.filter(id=pk).first()
data = model_to_dict(category_object)
return Response(data)
def post(self,request,*args,**kwargs):
"""增加一条分类信息"""
models.Category.objects.create(**request.data)
return Response('成功')
事实上,序列化的事情django restframework已经帮我们做好了,只需要引入并使用即可
我们写一个serializer.py文件
可以看到其中category是article的外键,这里为了查到category并显示其对应的中文名,我们用到了
category = serializers.CharField(source='category.name')
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
# fields = ['pk', 'title']
fields = '__all__'
class ArticleSerializer(serializers.ModelSerializer):
# 指定外键显示的字段来源
category = serializers.CharField(source='category.name')
tag = TagSerializer(many=True)
class Meta:
model = Article
fields = "__all__"
另一种显示外键 字段的方法是:
class ArticleSerializer(serializers.ModelSerializer):
category = serializers.SerializerMethodField()
class Meta:
model = Article
fields = "__all__"
def get_category(self, obj):
return obj.category.name
这里的get_category是固定写法,get_fieldname.同样的道理,对于choiceField,也有类似的处理:
status = serializers.CharField(source='get_status_display')
def get_status(self,obj):
return obj.get_status_display()
注意两者的写法区别,前者不加括号(django restframework会自动处理),后者是要加括号的,
我们看看在使用serizlizer之后的写法:
class DrfCategoryView(APIView):
def get(self, request, *args, **kwargs):
# 查
id = kwargs.get('id')
if id:
category_obj = Category.objects.filter(id=id).first()
ser = CategorySerializer(instance=category_obj, many=False)
return Response(ser.data)
category_objs = Category.objects.all()
ser = CategorySerializer(instance=category_objs, many=True)
return Response(ser.data)
def post(self, request, *args, **kwargs):
# 增加
ser = CategorySerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)
def put(self, request, *args, **kwargs):
id = kwargs.get('id')
category_obj = Category.objects.filter(id=id).first()
ser = CategorySerializer(instance=category_obj, many=True)
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)
def delete(self, request, *args, **kwargs):
id = kwargs.get('id')
category_obj = Category.objects.filter(id=id).first()
category_obj.delete()
return Response('delete finish')
可以看到serializer类似于原生django中的form,也能对数据进行校验。当有多条数据时,需要添加many=True,默认情况下为False,序列化后的数据被保存在data这个属性中,类似于cleaned_data.
补充:局部更新数据,比如只更新某个字段,而其它字段的值都没有更新时,在django中是可以指定update_fields=['name',],在rest framework中则有两点要注意:一是使用patch方法,二是加partial=True
def patch(self, request, *args, **kwargs):
pk = kwargs.get('pk')
article_obj = Article.objects.filter(id=pk).first()
ser = serializer.ArticleSerializer(instance=article_obj, data=request.data, partial=True)
if ser.is_valid():
ser.save()
return Response(ser.data)
return Response(ser.errors)