溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python利用Django寫restful api接口的示例

發(fā)布時(shí)間:2021-02-08 10:54:40 來(lái)源:億速云 閱讀:1333 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)Python利用Django寫restful api接口的示例的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來(lái)看看吧。

前言

用Python如何寫一個(gè)接口呢,首先得要有數(shù)據(jù),可以用我們?cè)诰W(wǎng)站上爬的數(shù)據(jù)。

大量的數(shù)據(jù)保存到數(shù)據(jù)庫(kù)比較方便。我用的pymsql,pymsql是Python中操作MySQL的模塊,其使用方法和MySQLdb幾乎相同。但目前在python3.x中,PyMySQL取代了MySQLdb。

1.連接數(shù)據(jù)庫(kù)

# 連接數(shù)據(jù)庫(kù),需指定charset否則可能會(huì)報(bào)錯(cuò)
db = pymysql.connect(host="localhost", user="root", password="123", db="mysql", charset="utf8mb4")
cursor = db.cursor() # 創(chuàng)建一個(gè)游標(biāo)對(duì)象

2.創(chuàng)建數(shù)據(jù)庫(kù)

cursor.execute("DROP TABLE IF EXISTS meizi_meizis") # 如果表存在則刪除
 # 創(chuàng)建表sql語(yǔ)句
 createTab = """create table meizi_meizis(
 id int primary key auto_increment,
 mid varchar(10) not null,
 title varchar(50),
 picname varchar(10),
 page_url varchar(50),
 img_url varchar(50)
 );"""
 cursor.execute(createTab) # 執(zhí)行創(chuàng)建數(shù)據(jù)表操作

3.爬取數(shù)據(jù)

def html(self, href, title):
 lists = []
 meiziid = href.split('/')[-1]
 html = self.request(href)
 max_span = BeautifulSoup(html.text, 'lxml').find('div', class_='pagenavi').find_all('span')[-2].get_text()
 for page in range(1, int(max_span) + 1):
 meizi = {}
 page_url = href + '/' + str(page)
 img_html = self.request(page_url)
 img_url = BeautifulSoup(img_html.text, 'lxml').find('div', class_='main-image').find('img')['src']
 picname = img_url[-9:-4]
 meizi['meiziid'] = meiziid
 meizi['title'] = title
 meizi['picname'] = picname
 meizi['page_url'] = page_url
 meizi['img_url'] = img_url
 lists.append(meizi) # 保存到返回?cái)?shù)組中
 return lists

4.保存到數(shù)據(jù)庫(kù)

def all_url(self, url):
 html = self.request(url)
 all_a = BeautifulSoup(html.text, 'lxml').find('div', class_='all').find_all('a')
 for index, a in enumerate(all_a):
 title = a.get_text()
 href = a['href']
 lists = self.html(href, title)
 for i in lists:
 # print(i['meiziid'], i['title'], i['picname'], i['page_url'], i['img_url'])
 # 插入數(shù)據(jù)到數(shù)據(jù)庫(kù)sql語(yǔ)句,%s用作字符串占位
 sql = "INSERT INTO `meizi_meizis`(`mid`,`title`,`picname`,`page_url`,`img_url`) VALUES(%s,%s,%s,%s,%s)"
 try:
  cursor.execute(sql, (i['meiziid'], i['title'], i['picname'], i['page_url'], i['img_url']))
  db.commit()
  print(i[0] + " is success")
 except:
  db.rollback()
 db.close() # 關(guān)閉數(shù)據(jù)庫(kù)

5.創(chuàng)建Web工程

運(yùn)行我們的爬蟲,很快數(shù)據(jù)庫(kù)表里就有數(shù)據(jù)了。

Python利用Django寫restful api接口的示例

然后開始寫接口。我是通過Django+rest_framework來(lái)寫的。

Django 是用Python開發(fā)的一個(gè)免費(fèi)開源的Web框架,可以用于快速搭建高性能,優(yōu)雅的網(wǎng)站。Django 中提供了開發(fā)網(wǎng)站經(jīng)常用到的模塊,常見的代碼都為你寫好了,減少重復(fù)的代碼。

Django 目錄結(jié)構(gòu)

urls.py

網(wǎng)址入口,關(guān)聯(lián)到對(duì)應(yīng)的views.py中的一個(gè)函數(shù)(或者generic類),訪問網(wǎng)址就對(duì)應(yīng)一個(gè)函數(shù)。

views.py

處理用戶發(fā)出的請(qǐng)求,從urls.py中對(duì)應(yīng)過來(lái), 通過渲染templates中的網(wǎng)頁(yè)可以將顯示內(nèi)容,比如登陸后的用戶名,用戶請(qǐng)求的數(shù)據(jù),輸出到網(wǎng)頁(yè)。

models.py

與數(shù)據(jù)庫(kù)操作相關(guān),存入或讀取數(shù)據(jù)時(shí)用到這個(gè),當(dāng)然用不到數(shù)據(jù)庫(kù)的時(shí)候 你可以不使用。

forms.py

表單,用戶在瀏覽器上輸入數(shù)據(jù)提交,對(duì)數(shù)據(jù)的驗(yàn)證工作以及輸入框的生成等工作,當(dāng)然你也可以不使用。

templates 文件夾

views.py 中的函數(shù)渲染templates中的Html模板,得到動(dòng)態(tài)內(nèi)容的網(wǎng)頁(yè),當(dāng)然可以用緩存來(lái)提高速度。

admin.py

后臺(tái),可以用很少量的代碼就擁有一個(gè)強(qiáng)大的后臺(tái)。

settings.py

Django 的設(shè)置,配置文件,比如 DEBUG 的開關(guān),靜態(tài)文件的位置等。

Django 常用操作

1)新建一個(gè) django project

django-admin.py startproject project_name

2)新建 app

python manage.py startapp app_name

一般一個(gè)項(xiàng)目有多個(gè)app, 當(dāng)然通用的app也可以在多個(gè)項(xiàng)目中使用。

還得在工程目錄的settings.py文件在配置

INSTALLED_APPS = [
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 
 'meizi',
]

在app/views.py下編寫代碼

def index(request):
 return HttpResponse(u"你好")

在工程目錄urls.py配置

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

通過python manage.py runserver啟動(dòng),就會(huì)看到我們輸出的“你好”了

 3)創(chuàng)建數(shù)據(jù)庫(kù)表 或 更改數(shù)據(jù)庫(kù)表或字段

在app下的models.py創(chuàng)建表

class Person(models.Model):
 name = models.CharField(max_length=30)
 age = models.IntegerField()
 
 def __unicode__(self):
 # 在Python3中使用 def __str__(self):
 return self.name

運(yùn)行命令,就可以生成對(duì)應(yīng)的表

Django 1.7.1及以上 用以下命令
# 1. 創(chuàng)建更改的文件
python manage.py makemigrations
# 2. 將生成的py文件應(yīng)用到數(shù)據(jù)庫(kù)
python manage.py migrate

在views.py文件里就可以獲取數(shù)據(jù)庫(kù)的數(shù)據(jù)

def create(request):
 # 新建一個(gè)對(duì)象的方法有以下幾種:
 Person.objects.create(name='xiaoli', age=18)
 # p = Person(name="WZ", age=23)
 # p = Person(name="TWZ")
 # p.age = 23
 # p.save()
 # 這種方法是防止重復(fù)很好的方法,但是速度要相對(duì)慢些,返回一個(gè)元組,第一個(gè)為Person對(duì)象,
 # 第二個(gè)為True或False, 新建時(shí)返回的是True, 已經(jīng)存在時(shí)返回False
 # Person.objects.get_or_create(name="WZT", age=23)
 s = Person.objects.get(name='xiaoli')
 return HttpResponse(str(s))

6.寫接口

接口使用rest_framework,rest_framework是一套基于Django 的 REST 框架,是一個(gè)強(qiáng)大靈活的構(gòu)建 Web API 的工具包。

寫接口三步完成:連接數(shù)據(jù)庫(kù)、取數(shù)據(jù)、數(shù)據(jù)輸出

1)連接數(shù)據(jù)庫(kù)

在工程目錄下的settings.py文件下配置  

DATABASES = {
 # 'default': {
 # 'ENGINE': 'django.db.backends.sqlite3',
 # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 # }
 'default': {
 'ENGINE': 'django.db.backends.mysql',
 'NAME': 'mysql',
 'USER': 'root',
 'HOST': '127.0.0.1',
 'PASSWORD': '123',
 'PORT': 3306,
 # show variables like 'character_set_database';
 # 修改字段字符編碼
 # alter table spiders_weibo modify text longtext charset utf8mb4 collate utf8mb4_unicode_ci;
 'OPTIONS': {'charset': 'utf8mb4'},
 }
}

2)取數(shù)據(jù)

既然要取數(shù)據(jù),那model肯定得和數(shù)據(jù)庫(kù)的一致,我發(fā)現(xiàn)一個(gè)快捷的方式可以把數(shù)據(jù)庫(kù)中的表生成對(duì)應(yīng)的model,在項(xiàng)目目錄下執(zhí)行命令

python manage.py inspectdb

可以看到下圖

Python利用Django寫restful api接口的示例

取我們表的model拷貝到app下的models.py里

class Meizis(models.Model):
 mid = models.CharField(max_length=10)
 title = models.CharField(max_length=50, blank=True, null=True)
 picname = models.CharField(max_length=10, blank=True, null=True)
 page_url = models.CharField(max_length=50, blank=True, null=True)
 img_url = models.CharField(max_length=50, blank=True, null=True)
 
 class Meta:
 managed = False
 db_table = 'meizi_meizis'

創(chuàng)建一個(gè)序列化Serializer類

提供序列化和反序列化的途徑,使之可以轉(zhuǎn)化為,某種表現(xiàn)形式如json。我們可以借助serializer來(lái)實(shí)現(xiàn),類似于Django表單(form)的運(yùn)作方式。在app目錄下,創(chuàng)建文件serializers.py。

class MeiziSerializer(serializers.ModelSerializer):
 # ModelSerializer和Django中ModelForm功能相似
 # Serializer和Django中Form功能相似
 class Meta:
 model = Meizis
 # 和"__all__"等價(jià)
 fields = ('mid', 'title', 'picname', 'page_url', 'img_url')

這樣在views.py就可以來(lái)獲取數(shù)據(jù)庫(kù)的數(shù)據(jù)了  

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

3) 數(shù)據(jù)輸出客戶端或前端

REST框架提供了兩種編寫API視圖的封裝。

  • @api_view裝飾器,基于方法的視圖。

  • 繼承APIView類,基于類的視圖。 

request.data會(huì)自行處理輸入的json請(qǐng)求

使用格式后綴明確的指向指定的格式,需要添加一個(gè)format關(guān)鍵字參數(shù)

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

@api_view(['GET', 'POST'])
def getlist(request, format=None):
 if request.method == 'GET':
 meizis = Meizis.objects.all()
 serializer = MeiziSerializer(meizis, many=True)
 return Response(serializer.data)
 
 elif request.method == 'POST':
 serializer = MeiziSerializer(data=request.data)
 if serializer.is_valid():
 serializer.save()
 return Response(serializer.data, status=status.HTTP_201_CREATED)
 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

4)分頁(yè)

最后別忘了在urls.py配置URL,通過瀏覽器就可以看到j(luò)son數(shù)據(jù)了。

Python利用Django寫restful api接口的示例

Python利用Django寫restful api接口的示例

 當(dāng)然app也是可以調(diào)用我們的接口的

還有個(gè)問題

我們的數(shù)據(jù)有好幾千條,一塊返回來(lái)很不合理,所以需要分頁(yè),當(dāng)然rest_framework框架提供了這個(gè)功能,post請(qǐng)求不支持,需要自己查數(shù)據(jù)庫(kù)或者切片來(lái)進(jìn)行返回。來(lái)看看rest_framework是如何來(lái)分頁(yè)的。在models.py里創(chuàng)建一個(gè)類

class StandardResultSetPagination(LimitOffsetPagination):
 # 默認(rèn)每頁(yè)顯示的條數(shù)
 default_limit = 20
 # url 中傳入的顯示數(shù)據(jù)條數(shù)的參數(shù)
 limit_query_param = 'limit'
 # url中傳入的數(shù)據(jù)位置的參數(shù)
 offset_query_param = 'offset'
 # 最大每頁(yè)顯示條數(shù)
 max_limit = None

在serializers.py創(chuàng)建倆個(gè)類,為什么是倆個(gè)?因?yàn)槲覀冇袀z個(gè)接口,一個(gè)明細(xì),一個(gè)列表,而列表是不需要把字段的所有數(shù)據(jù)都返回的

class ListSerialize(serializers.ModelSerializer):
 class Meta:
 model = Meizis
 fields = ('mid', 'title')
 
 
class ListPicSerialize(serializers.ModelSerializer):
 class Meta:
 model = Meizis
 fields = "__all__"

在views.py里編寫

@api_view(['GET'])
def getlist(request, format=None):
 if request.method == 'GET':
 meizis = Meizis.objects.values('mid','title').distinct()
 # http: // 127.0.0.1:8000 / getlist?limit = 20
 # http: // 127.0.0.1:8000 / getlist?limit = 20 & offset = 20
 # http: // 127.0.0.1:8000 / getlist?limit = 20 & offset = 40
 # 根據(jù)url參數(shù) 獲取分頁(yè)數(shù)據(jù)
 obj = StandardResultSetPagination()
 page_list = obj.paginate_queryset(meizis, request)
 # 對(duì)數(shù)據(jù)序列化 普通序列化 顯示的只是數(shù)據(jù)
 ser = ListSerialize(instance=page_list, many=True) # 多個(gè)many=True # instance:把對(duì)象序列化
 response = obj.get_paginated_response(ser.data)
 return response
 
 
@api_view(['GET', 'POST'])
def getlispic(request, format=None):
 if request.method == 'GET':
 mid = request.GET['mid']
 if mid is not None:
 # get是用來(lái)獲取一個(gè)對(duì)象的,如果需要獲取滿足條件的一些數(shù)據(jù),就要用到filter
 meizis = Meizis.objects.filter(mid=mid)
 obj = StandardResultSetPagination()
 page_list = obj.paginate_queryset(meizis, request)
 ser = ListPicSerialize(instance=page_list, many=True)
 response = obj.get_paginated_response(ser.data)
 return response
 else:
 return Response(str('請(qǐng)傳mid'))

感謝各位的閱讀!關(guān)于“Python利用Django寫restful api接口的示例”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI