djangoapi接口开发
Django使用AJAX调用自己写的API接口的方法在这个例子中,我们将使用django编写饿了么高校外卖商家查询api接口,并且使用ajax技术来实现api接口的使用,包括使用ajax get方法加载更多数据,使用ajax方法来更新、修改、新增、删除数据。利用api可以做到前后端分离,为开发web应用提供了便利。
安装rest framework
首先使用pycharm新建一个django项目,并且使用virtualenv或者pipenv虚拟环境
创建成功会自动安装django2.1和所需依赖,restframework框架需要自己手动安装
|
/ / 激活虚拟环境安装以下 (venv)$ pip install djangorestframework (venv)$ pip install django - filter (venv)$ pip install pytest (venv)$ pip install pytest - django / / 由于笔者使用postgresql数据库,所以还需要安装以下 (venv)$ pip install psycopg2 / / 使用mysql数据库安装如下 (venv)$ pip install pymysql |
准备数据来提供服务
数据来源:饿了么爬虫
数据内容:全国所有大学附近的外卖商家top20
数据需要导入数据库
django编写rest api接口
项目结构
settings.py.
|
/ / 安装的app如下 installed_apps = [ #... 'rest_framework' , 'django_filters' , 'api.apps.apiconfig' , 'front.apps.frontconfig' , ] / / restframework 配置如下 rest_framework = { / / 这里配置了分页处理,每页最多 20 个项目 'default_pagination_class' : 'api.custompagination.limitoffsetpaginationwithupperbound' , 'page_size' : 20 , 'default_filter_backends' : ( / / 这里配置了排序、过滤、搜索器 'django_filters.rest_framework.djangofilterbackend' , 'rest_framework.filters.orderingfilter' , 'rest_framework.filters.searchfilter' , ), / / 这里配置了用户认证,管理员才可以更改内容,未登录不能更改 'default_authentication_classes' :( 'rest_framework.authentication.basicauthentication' , 'rest_framework.authentication.sessionauthentication' , ), / / 这里配置了访问次数限制,过多会返回 429 错误 too many requests 'default_throttle_classes' : ( 'rest_framework.throttling.anonratethrottle' , 'rest_framework.throttling.userratethrottle' , ), / / 这里配置了访问次数,anon代表匿名用户,user代表已登录用户,entries是我自己设置的作用域, 300 / hour代表最多 300 次每小时 'default_throttle_rates' : { 'anon' : '300/hour' , 'user' : '100/hour' , 'entries' : '200/hour' , }, 'default_versioning_class' : 'rest_framework.versioning.namespaceversioning' , } |
models.py.
|
from django.db import models class entry(models.model): city = models.charfield(max_length = 50 ) school = models.charfield(max_length = 100 ) link = models.charfield(max_length = 100 ,null = true,default = 'null' ) name = models.charfield(max_length = 200 ) lat = models.charfield(max_length = 20 ,null = true,default = '0.0' ) lng = models.charfield(max_length = 20 ,null = true,default = '0.0' ) address = models.charfield(max_length = 200 ,null = true,default = 'null' ) distance = models.charfield(max_length = 20 ,null = true,default = '0' ) time = models.charfield(max_length = 20 ,null = true,default = '0:00' ) contact = models.charfield(max_length = 200 ,null = true,default = 'null' ) score = models.charfield(max_length = 10 ,null = true,default = '0' ) comments = models.charfield(max_length = 20 ,null = true,default = '0' ) sell = models.charfield(max_length = 20 ,null = true,default = '0' ) image = models.charfield(max_length = 200 ,null = true,default = 'null' ) owner = models.foreignkey( 'auth.user' ,related_name = 'entries' ,on_delete = models.cascade) # class meta: # ordering = ('name',) def __str__( self ): return self .name |
serializers.py.
|
from rest_framework import serializers from api.models import entry / / 这里继承自超链接模型序列器,用于把数据转换为json格式,并且显示链接 class entryserializer(serializers.hyperlinkedmodelserializer): owner = serializers.readonlyfield(source = 'owner.username' ) class meta: model = entry fields = ( 'url' , 'pk' , 'name' , 'city' , 'school' , 'link' , 'lat' , 'lng' , 'address' , 'distance' , 'time' , 'contact' , 'score' , 'comments' , 'sell' , 'image' , 'owner' ) |
views.py.
|
from rest_framework import generics from rest_framework.response import response from rest_framework.reverse import reverse from api.models import entry from api.serializers import entryserializer from rest_framework import permissions from rest_framework.permissions import isauthenticated from rest_framework.throttling import scopedratethrottle from api import custompermission / / 这里是获取所有数据,可实现http get、post、option操作 class entrylist(generics.listcreateapiview): / / 限流自定义作用域 throttle_scope = 'entries' throttle_classes = (scopedratethrottle,) queryset = entry.objects. all () serializer_class = entryserializer name = 'entry-list' filter_fields = ( 'city' , 'school' , 'name' ) search_fields = ( 'school' , 'city' ) ordering_fields = ( 'city' ) / / 管理员才能post操作创建新的数据 permission_classes = ( permissions.isauthenticatedorreadonly, custompermission.iscurrentuserownerorreadonly, ) def perform_create( self , serializer): serializer.save(owner = self .request.user) / / 这里是获取具体某一项的数据,可实现http get、put、patch、option操作 class entrydetail(generics.retrieveupdatedestroyapiview): throttle_scope = 'entries' throttle_classes = (scopedratethrottle,) queryset = entry.objects. all () serializer_class = entryserializer name = 'entry-detail' permission_classes = ( permissions.isauthenticatedorreadonly, custompermission.iscurrentuserownerorreadonly, ) / / api根目录 class apiroot(generics.genericapiview): name = 'api-root' def get( self , request, * args, * * kwargs): return response({ 'entries' : reverse(entrylist.name, request = request), }) |
urls.py.
|
from django.urls import path from api import views urlpatterns = [ path( 'entries/' , views.entrylist.as_view(), name = views.entrylist.name), path( 'entry-detail/<int:pk>' , views.entrydetail.as_view(), name = views.entrydetail.name), path('', views.apiroot.as_view(), name = views.apiroot.name) ] |
ele/urls.py.
|
from django.urls import path,include urlpatterns = [ path( 'v1/' ,include( 'api.urls' )), path( 'v1/api-auth/' ,include( 'rest_framework.urls' )), path(' ',include(' front.urls')) ] |
以下为启动界面
到此为止非常简单的api就写完了,接下来就是自动化测试是否达到预期效果。 如图,测试通过!
在程序中调用刚刚写好的api
创建一个新的app并且添加到settings.py里面
|
(venv)$ python manage.py startapp front |
做好的效果如下:点击加载更多会触发ajax
由于篇幅有限,这里贴出js代码 使用ajax get请求刚刚写好的api接口并且添加到表格中
myjs.js.
|
$( '#load-more' ).click(function () { $.ajax({ method: 'get' , url:api_url, datatype: 'json' , success:function (data) { api_url = data[ 'next' ]; if (api_url = = null){ $( '#load-more' ).val( '已加载全部' ); $( '#load-more' ).attr( 'disabled' ,true); / / api_url这里就是刚刚写好的api接口 api_url = 'v1/entries/' ; } var results = data[ 'results' ]; for (i = 0 ;i<results.length;i + + ){ $( '#ele-table-body' ).append( ' <tr>\n' + ' <th scope="col">' + results[i][ 'pk' ] + '</th>\n' + ' <th scope="col">' + results[i][ 'city' ] + '</th>\n' + ' <th scope="col"><a href="/detail/' + results[i][ 'pk' ] + '" rel="external nofollow" >' + results[i][ 'name' ] + '</a></th>\n' + ' <th scope="col">' + results[i][ 'school' ] + '</th>\n' + ' <th scope="col">' + results[i][ 'score' ] + '</th>\n' + ' </tr>' ) } } }) }); |
可以修改具体的一条数据,使用ajax patch方法提交数据。 注:put方法是修改所有数据,而patch方法是修改局部数据
myjs.js.