rest api
Api 介面 高山山書寫例子
-
resources.py
#!coding=utf-8 import json from django.http.response import HttpResponse from django.conf.urls import url from django.views.decorators.csrf import csrf_exempt from Api.utils import method_not_allowed # 為所有的請求 規定一個預設類 方便 且 節省程式碼量 不用每次判斷method class Resource(object): def __init__(self, name=None): # 給 resource 初始名字 如果沒有輸入name 那麼初始名為自己的類名 self.name = name or self.__class__.__name__.lower() def enter(self, request, *args, **kwargs): method = request.method #判斷request的型別是什麼,分別進行處理 if method == 'GET': response = self.get(request, *args, **kwargs) elif method == 'POST': response = self.post(request, *args, **kwargs) elif method == 'PUT': response = self.put(request, *args, **kwargs) elif method == 'DELETE': response = self.delete(request, *args, **kwargs) elif method == 'HEAD': response = self.head(request, *args, **kwargs) elif method == "OPTIONS": response = self.options(request, *args, **kwargs) else: response = HttpResponse(json.dumps({ "state": 422, "msg": '方法不支援' })) return response # 因為是預設的resources類裡的方法 預設都是返回方法不支援 def get(self, request, *args, **kwargs): return method_not_allowed() # method_not_allowed 這類經常用到的函式 可以放在一個py檔案裡 此例子是放在utils.py檔案中 def post(self, request, *args, **kwargs): return method_not_allowed() def delete(self, request, *args, **kwargs): return method_not_allowed() def put(self, request, *args, **kwargs): return method_not_allowed() def options(self, request, *args, **kwargs): return method_not_allowed() def head(self, request, *args, **kwargs): return method_not_allowed() # url註冊器 register方法將檢視類 class Register(object): def __init__(self, version='v1'): self.version = version self.resources = [] def regist(self, resource): self.resources.append(resource) @property # property裝飾器 可以使函式 通過 register.urls 來獲得函式的返回值 def urls(self): urlpatterns = [] for resource in self.resources: urlpatterns.append( url(r'{version}/{name}'.format(version=self.version, name=resource.name), csrf_exempt(resource.enter)) #csrf_exempt()裝飾器 是為了使enter方法可以不被csrf限制 ) return urlpatterns
-
views.py
#!coding=utf-8 import random from datetime import datetime from django.contrib.auth import authenticate, login, logout from Question.models import * from Api.resources import Resource from Api.utils import * from Api.decorators import * #以下均為檢視的類方法 繼承上面的Resource類 只需要寫自己需要的方法 不需要寫那些限制的重複程式碼 #由於瀏覽器只有get和post兩種方式 且django框架只能解析form-data, json,xml,text均無法自動解析 因此寫一箇中介軟體 用來偽增加瀏覽器的請求方式(實際上還是隻有兩種請求方式), 並對返回的不同格式的資料進行提取解析, 方便在檢視檔案中進行操作 獲取註冊碼 class ReigstCodeResource(Resource): def get(self, request, *args, **kwargs): regist_code = random.randint(10000, 100000) request.session['regist_code'] = regist_code return HttpResponse(json.dumps({ 'regist_code': regist_code }), content_type="application/json") 使用者資訊 class UserResource(Resource): # 獲取使用者資訊 def get(self, request, *args, **kwargs): if request.user.is_authenticated: user = request.user # 判斷是否是普通使用者 if hasattr(user, 'userinfo'): userinfo = user.userinfo # 構建json字典 data = dict() data['user'] = user.id data['age'] = getattr(userinfo, 'age', '') data['name'] = getattr(userinfo, 'name', '') data['gender'] = getattr(userinfo, 'gender', '') data['phone'] = getattr(userinfo, 'phone', '') data['email'] = getattr(userinfo, 'email', '') data['address'] = getattr(userinfo, 'address', '') if userinfo.birthday: data['birthday'] = userinfo.birthday.strftime("%Y-%m-%d") else: data['birthday'] = datetime.now().strftime("%Y-%m-%d") data['qq'] = getattr(userinfo, 'qq', '') data['wechat'] = getattr(userinfo, 'wechat', '') data['job'] = getattr(userinfo, 'job', '') data['salary'] = getattr(userinfo, 'salary', '') # 用json把data轉化成字串,返回給客戶端 return HttpResponse(json.dumps(data), content_type="application/json") # 判斷是否是客戶 elif hasattr(user, 'customer'): customer = user.customer # 構建json字典 data = dict() data['user'] = user.id data['name'] = getattr(customer, 'name', '') data['email'] = getattr(customer, 'email', '') data['company'] = getattr(customer, 'company', '') data['address'] = getattr(customer, 'address', '') data['phone'] = getattr(customer, 'phone', '') data['mobile'] = getattr(customer, 'mobile', '') data['qq'] = getattr(customer, 'qq', '') data['wechat'] = getattr(customer, 'wechat', '') data['web'] = getattr(customer, 'web', '') data['industry'] = getattr(customer, 'industry', '') data['description'] = getattr(customer, 'description', '') # 用json把data轉化稱字串,返回給客戶端 return HttpResponse(json.dumps(data), content_type="application/json") else: # 沒有相關使用者資訊,返回空 return HttpResponse(json.dumps({ "data": {} }), content_type="application/json") # 使用者未登入,不允許檢視資訊 return HttpResponse(json.dumps({ "msg": '未登入' }), content_type="application/json")
-
# 註冊使用者
def put(self, request, *args, **kwargs):
data = request.PUT
username = data.get('username', '')
password = data.get('password', '')
regist_code = data.get('regist_code', '')
session_regist_code = request.session.get('regist_code', '')
category = data.get('category', 'userinfo')
ensure_password = data.get('ensure_password', '')
# 構建錯誤資訊字典
errors = dict()
if not username:
errors['username'] = '沒有提供使用者名稱'
elif User.objects.filter(username=username):
errors['username'] = '使用者名稱已存在'
if len(password) < 6:
errors['password'] = '密碼長度不夠'
if password != ensure_password:
errors['ensure_password'] = '密碼不一樣'
if regist_code != str(session_regist_code):
errors['regist_code'] = '驗證碼不對'
if errors:
return HttpResponse(json.dumps(errors), content_type='application/json')
user = User()
user.username = username
# 設定密碼
user.set_password(password)
user.save()
# 根據使用者型別,建立普通使用者或者客戶
if category == 'userinfo':
userinfo = UserInfo()
userinfo.user = user
userinfo.name = '姓名'
userinfo.save()
else:
customer = Customer()
customer.name = '客戶名稱'
customer.user = user
customer.save()
return HttpResponse(json.dumps({
"msg": "建立成功",
"user_id": user.id
}), content_type='application/json')
# 更新使用者
def post(self, request, *args, **kwargs):
data = request.POST
user = request.user
if user.is_authenticated:
# 判斷是否是普通使用者
if hasattr(user, 'userinfo'):
userinfo = user.userinfo
userinfo.name = data.get('name', '姓名')
userinfo.age = data.get('age', '')
userinfo.gender = data.get('gender', '')
userinfo.phone = data.get('phone', '')
userinfo.email = data.get('email', '')
userinfo.address = data.get('address', '')
# 時間特殊處理
try:
birthday = datetime.strptime(
data.get('birthday', '2018-01-01'), "%Y-%m-%d")
except Exception as e:
birthday = datetime.now()
userinfo.birthday = birthday
userinfo.qq = data.get('qq', '')
userinfo.wechat = data.get('wechat', '')
userinfo.job = data.get('job', '')
userinfo.salary = data.get('salary', '')
userinfo.save()
# 判斷是否是客戶
elif hasattr(user, 'customer'):
customer = user.customer
customer.name = data.get('name', '客戶名稱')
customer.email = data.get('email', '')
customer.company = data.get('company', '')
customer.address = data.get('address', '')
customer.phone = data.get('phone', '')
customer.mobile = data.get('mobile', '')
customer.qq = data.get('qq', '')
customer.wechat = data.get('wechat', '')
customer.web = data.get('web', '')
customer.industry = data.get('industry', '')
customer.description = data.get('description', '')
customer.save()
return HttpResponse(json.dumps({
'msg': '更新成功'
}), content_type="application/json")
return HttpResponse(json.dumps({
'msg': '還未登入'
}), content_type="application/json")
使用者登入與退出
class SessionResource(Resource):
def get(self, request, *args, **kwargs):
if request.user.is_authenticated:
return json_response({
'msg': '已經登入'
})
return json_response({
'msg': '還未登入'
})
def put(self, request, *args, **kwargs):
data = request.PUT
username = data.get('username', '')
password = data.get('password', '')
user = authenticate(username=username, password=password)
if user:
login(request, user)
return json_response({
'msg': '登入成功'
})
return json_response({
'msg': '使用者名稱或密碼錯誤'
})
def delete(self, request, *args, **kwargs):
logout(request)
return json_response({
'msg': '退出成功'
})
問卷資源
class QuestionnaireResource(Resource):
@customer_required
def get(self, request, *args, **kwargs):
return json_response({})
@customer_required
def put(self, request, *args, **kwargs):
return json_response({})
@customer_required
def post(self, request, *args, **kwargs):
return json_response({})
@customer_required
def delete(self, request, *args, **kwargs):
return json_response({})
```
```
-
middleware.py 中介軟體
import json from django.http.multipartparser import MultiPartParser from django.middleware.common import MiddlewareMixin class DataConvert(MiddlewareMixin): """ # 資料型別轉換 > 因為django只能解析使用post方式上傳的formdata > 不能夠解析通過其他方法上傳的json,xml,text格式資料,所以這裡面,我們需要手動來解析上傳的資料 """ def process_request(self, request): method = request.method if 'application/json' in request.META['CONTENT_TYPE']: # 把客戶端上傳的json資料轉化成python字典 data = json.loads(request.body.decode()) files = None elif 'multipart/form-data' in request.META['CONTENT_TYPE']: # 把客戶端已formdata上傳的資料進行解析,通常客戶端會把上傳的檔案也放在formdata中, # 所以下面的解析會把上傳的檔案也解析出來 data, files = MultiPartParser( request.META, request, request.upload_handlers).parse() else: data = request.GET files = None if 'HTTP_X_METHOD' in request.META: method = request.META['HTTP_X_METHOD'].upper() setattr(request, 'method', method) if files: setattr(request, '{method}_FILES'.format(method=method), files) setattr(request, method, data)
-
decorators.py 裝飾器
from Api.utils import permission_denied #因為檢視檔案中 很多函式需要加使用者驗證 使用裝飾器 減少程式碼量 # 在執行制定方法前, 先對使用者進行判斷 是否已經登陸, 並對其進行分類處理 def customer_required(func): def _wrapper(self, request, *args, **kwargs): if request.user.is_authenticated and hasattr(request.user, 'customer'): return func(self, request, *args, **kwargs) return permission_denied() return _wrapper def userinfo_required(func): def _wrapper(self, request, *args, **kwargs): if request.user.is_authenticated and hasattr(request.user, 'userinfo'): return func(self, request, *args, **kwargs) return permission_denied() return _wrapper
-
utils.py 一些常見的response放在這個檔案中
#!coding=utf-8 import json from django.http.response import HttpResponse def method_not_allowed(): return HttpResponse(json.dumps({ "state": 405, "msg": '方法不支援', }), content_type="application/json") def json_response(data): json_data = { 'state': 200, 'msg': 'OK', 'data': data } return HttpResponse(json.dumps(json_data), content_type='application/json') def server_error(): return HttpResponse(json.dumps({ 'state': 500, 'msg': '伺服器發生錯誤' }), content_type='application/json') def not_found(): return HttpResponse(json.dumps({ 'state': 404, 'msg': '沒有找到頁面' }), content_type='application/json') def params_error(data={}): return HttpResponse(json.dumps({ 'state': 422, 'msg': '引數錯誤', 'data': data }), content_type='application/json') def not_authenticated(): return HttpResponse(json.dumps({ 'state': 401, 'msg': '未登入' }), content_type='application/json') def permission_denied(): return HttpResponse(json.dumps({ 'state': 403, 'msg': '沒有許可權' }), content_type='application/json')
相關文章
- GraphQL API vs REST APIAPIREST
- Spark REST API & metricsSparkRESTAPI
- Elasticsearch(二)——Rest APIElasticsearchRESTAPI
- Django REST framework API 指南(21):SchemasDjangoRESTFrameworkAPI
- Harbor配置Swagger遠端REST APISwaggerRESTAPI
- rest-api設計風格RESTAPI
- Django REST framework API 指南(6):路由DjangoRESTFrameworkAPI路由
- Django REST framework API 指南(7):解析DjangoRESTFrameworkAPI
- Django REST framework API 指南(8):渲染DjangoRESTFrameworkAPI
- Django REST framework API 指南(27):SettingsDjangoRESTFrameworkAPI
- Django REST framework API 指南(15):限流DjangoRESTFrameworkAPI
- Django REST framework API 指南(17):分頁DjangoRESTFrameworkAPI
- Django REST framework API 指南(18):版本控制DjangoRESTFrameworkAPI
- Elasticsearch Java High Level REST Client(Exists API)ElasticsearchJavaRESTclientAPI
- Elasticsearch Java High Level REST Client(Delete API)ElasticsearchJavaRESTclientdeleteAPI
- REST API簽名認證機制RESTAPI
- Django REST framework API 指南(13):認證DjangoRESTFrameworkAPI
- elasticsearch常用請求介面Rest API示例ElasticsearchRESTAPI
- Flask框架搭建REST-API服務Flask框架RESTAPI
- Pulsar 入門實戰(6)--Rest APIRESTAPI
- Django REST framework API 指南(23):返回 URLDjangoRESTFrameworkAPI
- Django REST framework API 指南(24):異常DjangoRESTFrameworkAPI
- Django REST framework API 指南(26):測試DjangoRESTFrameworkAPI
- Django REST framework API 指南(16):過濾DjangoRESTFrameworkAPI
- 在 .NET Core 中構建 REST APIRESTAPI
- Elasticsearch 入門實戰(8)--REST API 使用二(Search API)ElasticsearchRESTAPI
- (16) SpringCloud-Eureka的REST API及API擴充套件SpringGCCloudRESTAPI套件
- Django REST framework API 指南(5):檢視集DjangoRESTFrameworkAPI
- 影響rest api版本選擇的因素RESTAPI
- Django REST framework API 指南(12):驗證器DjangoRESTFrameworkAPI
- Django REST framework API 指南(14):許可權DjangoRESTFrameworkAPI
- Django REST framework API 指南(9):序列化DjangoRESTFrameworkAPI
- 使用JBang構建Spring Boot Rest API教程Spring BootRESTAPI
- SpringBoot:Java High Level REST Client 搜尋 APISpring BootJavaRESTclientAPI
- Django REST framework API 指南(4):通用檢視DjangoRESTFrameworkAPI
- Django REST framework API 指南(22):Format 字尾DjangoRESTFrameworkAPIORM
- Django REST framework API 指南(25):狀態碼DjangoRESTFrameworkAPI
- 快用Django REST framework寫寫API吧DjangoRESTFrameworkAPI