在这个例子中,我们将使用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.
$('#edit-confirm-btn').click(function () { var name = $('#name').val(); var distance = $('#distance').val(); var adderss = $('#address').val(); var time = $('#time').val(); var score = $('#score').val(); var comments = $('#comments').val(); var sell = $('#sell').val(); var pk = $('#pk').val(); $.ajax({ type:'PATCH', url:'/detail/' + pk, data:{ "name": name, "distance": distance, "address": adderss, "time": time, "score": score, "comments": comments, "sell": sell, }, success:function (data) { if (data.status == 'ok'){ console.log('success'); location.reload(); } } }) })
本文通过一个小例子介绍了如何使用Django调用自己写的api
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]