Django结合AJAX实现前后端分离的API接口开发与调用
本文详细讲解如何利用Django和Django REST Framework构建外卖商家查询API,并通过AJAX技术在前端实现数据的加载、更新、修改、新增及删除操作。内容涵盖环境配置、模型序列化、视图编写及前端JS交互,展示完整的前后端分离开发流程。
Django结合AJAX实现前后端分离的API接口开发与调用
本示例旨在演示如何使用Django编写饿了么高校外卖商家查询API接口,并借助AJAX技术实现接口的实际调用。功能涵盖利用AJAX GET方法加载更多数据,以及通过AJAX方法执行数据的更新、修改、新增和删除操作。通过API实现前后端分离,为Web应用开发提供了极大的便利。
安装REST Framework
安装REST Framework
首先,在PyCharm中新建一个Django项目,并建议使用virtualenv或pipenv创建虚拟环境。

项目创建成功后,会自动安装Django 2.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
准备用于提供服务的数据
准备用于提供服务的数据
数据来源:通过爬虫获取的饿了么数据。
数据内容:全国各大学附近的外卖商家Top 20信息。
需将数据导入数据库以提供服务。

使用Django编写REST API接口
使用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
在程序中调用刚才编写的API
创建一个新的app,并将其添加到settings.py配置中。
(venv)$ python manage.py startapp front
最终效果如下:点击“加载更多”按钮会触发AJAX请求。


由于篇幅限制,这里展示JavaScript代码:使用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。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









