前言
之前的文章完成了接口文檔到參數(shù)解析, 一個(gè)完整的流程中還缺少對(duì)數(shù)據(jù)庫(kù)的操作. 本篇內(nèi)容為django連接數(shù)據(jù)庫(kù), 并編寫一個(gè)image表用來存儲(chǔ)圖片路徑, 編寫圖片上傳接口和查看數(shù)據(jù)庫(kù)中所有圖片路徑的接口.
前期準(zhǔn)備
django操作圖片需要安裝一個(gè)三方庫(kù)叫做,Pillow
workon python35
pip install pillow
pip install pymysql
Pillow這個(gè)庫(kù)可以對(duì)圖片進(jìn)行操作, 例如生成縮略圖等等, 非常強(qiáng)大.
pymysql是python3中用來連接數(shù)據(jù)庫(kù)的一個(gè)庫(kù).
安裝mysql數(shù)據(jù)庫(kù). 安裝MySQLWorkBench(作用和navicat一樣,使用其他軟件也可以)

選好點(diǎn)擊apply 提交創(chuàng)建新庫(kù).
django如何存儲(chǔ)圖片
一般圖片不存數(shù)據(jù)庫(kù)單獨(dú)存儲(chǔ)于某個(gè)路徑, 開發(fā)過程中就存在項(xiàng)目的某個(gè)路徑下.
iOS開發(fā)中有個(gè)http 304問題. 就是請(qǐng)求圖片時(shí), 如果有緩存直接取緩存的圖片. 實(shí)際上蘋果早已幫我們處理好了. 實(shí)際開發(fā)中不需要針對(duì)http 304編寫任何代碼.
關(guān)于http 304的問題
https://segmentfault.com/a/1190000004356632
這一篇文章寫的非常詳細(xì)了.
現(xiàn)在我們進(jìn)行服務(wù)端編程, 服務(wù)端是如何生成etag, last-modify這些參數(shù)的呢?
這個(gè)問題涉及到服務(wù)端框架對(duì)靜態(tài)資源的管理方法.
在實(shí)際將項(xiàng)目部署到服務(wù)器上時(shí), 我們對(duì)動(dòng)態(tài)資源和靜態(tài)資源是分開管理的. 我使用nginx+uwsgi 部署, nginx 管理靜態(tài)資源, ETag 之類的, nginx 會(huì)自動(dòng)生成,管理, 不需要服務(wù)端程序員為此編寫什么代碼.....
圖片上傳接口, 接收到圖片文件, 類型, 大小校驗(yàn), 將圖片保存到靜態(tài)文件目錄下, 生成此圖片的url存儲(chǔ)到mysql數(shù)據(jù)庫(kù).
編寫存儲(chǔ)圖片路徑和id的表.
修改models.py文件.
from django.db import models
import datetime
class Image(models.Model):
# url = models.TextField(null=True)
image = models.ImageField(upload_to=str('image/{time}'.format(time=str(datetime.date.today().strftime("%Y%m/%d")))))
create_time = models.DateTimeField(auto_now_add=True, null=True)
update_time = models.DateTimeField(auto_now=True, null=True)
class Meta:
pass
ImageField中的upload_to表示圖片上傳的具體路徑.
修改數(shù)據(jù)庫(kù)配置連接mysql
修改settings.py文件中的DATABASES 到下面的樣式. name是剛剛創(chuàng)建mysql新庫(kù)的名稱. user password 是mysql用戶的用戶名和密碼. mysql端口號(hào)默認(rèn)為3306
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'root',
'PASSWORD': '111111',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
記得刪除 migrations目錄下除了__init__.py 之外的所有文件.
這些文件記錄了對(duì)數(shù)據(jù)庫(kù)定義個(gè)整個(gè)修改流程. 切換數(shù)據(jù)庫(kù)后這個(gè)流程和新庫(kù)根本對(duì)不上號(hào). 需要全部刪除.
修改與settings.py 同一目錄的__init__.py 文件
添加兩行代碼
import pymysql
pymysql.install_as_MySQLdb()
cd到項(xiàng)目manage.py文件的路徑下,運(yùn)行
workon python35
python manage.py makemigrations
python manage.py migrate
使用mysqlworkbench 連接3306打開之前創(chuàng)建的庫(kù)可以看到表都已經(jīng)被創(chuàng)建出來

編寫圖片上傳接口
from rest_framework import serializers
class ImageUploadSerializer(serializers.Serializer):
token = serializers.CharField(max_length=100)
image = serializers.ImageField()
from .models import *
from django.views.decorators.csrf import csrf_exempt
import time
import hashlib
class ImageUpload(APIView):
'''
圖片上傳接口 \n
"http://127.0.0.1:8000/pages/uploadImage" (我簡(jiǎn)單寫了個(gè)頁面做提交)\n
'''
# coreapi_fields = (DocParam(name='token', description='token'),
# DocParam(name='image', description='文件', type='file'),)
@csrf_exempt
def post(self, request, *args, **kwargs):
image = request.FILES['image']
data = get_parameter_dic(request)
# 需要判斷文件類型是否是圖片.
serial = ImageUploadSerializer(data={"token": data["token"],
"image": image})
if serial.is_valid():
print("校驗(yàn)成功")
else:
return JsonError("參數(shù)校驗(yàn)失敗")
image = serial.validated_data.get("image")
new_image = Image(image=image)
imageName = str(new_image.image.name)
location = str(imageName).find('.')
extension = imageName[location:]
name = imageName[:location]
namestring = name+str(time.time())
md5 = hashlib.md5(namestring.encode('utf-8')).hexdigest()
new_image.image.name = md5[:10] + extension
new_image.save()
return JsonResponse(data=new_image)
運(yùn)行項(xiàng)目

調(diào)用上傳圖片接口, 我用了postman測(cè)試接口

圖片存儲(chǔ)位置

圖片的完整訪問路徑為
http://localhost:8000/image/201710/20/d527b242d1.jpg
此時(shí)請(qǐng)求會(huì)失敗因?yàn)檫@個(gè)路徑不允許訪問, 需要進(jìn)行簡(jiǎn)單配置
setting.py 文件中添加
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')
urls.py文件中添加
from django.conf.urls import url, include
from django.contrib import admin
from rest_framework.schemas import get_schema_view
from mytest.views import ReturnJson
import mytest
from mytest.views import SwaggerSchemaView
from mytest.views import ImageUpload
from django.views.static import serve
from django.conf import settings
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^docs/', SwaggerSchemaView.as_view(), name='apiDocs'),
url(r'^api/getjson', ReturnJson.as_view()),
url(r'^api/uploadimage', ImageUpload.as_view()),
# url(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]
這次圖片鏈接變?yōu)?/p>
http://localhost:8000/media/image/201710/20/d527b242d1.jpg
寫一個(gè)查詢所有圖片并返回json的接口
from .models import Image
class GETAllImages(APIView):
def get(self, request, *args, **kwargs):
imagesset=Image.objects.all()
return JsonResponse(data=imagesset)
修改urls.py文件添加此接口
from django.conf.urls import url, include
from django.contrib import admin
from rest_framework.schemas import get_schema_view
from mytest.views import ReturnJson
import mytest
from mytest.views import SwaggerSchemaView
from mytest.views import ImageUpload, GETAllImages
from django.views.static import serve
from django.conf import settings
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^docs/', SwaggerSchemaView.as_view(), name='apiDocs'),
url(r'^api/getjson', ReturnJson.as_view()),
url(r'^api/uploadimage', ImageUpload.as_view()),
url(r'^api/getallimage', GETAllImages.as_view()),
url(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]
全部搞定
