Django使用AJAX調用本身寫的API接口

Django使用AJAX調用本身寫的API接口

在這裏插入圖片描述
***javascript

具體代碼和數據已上傳到github

https://github.com/PythonerKK/eleme-api-by-django-restful-framework
***java

在這個例子中,咱們將使用Django編寫餓了麼高校外賣商家查詢API接口,而且使用AJAX技術來實現API接口的使用,包括使用ajax get方法加載更多數據,使用ajax方法來更新、修改、新增、刪除數據。利用API能夠作到先後端分離,爲開發web應用提供了便利。python

安裝rest framework

首先使用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

Django編寫rest api接口

項目結構
在這裏插入圖片描述
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就寫完了,接下來就是自動化測試是否達到預期效果。
如圖,測試經過!
在這裏插入圖片描述

在程序中調用剛剛寫好的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

相關文章
相關標籤/搜索