美文网首页互联网科技Python之佳 程序员
Django使用AJAX调用自己写的API接口

Django使用AJAX调用自己写的API接口

作者: 派派森森 | 来源:发表于2019-03-05 20:27 被阅读10次

    在这个例子中,我们将使用Django编写饿了么高校外卖商家查询API接口,并且使用AJAX技术来实现API接口的使用,包括使用ajax get方法加载更多数据,使用ajax方法来更新、修改、新增、删除数据。利用API可以做到前后端分离,为开发web应用提供了便利。

    安装rest framework

    首先使用Pycharm新建一个Django项目,并且使用virtualenv或者pipenv虚拟环境

    image

    创建成功会自动安装Django2.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
    
    

    准备数据来提供服务

    数据来源:饿了么爬虫

    数据内容:全国所有大学附近的外卖商家Top20

    数据需要导入数据库

    image

    Django编写rest api接口

    项目结构

    image

    小编最近整理了一套Python学习教程,有需要的小伙伴,记得来小编的交流群:556370268,即可免费领取一套Python学习教程哦

    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'))
    ] 
    
    

    以下为启动界面

    image image

    到此为止非常简单的api就写完了,接下来就是自动化测试是否达到预期效果。

    如图,测试通过!

    image

    在程序中调用刚刚写好的api

    创建一个新的app并且添加到settings.py里面

    (venv)$ python manage.py startapp front
    
    

    做好的效果如下:点击加载更多会触发ajax

    image image

    由于篇幅有限,这里贴出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方法是修改局部数据

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

    本文通过一个小例子介绍了如何使用Django调用自己写的api

    相关文章

      网友评论

        本文标题:Django使用AJAX调用自己写的API接口

        本文链接:https://www.haomeiwen.com/subject/zicauqtx.html