Django使用AJAX調(diào)用自己寫的API接口

在這個(gè)例子中,我們將使用Django編寫?zhàn)I了么高校外賣商家查詢API接口笼痹,并且使用AJAX技術(shù)來實(shí)現(xiàn)API接口的使用蹭沛,包括使用ajax get方法加載更多數(shù)據(jù)排截,使用ajax方法來更新娱节、修改挠蛉、新增、刪除數(shù)據(jù)肄满。利用API可以做到前后端分離谴古,為開發(fā)web應(yīng)用提供了便利。

安裝rest framework

首先使用Pycharm新建一個(gè)Django項(xiàng)目稠歉,并且使用virtualenv或者pipenv虛擬環(huán)境

image

創(chuàng)建成功會(huì)自動(dòng)安裝Django2.1和所需依賴掰担,restframework框架需要自己手動(dòng)安裝

//激活虛擬環(huán)境安裝以下
(venv)$ pip install djangorestframework
(venv)$ pip install django-filter 
(venv)$ pip install pytest
(venv)$ pip install pytest-django 
//由于筆者使用Postgresql數(shù)據(jù)庫,所以還需要安裝以下
(venv)$ pip install psycopg2
//使用mysql數(shù)據(jù)庫安裝如下
(venv)$ pip install pymysql

準(zhǔn)備數(shù)據(jù)來提供服務(wù)

數(shù)據(jù)來源:餓了么爬蟲

數(shù)據(jù)內(nèi)容:全國(guó)所有大學(xué)附近的外賣商家Top20

數(shù)據(jù)需要導(dǎo)入數(shù)據(jù)庫

image

Django編寫rest api接口

項(xiàng)目結(jié)構(gòu)

image

小編最近整理了一套Python學(xué)習(xí)教程怒炸,有需要的小伙伴带饱,記得來小編的交流群:556370268,即可免費(fèi)領(lǐng)取一套Python學(xué)習(xí)教程哦

settings.py.

// 安裝的app如下
INSTALLED_APPS = [
 #...
 'rest_framework',
 'django_filters',
 'api.apps.ApiConfig',
 'front.apps.FrontConfig',
]
//restframework 配置如下
REST_FRAMEWORK = {
//這里配置了分頁處理阅羹,每頁最多20個(gè)項(xiàng)目
'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',
 ),
 //這里配置了用戶認(rèn)證捏鱼,管理員才可以更改內(nèi)容执庐,未登錄不能更改
 'DEFAULT_AUTHENTICATION_CLASSES':(
 'rest_framework.authentication.BasicAuthentication',
 'rest_framework.authentication.SessionAuthentication',
 ),
 //這里配置了訪問次數(shù)限制,過多會(huì)返回429錯(cuò)誤 too many requests
 'DEFAULT_THROTTLE_CLASSES': (
 'rest_framework.throttling.AnonRateThrottle',
 'rest_framework.throttling.UserRateThrottle',
 ),
 //這里配置了訪問次數(shù)导梆,anon代表匿名用戶轨淌,user代表已登錄用戶,entries是我自己設(shè)置的作用域看尼,300/hour代表最多300次每小時(shí)
 '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
//這里繼承自超鏈接模型序列器递鹉,用于把數(shù)據(jù)轉(zhuǎn)換為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
//這里是獲取所有數(shù)據(jù)藏斩,可實(shí)現(xiàn)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操作創(chuàng)建新的數(shù)據(jù)
 permission_classes = (
 permissions.IsAuthenticatedOrReadOnly,
 custompermission.IsCurrentUserOwnerOrReadOnly,
 )
 def perform_create(self, serializer):
 serializer.save(owner=self.request.user)

//這里是獲取具體某一項(xiàng)的數(shù)據(jù)灾茁,可實(shí)現(xiàn)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'))
] 

以下為啟動(dòng)界面

image
image

到此為止非常簡(jiǎn)單的api就寫完了禀挫,接下來就是自動(dòng)化測(cè)試是否達(dá)到預(yù)期效果旬陡。

如圖,測(cè)試通過语婴!

image

在程序中調(diào)用剛剛寫好的api

創(chuàng)建一個(gè)新的app并且添加到settings.py里面

(venv)$ python manage.py startapp front

做好的效果如下:點(diǎn)擊加載更多會(huì)觸發(fā)ajax

image
image

由于篇幅有限描孟,這里貼出js代碼

使用ajax get請(qǐng)求剛剛寫好的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>'
 )
 }
 }
 })
 });

可以修改具體的一條數(shù)據(jù),使用ajax patch方法提交數(shù)據(jù)砰左。

注:PUT方法是修改所有數(shù)據(jù)匿醒,而PATCH方法是修改局部數(shù)據(jù)

image

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();
 }
 }
 })
 })

本文通過一個(gè)小例子介紹了如何使用Django調(diào)用自己寫的api

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市缠导,隨后出現(xiàn)的幾起案子廉羔,更是在濱河造成了極大的恐慌,老刑警劉巖僻造,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憋他,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡髓削,警方通過查閱死者的電腦和手機(jī)竹挡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來立膛,“玉大人揪罕,你說我怎么就攤上這事”Ρ茫” “怎么了好啰?”我有些...
    開封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鲁猩。 經(jīng)常有香客問我坎怪,道長(zhǎng),這世上最難降的妖魔是什么廓握? 我笑而不...
    開封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任搅窿,我火速辦了婚禮,結(jié)果婚禮上隙券,老公的妹妹穿的比我還像新娘男应。我一直安慰自己,他們只是感情好娱仔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開白布沐飘。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪耐朴。 梳的紋絲不亂的頭發(fā)上借卧,一...
    開封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音筛峭,去河邊找鬼铐刘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛影晓,可吹牛的內(nèi)容都是我干的镰吵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼挂签,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼疤祭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起饵婆,我...
    開封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤勺馆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后啦辐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谓传,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜈项,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年芹关,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片紧卒。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡侥衬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出跑芳,到底是詐尸還是另有隱情轴总,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布博个,位于F島的核電站怀樟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盆佣。R本人自食惡果不足惜往堡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望共耍。 院中可真熱鬧虑灰,春花似錦、人聲如沸痹兜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至对湃,卻和暖如春崖叫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拍柒。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工归露, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人斤儿。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓剧包,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親往果。 傳聞我的和親對(duì)象是個(gè)殘疾皇子疆液,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容