Django使用AJAX調(diào)用自己寫的API接口的方法
在這個(gè)例子中,我們將使用Django編寫?zhàn)I了么高校外賣商家查詢API接口,并且使用AJAX技術(shù)來(lái)實(shí)現(xiàn)API接口的使用,包括使用ajax get方法加載更多數(shù)據(jù),使用ajax方法來(lái)更新、修改、新增、刪除數(shù)據(jù)。利用API可以做到前后端分離,為開發(fā)web應(yīng)用提供了便利。
安裝rest framework
首先使用Pycharm新建一個(gè)Django項(xiàng)目,并且使用virtualenv或者pipenv虛擬環(huán)境
創(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ù)庫(kù),所以還需要安裝以下 (venv)$ pip install psycopg2 //使用mysql數(shù)據(jù)庫(kù)安裝如下 (venv)$ pip install pymysql
準(zhǔn)備數(shù)據(jù)來(lái)提供服務(wù)
數(shù)據(jù)來(lái)源:餓了么爬蟲
數(shù)據(jù)內(nèi)容:全國(guó)所有大學(xué)附近的外賣商家Top20
數(shù)據(jù)需要導(dǎo)入數(shù)據(jù)庫(kù)
Django編寫rest api接口
項(xiàng)目結(jié)構(gòu)
settings.py.
// 安裝的app如下 INSTALLED_APPS = [ #... 'rest_framework', 'django_filters', 'api.apps.ApiConfig', 'front.apps.FrontConfig', ] //restframework 配置如下 REST_FRAMEWORK = { //這里配置了分頁(yè)處理,每頁(yè)最多20個(gè)項(xiàng)目 'DEFAULT_PAGINATION_CLASS':'api.custompagination.LimitOffsetPaginationWithUpperBound', 'PAGE_SIZE': 20, 'DEFAULT_FILTER_BACKENDS': ( //這里配置了排序、過(guò)濾、搜索器 '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', ), //這里配置了訪問(wèn)次數(shù)限制,過(guò)多會(huì)返回429錯(cuò)誤 too many requests 'DEFAULT_THROTTLE_CLASSES': ( 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle', ), //這里配置了訪問(wèn)次數(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)界面
到此為止非常簡(jiǎn)單的api就寫完了,接下來(lái)就是自動(dòng)化測(cè)試是否達(dá)到預(yù)期效果。 如圖,測(cè)試通過(guò)!
在程序中調(diào)用剛剛寫好的api
創(chuàng)建一個(gè)新的app并且添加到settings.py里面
(venv)$ python manage.py startapp front
做好的效果如下:點(diǎn)擊加載更多會(huì)觸發(fā)ajax
由于篇幅有限,這里貼出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'] +'" 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>' ) } } }) });
可以修改具體的一條數(shù)據(jù),使用ajax patch方法提交數(shù)據(jù)。 注:PUT方法是修改所有數(shù)據(jù),而PATCH方法是修改局部數(shù)據(jù)
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(); } } }) })
本文通過(guò)一個(gè)小例子介紹了如何使用Django調(diào)用自己寫的api
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Django 使用Ajax進(jìn)行前后臺(tái)交互的示例講解
- Django中使用jquery的ajax進(jìn)行數(shù)據(jù)交互的實(shí)例代碼
- 使用Python的Django框架結(jié)合jQuery實(shí)現(xiàn)AJAX購(gòu)物車頁(yè)面
- django使用ajax post數(shù)據(jù)出現(xiàn)403錯(cuò)誤如何解決
- django中使用jquery ajax post數(shù)據(jù)出現(xiàn)403錯(cuò)誤的解決辦法(兩種方法)
- Django框架如何使用ajax的post方法
- Django環(huán)境下使用Ajax的操作代碼
相關(guān)文章
python多線程+代理池爬取天天基金網(wǎng)、股票數(shù)據(jù)過(guò)程解析
這篇文章主要介紹了python多線程+代理池爬取天天基金網(wǎng)、股票數(shù)據(jù)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Python虛擬環(huán)境遷移的實(shí)現(xiàn)
本文主要介紹了Python虛擬環(huán)境遷移的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03詳解Ubuntu環(huán)境下部署Django+uwsgi+nginx總結(jié)
這篇文章主要介紹了Ubuntu環(huán)境下部署Django+uwsgi+nginx總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04解決python xx.py文件點(diǎn)擊完之后一閃而過(guò)的問(wèn)題
今天小編就為大家分享一篇解決python xx.py文件點(diǎn)擊完之后一閃而過(guò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06Python通過(guò)Pillow實(shí)現(xiàn)圖片對(duì)比
這篇文章主要介紹了Python Pillow實(shí)現(xiàn)圖片對(duì)比,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04Python OpenCV讀取png圖像轉(zhuǎn)成jpg圖像存儲(chǔ)的方法
今天小編就為大家分享一篇Python OpenCV讀取png圖像轉(zhuǎn)成jpg圖像存儲(chǔ)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10一文掌握python中的__init__的意思及使用場(chǎng)景分析
__init__是構(gòu)造方法,誰(shuí)調(diào)用,表示誰(shuí)(更直觀的理解就是類的方法中,誰(shuí)調(diào)用,表示誰(shuí),見(jiàn)下面第一個(gè)代碼)!!并不是必選項(xiàng),也就是說(shuō)在類中,這個(gè)不是必須用的,那什么場(chǎng)景需要用到,什么場(chǎng)景不需要用到呢,感興趣的朋友跟隨小編一起看看吧2023-02-02Python利用Turtle繪制哆啦A夢(mèng)和小豬佩奇
turtle庫(kù)是python的基礎(chǔ)繪圖庫(kù),經(jīng)常被用來(lái)介紹編程知識(shí)的方法庫(kù),是標(biāo)準(zhǔn)庫(kù)之一,利用turtle可以制作很多復(fù)雜的繪圖。本文將為大家介紹通過(guò)turtle庫(kù)繪制制哆啦A夢(mèng)和小豬佩奇,感興趣的小伙伴可以學(xué)習(xí)一下2022-04-04