欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

怎么在django項(xiàng)目中將數(shù)據(jù)導(dǎo)出到excel文件-創(chuàng)新互聯(lián)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)怎么在django項(xiàng)目中將數(shù)據(jù)導(dǎo)出到excel文件,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

新林ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為成都創(chuàng)新互聯(lián)公司的ssl證書(shū)銷(xiāo)售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話(huà)聯(lián)系或者加微信:18982081108(備注:SSL證書(shū)合作)期待與您的合作!

依賴(lài)模塊

xlwt下載:pip install xlwt

后臺(tái)模塊

view.py

# 導(dǎo)出Excel文件
def export_excel(request):
  city = request.POST.get('city')
  print(city)
  list_obj=place.objects.filter(city=city)
  # 設(shè)置HTTPResponse的類(lèi)型
  response = HttpResponse(content_type='application/vnd.ms-excel')
  response['Content-Disposition'] = 'attachment;filename='+city+'.xls'
  """導(dǎo)出excel表"""
  if list_obj:
    # 創(chuàng)建工作簿
    ws = xlwt.Workbook(encoding='utf-8')
    # 添加第一頁(yè)數(shù)據(jù)表
    w = ws.add_sheet('sheet1') # 新建sheet(sheet的名稱(chēng)為"sheet1")
    # 寫(xiě)入表頭
    w.write(0, 0, u'地名')
    w.write(0, 1, u'次數(shù)')
    w.write(0, 2, u'經(jīng)度')
    w.write(0, 3, u'緯度')
    # 寫(xiě)入數(shù)據(jù)
    excel_row = 1
    for obj in list_obj:
      name = obj.place
      sum = obj.sum
      lng = obj.lng
      lat = obj.lat
      # 寫(xiě)入每一行對(duì)應(yīng)的數(shù)據(jù)
      w.write(excel_row, 0, name)
      w.write(excel_row, 1, sum)
      w.write(excel_row, 2, lng)
      w.write(excel_row, 3, lat)
      excel_row += 1
    # 寫(xiě)出到IO
    output = BytesIO()
    ws.save(output)
    # 重新定位到開(kāi)始
    output.seek(0)
    response.write(output.getvalue())
  return response

前端模塊

<button id="export_excel" type="button" class="btn btn-primary col-sm-5"  >導(dǎo)出excel</button>

$("#export_excel").click(function () {
     var csrf=$('input[name="csrfmiddlewaretoken"]').val();
     const req = new XMLHttpRequest();
     req.open('POST', '/export_excel/', true);
     req.responseType = 'blob';
     req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); //設(shè)置請(qǐng)求頭
     req.send('city='+$('#city').val()+"&&csrfmiddlewaretoken="+csrf); //輸入?yún)?shù)
     req.onload = function() {
       const data = req.response;
       const a = document.createElement('a');
       const blob = new Blob([data]);
       const blobUrl = window.URL.createObjectURL(blob);
       download(blobUrl) ;
     };

   });
function download(blobUrl) {
 var city = $("input[name='city']").val();
 const a = document.createElement('a');
 a.style.display = 'none';
 a.download = '<文件命名>';
 a.href = blobUrl;
 a.click();
 document.body.removeChild(a);
}

補(bǔ)充知識(shí):Python Django實(shí)現(xiàn)MySQL百萬(wàn)、千萬(wàn)級(jí)的數(shù)據(jù)量下載:解決memoryerror、nginx time out

前文

在用Django寫(xiě)項(xiàng)目的時(shí)候時(shí)常需要提供文件下載的功能,而Django也是貼心提供了幾種方法:FileResponse、StreamingHttpResponse、HttpResponse,其中FileResponse和StreamingHttpResponse都是使用迭代器迭代生成數(shù)據(jù)的方法,所以適合傳輸文件比較大的情況;而HttpResponse則是直接取得數(shù)據(jù)返回給用戶(hù),所以容易造成memoryerror和nginx time out(一次性取得數(shù)據(jù)和返回的數(shù)據(jù)過(guò)多,導(dǎo)致nginx超時(shí)或者內(nèi)存不足),關(guān)于這三者,DJango的官網(wǎng)也是寫(xiě)的非常清楚,連接如下:https://docs.djangoproject.com/en/1.11/ref/request-response/

那正常我們使用的是FileResponse和StreamingHttpResponse,因?yàn)樗鼈兞魇絺鬏?迭代器)的特點(diǎn),可以使得數(shù)據(jù)一條條的返回給客戶(hù)端,文件隨時(shí)中斷和復(fù)傳,并且保持文件的一致性。

FileResponse和StreamingHttpResponse

FileResponse顧名思義,就是打開(kāi)文件然后進(jìn)行傳輸,并且可以指定一次能夠傳輸?shù)臄?shù)據(jù)chunk。所以適用場(chǎng)景:從服務(wù)端返回大文件。缺點(diǎn)是無(wú)法實(shí)時(shí)獲取數(shù)據(jù)庫(kù)的內(nèi)容并傳輸給客戶(hù)端。舉例如下:

def download(request):
 file=open('path/demo.py','rb')
  response =FileResponse(file)
  response['Content-Type']='application/octet-stream'
  response['Content-Disposition']='attachment;filename="demo.py"'
  return response

從上可以發(fā)現(xiàn),文件打開(kāi)后作為參數(shù)傳入FileResponse,隨后指定傳輸頭即可,但是很明顯用這個(gè)來(lái)傳輸數(shù)據(jù)庫(kù)就不太方便了,所以這邊推介用StreamingHttpResponse的方式來(lái)傳輸。

這里就用PyMysql來(lái)取得數(shù)據(jù),然后指定為csv的格式返回,具體代碼如下:

# 通過(guò)pymysql取得數(shù)據(jù)
import pymysql
field_types = {
    1: 'tinyint',
    2: 'smallint',
    3: 'int'} #用于后面的字段名匹配,這里省略了大多數(shù)
conn = pymysql.connect(host='127.0.0.1',port=3306,database='demo',user='root',password='root')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute(sql)
#獲取所有數(shù)據(jù)
data = cursor.fetchall()
cols = {}
#獲取所有字段
for i,row in enumerate(self.cursor.description):
 if row[0] in cols:
   cols[str(i)+row[0]] = field_types.get(row[1], str(row[1])) #這里的field_type是類(lèi)型和數(shù)字的匹配
 cols[row[0]] = field_types.get(row[1], str(row[1]))
cursor.close()
conn.close()

#通過(guò)StreamingHttpResponse指定返回格式為csv
response = StreamingHttpResponse(get_result_fromat(data, cols))
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = 'attachment;filename="{0}"'.format(out_file_name)
return response

#循環(huán)所有數(shù)據(jù),然后加到字段上返回,注意的是要用迭代器來(lái)控制
def get_result_fromat(data, cols):
 tmp_str = ""
 # 返回文件的每一列列名
  for col in cols:
    tmp_str += '"%s",' % (col)
  yield tmp_str.strip(",") + "\n"
  for row in data:
    tmp_str = ""
    for col in cols:
      tmp_str += '"%s",' % (str(row[col]))
    yield tmp_str.strip(',') + "\n"

整個(gè)代碼如上,大致分為三部分:從mysql取數(shù)據(jù),格式化成我們想要的格式:excel、csv、txt等等,這邊指定的是csv,如果對(duì)其他格式也有興趣的可以留言,最后就是用StreamingHttpResponse指定返回的格式返回。

實(shí)現(xiàn)百萬(wàn)級(jí)數(shù)據(jù)量下載

上面的代碼下載可以支持幾萬(wàn)行甚至十幾萬(wàn)行的數(shù)據(jù),但是如果超過(guò)20萬(wàn)行以上的數(shù)據(jù),那就比較困難了,我這邊的剩余內(nèi)存大概是1G的樣子,當(dāng)超過(guò)15萬(wàn)行數(shù)據(jù)(大概)的時(shí)候,就報(bào)memoryerror了,問(wèn)題就是因?yàn)閒etchall,雖然我們StreamingHttpResponse是一條條的返回,但是我們的數(shù)據(jù)時(shí)一次性批量的取得!

如何解決?以下是我的解決方法和思路:

用fetchone來(lái)代替fetchall,迭代生成fetchone

發(fā)現(xiàn)還是memoryerror,因?yàn)閑xecute是一次性執(zhí)行,后來(lái)發(fā)現(xiàn)可以用流式游標(biāo)來(lái)代替原來(lái)的普通游標(biāo),即SSDictCursor代替DictCursor

于是整個(gè)代碼需要修改的地方如下:

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) ===>
cursor = conn.cursor(cursor=pymysql.cursors.SSDictCursor)

data = cursor.fetchall() ===>
row = cursor.fetchone()

def get_result_fromat(data, cols):
 tmp_str = ""
 # 返回文件的每一列列名
  for col in cols:
    tmp_str += '"%s",' % (col)
  yield tmp_str.strip(",") + "\n"
  for row in data:
    tmp_str = ""
    for col in cols:
      tmp_str += '"%s",' % (str(row[col]))
    yield tmp_str.strip(',') + "\n" 
    
    =====>
    
def get_result_fromat(data, cols):
 tmp_str = ""
  for col in cols:
    tmp_str += '"%s",' % (col)
  yield tmp_str.strip(",") + "\n"
  while True:
    tmp_str = ""
    for col in cols:
      tmp_str += '"%s",' % (str(row[col]))
    yield tmp_str.strip(',') + "\n"
    row = db.cursor.fetchone()
    if row is None:
      break

可以看到就是通過(guò)while True來(lái)實(shí)現(xiàn)不斷地取數(shù)據(jù)下載,有效避免一次性從MySQL取出內(nèi)存不足報(bào)錯(cuò),又或者取得過(guò)久導(dǎo)致nginx超時(shí)!

上述就是小編為大家分享的怎么在django項(xiàng)目中將數(shù)據(jù)導(dǎo)出到excel文件了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

文章標(biāo)題:怎么在django項(xiàng)目中將數(shù)據(jù)導(dǎo)出到excel文件-創(chuàng)新互聯(lián)
URL分享:http://aaarwkj.com/article20/dohsjo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、品牌網(wǎng)站設(shè)計(jì)網(wǎng)站設(shè)計(jì)公司、網(wǎng)站排名、面包屑導(dǎo)航、ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
亚洲最大成人综合福利网| 成人精品亚洲一区二区| 亚洲熟妇丰满多毛的大昊| 久久精品欧美日韩视频| 人妻熟女一区二区视频| 日韩视频播放一区二区| 日本午夜福利免费在线播放| 亚洲成年人黄片在线播放| 一区二区五区日韩国产| 深夜av一区二区三区| 日韩亚洲中文一区三级黄片| 亚洲黄色成人在线观看| 日韩精品一区二区91| 丝袜美腿亚洲欧美日韩| 末满18周岁禁止观看| 97成人在线视频免费播放| 91狠狠综合久久精品| 欧美日本一区二区三区免费| 日本免费熟女一区二区| 国产麻豆剧传媒国产av| 九九热在线视频观看最新| 日本高清一区二区不卡视频| 欧美黄片网站免费观看| 日本免费一区二区三区四区视频| 亚洲日本一区二区高清| 久久热久久热在线视频| 国产精品1区2区久久久 | 美女丝袜诱惑国产在线观看| 不卡在线视频中文字幕| 91在线视频国产网站| 91香蕉伊人综合久久麻豆| 黄色片在线观看中文字幕| 91精品夜夜夜一区二区| 一区二区三区视频在线国产| 91精品麻豆国产自产在线 | 国产亚洲中文字幕91| 男人天堂在线视频网站| 亚洲无线码一区国产欧美国日| 最新91精品手机国产在线| 在线亚洲精品一区二区| 欧美日韩一级性生活片|