用Python如何写一个接口呢,首先得要有数据,可以用我们在网站上爬的数据,在上一篇文章中写了如何用Python爬虫,有兴趣的可以看看:
 
大量的数据保存到数据库比较方便。我用的pymsql,pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同。但目前在python3.x中,PyMySQL取代了MySQLdb。
 

1.连接数据库

  1. # 连接数据库,需指定charset否则可能会报错
  2. db = pymysql.connect(host="localhost", user="root", password="123", db="mysql", charset="utf8mb4")
  3. cursor = db.cursor() # 创建一个游标对象

  

2.创建数据库

  1. cursor.execute("DROP TABLE IF EXISTS meizi_meizis") # 如果表存在则删除
  2. # 创建表sql语句
  3. createTab = """create table meizi_meizis(
  4. id int primary key auto_increment,
  5. mid varchar(10) not null,
  6. title varchar(50),
  7. picname varchar(10),
  8. page_url varchar(50),
  9. img_url varchar(50)
  10. );"""
  11. cursor.execute(createTab) # 执行创建数据表操作

  

3.爬取数据

  1. def html(self, href, title):
  2. lists = []
  3. meiziid = href.split('/')[-1]
  4. html = self.request(href)
  5. max_span = BeautifulSoup(html.text, 'lxml').find('div', class_='pagenavi').find_all('span')[-2].get_text()
  6. for page in range(1, int(max_span) + 1):
  7. meizi = {}
  8. page_url = href + '/' + str(page)
  9. img_html = self.request(page_url)
  10. img_url = BeautifulSoup(img_html.text, 'lxml').find('div', class_='main-image').find('img')['src']
  11. picname = img_url[-9:-4]
  12. meizi['meiziid'] = meiziid
  13. meizi['title'] = title
  14. meizi['picname'] = picname
  15. meizi['page_url'] = page_url
  16. meizi['img_url'] = img_url
  17. lists.append(meizi) # 保存到返回数组中
  18. return lists

  

4.保存到数据库

  1. def all_url(self, url):
  2. html = self.request(url)
  3. all_a = BeautifulSoup(html.text, 'lxml').find('div', class_='all').find_all('a')
  4. for index, a in enumerate(all_a):
  5. title = a.get_text()
  6. href = a['href']
  7. lists = self.html(href, title)
  8. for i in lists:
  9. # print(i['meiziid'], i['title'], i['picname'], i['page_url'], i['img_url'])
  10. # 插入数据到数据库sql语句,%s用作字符串占位
  11. sql = "INSERT INTO `meizi_meizis`(`mid`,`title`,`picname`,`page_url`,`img_url`) VALUES(%s,%s,%s,%s,%s)"
  12. try:
  13. cursor.execute(sql, (i['meiziid'], i['title'], i['picname'], i['page_url'], i['img_url']))
  14. db.commit()
  15. print(i[0] + " is success")
  16. except:
  17. db.rollback()
  18. db.close() # 关闭数据库

  

5.创建Web工程

运行我们的爬虫,很快数据库表里就有数据了。

然后开始写接口。我是通过Django+rest_framework来写的。

Django 是用Python开发的一个免费开源的Web框架,可以用于快速搭建高性能,优雅的网站。Django 中提供了开发网站经常用到的模块,常见的代码都为你写好了,减少重复的代码。
 

Django 目录结构

网址入口,关联到对应的views.py中的一个函数(或者generic类),访问网址就对应一个函数。
处理用户发出的请求,从urls.py中对应过来, 通过渲染templates中的网页可以将显示内容,比如登陆后的用户名,用户请求的数据,输出到网页。
与数据库操作相关,存入或读取数据时用到这个,当然用不到数据库的时候 你可以不使用。
表单,用户在浏览器上输入数据提交,对数据的验证工作以及输入框的生成等工作,当然你也可以不使用。
templates 文件夹
views.py 中的函数渲染templates中的Html模板,得到动态内容的网页,当然可以用缓存来提高速度。
后台,可以用很少量的代码就拥有一个强大的后台。
Django 的设置,配置文件,比如 DEBUG 的开关,静态文件的位置等。
 
 

Django 常用操作

1)新建一个 django project
django-admin.py startproject project_name
 
2)新建 app
python manage.py startapp app_name
一般一个项目有多个app, 当然通用的app也可以在多个项目中使用。
还得在工程目录的settings.py文件在配置
 
  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'rest_framework',
  9.  
  10. 'meizi',
  11. ]

  

在app/views.py下编写代码
  1. def index(request):
  2. return HttpResponse(u"你好")

  

在工程目录urls.py配置

  1. from learn import views as learn_views
  2. urlpatterns = [
  3. url(r'^$', learn_views.index),
  4. ]

通过python manage.py runserver启动,就会看到我们输出的“你好”了

 
3)创建数据库表 或 更改数据库表或字段
在app下的models.py创建表
 
  1. class Person(models.Model):
  2. name = models.CharField(max_length=30)
  3. age = models.IntegerField()
  4.  
  5. def __unicode__(self):
  6. # 在Python3中使用 def __str__(self):
  7. return self.name

运行命令,就可以生成对应的表

  1. Django 1.7.1及以上 用以下命令
  2. # 1. 创建更改的文件
  3. python manage.py makemigrations
  4. # 2. 将生成的py文件应用到数据库
  5. python manage.py migrate

在views.py文件里就可以获取数据库的数据

  1. def create(request):
  2. # 新建一个对象的方法有以下几种:
  3. Person.objects.create(name='xiaoli', age=18)
  4. # p = Person(name="WZ", age=23)
  5. # p = Person(name="TWZ")
  6. # p.age = 23
  7. # p.save()
  8. # 这种方法是防止重复很好的方法,但是速度要相对慢些,返回一个元组,第一个为Person对象,
  9. # 第二个为True或False, 新建时返回的是True, 已经存在时返回False
  10. # Person.objects.get_or_create(name="WZT", age=23)
  11. s = Person.objects.get(name='xiaoli')
  12. return HttpResponse(str(s))

  

6.写接口

接口使用rest_framework,rest_framework是一套基于Django 的 REST 框架,是一个强大灵活的构建 Web API 的工具包。

写接口三步完成:连接数据库、取数据、数据输出
 

1)连接数据库

在工程目录下的settings.py文件下配置
  1. DATABASES = {
  2. # 'default': {
  3. # 'ENGINE': 'django.db.backends.sqlite3',
  4. # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
  5. # }
  6. 'default': {
  7. 'ENGINE': 'django.db.backends.mysql',
  8. 'NAME': 'mysql',
  9. 'USER': 'root',
  10. 'HOST': '127.0.0.1',
  11. 'PASSWORD': '123',
  12. 'PORT': 3306,
  13. # show variables like 'character_set_database';
  14. # 修改字段字符编码
  15. # alter table spiders_weibo modify text longtext charset utf8mb4 collate utf8mb4_unicode_ci;
  16. 'OPTIONS': {'charset': 'utf8mb4'},
  17. }
  18. }

  

 

2)取数据

既然要取数据,那model肯定得和数据库的一致,我发现一个快捷的方式可以把数据库中的表生成对应的model,在项目目录下执行命令
  1. python manage.py inspectdb

可以看到下图

取我们表的model拷贝到app下的models.py里

  1. class Meizis(models.Model):
  2. mid = models.CharField(max_length=10)
  3. title = models.CharField(max_length=50, blank=True, null=True)
  4. picname = models.CharField(max_length=10, blank=True, null=True)
  5. page_url = models.CharField(max_length=50, blank=True, null=True)
  6. img_url = models.CharField(max_length=50, blank=True, null=True)
  7.  
  8. class Meta:
  9. managed = False
  10. db_table = 'meizi_meizis'

创建一个序列化Serializer类

提供序列化和反序列化的途径,使之可以转化为,某种表现形式如json。我们可以借助serializer来实现,类似于Django表单(form)的运作方式。在app目录下,创建文件serializers.py。
  1. class MeiziSerializer(serializers.ModelSerializer):
  2. # ModelSerializer和Django中ModelForm功能相似
  3. # Serializer和Django中Form功能相似
  4. class Meta:
  5. model = Meizis
  6. # 和"__all__"等价
  7. fields = ('mid', 'title', 'picname', 'page_url', 'img_url')

这样在views.py就可以来获取数据库的数据了

  1. meizis = Meizis.objects.all()
  2. serializer = MeiziSerializer(meizis, many=True)
  3. return Response(serializer.data)

  

3) 数据输出客户端或前端

 REST框架提供了两种编写API视图的封装。
  • @api_view装饰器,基于方法的视图。
  • 继承APIView类,基于类的视图。
 
request.data会自行处理输入的json请求
使用格式后缀明确的指向指定的格式,需要添加一个format关键字参数
http http://127.0.0.1:8000/getlist.json # JSON 后缀
http://127.0.0.1:8000/getlist.api # 可视化 API 后缀
http://127.0.0.1:8000/getlist/ code="print 123"post
  1. @api_view(['GET', 'POST'])
  2. def getlist(request, format=None):
  3. if request.method == 'GET':
  4. meizis = Meizis.objects.all()
  5. serializer = MeiziSerializer(meizis, many=True)
  6. return Response(serializer.data)
  7.  
  8. elif request.method == 'POST':
  9. serializer = MeiziSerializer(data=request.data)
  10. if serializer.is_valid():
  11. serializer.save()
  12. return Response(serializer.data, status=status.HTTP_201_CREATED)
  13. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

  

4)分页

最后别忘了在urls.py配置URL,通过浏览器就可以看到json数据了。

 当然app也是可以调用我们的接口的

还有个问题

我们的数据有好几千条,一块返回来很不合理,所以需要分页,当然rest_framework框架提供了这个功能,post请求不支持,需要自己查数据库或者切片来进行返回。来看看rest_framework是如何来分页的。在models.py里创建一个类
 
  1. class StandardResultSetPagination(LimitOffsetPagination):
  2. # 默认每页显示的条数
  3. default_limit = 20
  4. # url 中传入的显示数据条数的参数
  5. limit_query_param = 'limit'
  6. # url中传入的数据位置的参数
  7. offset_query_param = 'offset'
  8. # 最大每页显示条数
  9. max_limit = None

  

在serializers.py创建俩个类,为什么是俩个?因为我们有俩个接口,一个明细,一个列表,而列表是不需要把字段的所有数据都返回的

  1. class ListSerialize(serializers.ModelSerializer):
  2. class Meta:
  3. model = Meizis
  4. fields = ('mid', 'title')
  5.  
  6. class ListPicSerialize(serializers.ModelSerializer):
  7. class Meta:
  8. model = Meizis
  9. fields = "__all__"

  

在views.py里编写
  1. @api_view(['GET'])
  2. def getlist(request, format=None):
  3. if request.method == 'GET':
  4. meizis = Meizis.objects.values('mid','title').distinct()
  5. # http: // 127.0.0.1:8000 / getlist?limit = 20
  6. # http: // 127.0.0.1:8000 / getlist?limit = 20 & offset = 20
  7. # http: // 127.0.0.1:8000 / getlist?limit = 20 & offset = 40
  8. # 根据url参数 获取分页数据
  9. obj = StandardResultSetPagination()
  10. page_list = obj.paginate_queryset(meizis, request)
  11. # 对数据序列化 普通序列化 显示的只是数据
  12. ser = ListSerialize(instance=page_list, many=True) # 多个many=True # instance:把对象序列化
  13. response = obj.get_paginated_response(ser.data)
  14. return response
  15.  
  16. @api_view(['GET', 'POST'])
  17. def getlispic(request, format=None):
  18. if request.method == 'GET':
  19. mid = request.GET['mid']
  20. if mid is not None:
  21. # get是用来获取一个对象的,如果需要获取满足条件的一些数据,就要用到filter
  22. meizis = Meizis.objects.filter(mid=mid)
  23. obj = StandardResultSetPagination()
  24. page_list = obj.paginate_queryset(meizis, request)
  25. ser = ListPicSerialize(instance=page_list, many=True)
  26. response = obj.get_paginated_response(ser.data)
  27. return response
  28. else:
  29. return Response(str('请传mid'))

  

到这里就完成了接口的编写,都是对框架的简单使用,希望对大家有帮助。
 
 
GitHub地址,欢迎star
 
 

Python用Django写restful api接口的更多相关文章

  1. python 全栈开发,Day95(RESTful API介绍,基于Django实现RESTful API,DRF 序列化)

    昨日内容回顾 1. rest framework serializer(序列化)的简单使用 QuerySet([ obj, obj, obj]) --> JSON格式数据 0. 安装和导入: p ...

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

    Django使用AJAX调用自己写的API接口 *** 具体代码和数据已上传到github https://github.com/PythonerKK/eleme-api-by-django-rest ...

  3. Django编写RESTful API(一):序列化

    欢迎访问我的个人网站:www.comingnext.cn 关于RESTful API 现在,在开发的过程中,我们经常会听到前后端分离这个技术名词,顾名思义,就是前台的开发和后台的开发分离开.这个技术方 ...

  4. Django编写RESTful API(四):认证和权限

    欢迎访问我的个人网站:www.comingnext.cn 前言: 按照前面几篇文章里那样做,使用Django编写RESTful API的基本功能已经像模像样了.我们可以通过不同的URL访问到不同的资源 ...

  5. SpringMVC Restful api接口实现

    [前言] 面向资源的 Restful 风格的 api 接口本着简洁,资源,便于扩展,便于理解等等各项优势,在如今的系统服务中越来越受欢迎. .net平台有WebAPi项目是专门用来实现Restful ...

  6. 使用Flask设计带认证token的RESTful API接口

    大数据时代 Just a record. 使用Flask设计带认证token的RESTful API接口[翻译] 上一篇文章, 使用python的Flask实现一个RESTful API服务器端  简 ...

  7. Java 调用Restful API接口的几种方式--HTTPS

    摘要:最近有一个需求,为客户提供一些Restful API 接口,QA使用postman进行测试,但是postman的测试接口与java调用的相似但并不相同,于是想自己写一个程序去测试Restful ...

  8. Spring Boot入门系列(二十)快速打造Restful API 接口

    spring boot入门系列文章已经写到第二十篇,前面我们讲了spring boot的基础入门的内容,也介绍了spring boot 整合mybatis,整合redis.整合Thymeleaf 模板 ...

  9. 用 shell 脚本做 restful api 接口监控

    问题的提出 基于历史原因,公司有一个"三无"采集服务--无人员.无运维.无监控--有能力做的部门不想接.接了的部门没能力.于是就一直这样裸奔,直到前几天一个依赖于这个采集服务的大数 ...

随机推荐

  1. 磁盘上没有足够的空间完成此操作的解决办法_Windows小知识

    前言: 我们有时候调整系统分区时会遇到"磁盘上没有足够的空间完成此操作"的情况导致我们的分区无法完成,然而我们的磁盘上明明有未分配的空间,为什么不能创建磁盘分区呢?本文将介绍通过把 ...

  2. 聊聊Spring Cloud版本的那些事儿

    说说Spring Cloud版本的那些事儿. 版本命名 之前提到过,Spring Cloud是一个拥有诸多子项目的大型综合项目,原则上其子项目也都维护着自己的发布版本号.那么每一个Spring Clo ...

  3. linux或Mac中./与/

      mac终端命令和linux中命令是一致的,在执行可执行xxx.sh文件时,需要进入xxx.sh文件所在的目录,然后输入./xxx.sh才可以执行成功 1.为什么需要添加./   因为linux/u ...

  4. angularJS---自定义过滤器

    AngularJS另一个特点就是提供了过滤器,可以通过操作UNIX下管道的方式,操作数据结果. 通过使用管道,可以便于双向的数据绑定中视图的展现. 过滤器在处理过程中,将数据变成新的格式,而且可以使用 ...

  5. 6.app架构基础

    app架构,一个听起来高大尚的名字,很多小伙伴听到这个词语感觉很迷茫,不知道架构具体说的是啥?在q群里,"app后端应该怎么架构"这个问题被问了无数次.通过阅读本文,根据本人提出的 ...

  6. 跟我学ASP.NET MVC之五:SportsStrore开始

    摘要: 这篇文章将介绍一个ASP.NET应用程序SportsStore的开发过程. 开始 创建解决方案 创建工程 在New ASP.NET Project - SportsStore窗口中,选择Emp ...

  7. 【源码】otter工程结构

    最近在搞数据同步相关的内容,需要对otter的代码进行扩展,所以需要先熟悉一下otter的源码.首先我们整体来看下otter的工程结构.otter的工程结构比较复杂,需要花费一定的时间来理解各个部分的 ...

  8. BZOJ_3687_简单题_bitset

    BZOJ_3687_简单题_bitset Description 小呆开始研究集合论了,他提出了关于一个数集四个问题: 1.子集的异或和的算术和. 2.子集的异或和的异或和. 3.子集的算术和的算术和 ...

  9. [USACO11JAN]大陆议会The Continental Cowngress_2-sat

    [USACO11JAN]大陆议会The Continental Cowngress_2-sat 题意: 由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会. 议会以“每头 ...

  10. BZOJ_3697_采药人的路径_点分治

    BZOJ_3697_采药人的路径_点分治 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性 ...