***javascript
https://github.com/PythonerKK/eleme-api-by-django-restful-framework
***java
在這個例子中,咱們將使用Django編寫餓了麼高校外賣商家查詢API接口,而且使用AJAX技術來實現API接口的使用,包括使用ajax get方法加載更多數據,使用ajax方法來更新、修改、新增、刪除數據。利用API能夠作到先後端分離,爲開發web應用提供了便利。python
首先使用Pycharm新建一個Django項目,而且使用virtualenv或者pipenv虛擬環境
建立成功會自動安裝Django2.1和所需依賴,restframework框架須要本身手動安裝mysql
//激活虛擬環境安裝如下 (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
數據須要導入數據庫
git
項目結構
settings.py
.github
// 安裝的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
.web
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
.ajax
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
.sql
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就寫完了,接下來就是自動化測試是否達到預期效果。
如圖,測試經過!
建立一個新的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'] +'">' + 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