因爲在每一個項目所使用的解析器,當你運行別人的項目或者和別人合做開發一個項目,各個模塊的版本存在差別,建立虛擬環境可讓你運行的環境與別人的保持一致,html
虛擬環境的搭建在linue系統和window系統存在細微的差異前端
建立虛擬環境: mkvirtualenv 虛擬環境名python
指定解析器器的版本: mkvirtualenv luffy -p python3(這個是指定python解析器使用python3,能夠根據需求寫本身項目版本)linux
查看全部虛擬環境:workonredis
使用虛擬環境:workon 虛擬環境名稱數據庫
推出虛擬環境: deactivatedjango
刪除虛擬環境: rmvirtualenv 虛擬環境名稱(不能刪除當前正在使用的虛擬環境,須要先退出再刪除)後端
若是當前系統中沒有mkvirtualenv命令,可使用sudo apt-get install python-virtualenv和sudo easy_install virtualenvwrapper來安裝api
安裝virtualenv:pip install virtualenv服務器
建立虛擬環境: virtualenv 虛擬環境名
安裝3.7版本python解釋器: virtualenv -p F:\Python3.7\python37\python.exe 虛擬環境名
使用虛擬環境:在建立虛擬環境目錄下執行目錄文件 ./虛擬環境/Scripts/activate.bat
退出虛擬環境:在建立虛擬環境目錄下執行目錄文件 ./虛擬環境/Scripts/deactivate.bat
http://www.javashuo.com/article/p-eiauibub-k.html
在項目中,因爲須要人不能24小時去監控項目是否發生異常,全部能夠經過配置文件添加日誌文件配置來保存日誌信息,
能夠在配置文件中添加一下配置
# 日誌配置 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(module)s %(lineno)d %(message)s' }, }, 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'file': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 日誌位置,日誌文件名,日誌保存目錄必須手動建立 'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/luffy.log"), # 日誌文件的最大值,這裏咱們設置300M 'maxBytes': 300 * 1024 * 1024, # 日誌文件的數量,設置最大日誌數量爲10 'backupCount': 10, # 日誌格式:詳細格式 'formatter': 'verbose' }, }, # 日誌對象 'loggers': { 'django': { 'handlers': ['console', 'file'], 'propagate': True, # 是否讓日誌信息繼續冒泡給其餘的日誌處理系統 }, } }
此外,因爲django框架不能識別一些數據庫的錯誤,能夠自定義一個異常處理方法,而後能夠經過配置讓系統認識異常從而記錄下來
新建一個exceptions.py文件
from rest_framework.views import exception_handler from django.db import DatabaseError from rest_framework.response import Response from rest_framework import status import logging logger = logging.getLogger('django') def custom_exception_handler(exc, context): """ 自定義異常處理 :param exc: 異常類 :param context: 拋出異常的上下文 :return: Response響應對象 """ # 調用drf框架原生的異常處理方法 response = exception_handler(exc, context) if response is None: view = context['view'] if isinstance(exc, DatabaseError): # 數據庫異常 logger.error('[%s] %s' % (view, exc)) response = Response({'message': '服務器內部錯誤'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) return response
在配置文件中添加設置
REST_FRAMEWORK = { # 異常處理 'EXCEPTION_HANDLER': 'luffyapi.utils.exceptions.custom_exception_handler',#字典後面是自定義異常的路徑 }
雖然django內部已經有用戶登錄的表,可是該表格不知足項目需求,須要自定義一些字段來知足不一樣的登錄方式,如微信登錄,手機登陸等
咱們能夠自定義一個類,該類繼承系統提供的登錄模型類AbstractUser
class User(AbstractUser): """用戶模型類""" mobile = models.CharField(max_length=11, unique=True, verbose_name='手機號') class Meta: db_table = 'ly_users' verbose_name = '用戶' verbose_name_plural = verbose_name
寫好類後須要在配置文件
AUTH_USER_MODEL = 'users.User' #app名+模型類名,不用寫models.py這個文件名,系統自動識別,全部模型類必須寫在models.py文件中
中告訴系統登錄時使用自定義模型類而不是使用系統提供的
用戶登錄時,默認是經過用戶名和密碼的匹配來認證登錄成功與否,但用手機號登錄時就會失敗全部能夠經過自定義類來寫登錄邏輯
def get_user_by_account(account): """ 根據賬號獲取user對象 :param account: 帳號,能夠是用戶名,也能夠是手機號 :return: User對象 或者 None """ try: if re.match('^1[3-9]\d{9}$', account): # 賬號爲手機號 user = User.objects.get(mobile=account) else: # 賬號爲用戶名 user = User.objects.get(username=account) except User.DoesNotExist: return None else: return user import re from .models import User from django.contrib.auth.backends import ModelBackend class UsernameMobileAuthBackend(ModelBackend): """ 自定義用戶名或手機號認證 """ def authenticate(self, request, username=None, password=None, **kwargs): user = get_user_by_account(username) if user is not None and user.check_password(password): return user
經過配置文件來告訴系統
AUTHENTICATION_BACKENDS = [ 'user.utils.UsernameMobileAuthBackend', ]
極驗驗證: https://www.geetest.com/first_page/
雲通信發送短信: https://www.yuntongxun.com/
支付寶付款: https://open.alipay.com/platform/home.htm
保利威視頻加密:http://www.polyv.net/vod/
後端須要給前端發生圖片,視頻等媒體文件,須要建立一個目錄來存在這些文件,而且把該文件的目錄告訴django框架
在配置文件中添加
# 訪問靜態文件的url地址前綴 STATIC_URL = '/static/' # 設置django的靜態文件目錄 STATICFILES_DIRS = [ os.path.join(BASE_DIR,"static") ] # 項目中存儲上傳文件的根目錄[暫時配置],注意,uploads目錄須要手動建立不然上傳文件時報錯 MEDIA_ROOT=os.path.join(BASE_DIR,"uploads") # 訪問上傳文件的url地址前綴 MEDIA_URL ="/media/"
新增url
from django.urls import re_path from django.conf import settings from django.views.static import serve urlpatterns = [ ... re_path(r'media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}), ]
使用celery能夠異步處理一些耗時或者定時文體
安裝:pip install -U celery
使用:新建一個任務目錄
luffyapi/ ├── mycelery/ ├── config.py # 配置文件 ├── __init__.py ├── main.py # 主程序 └── sms/ # 一個目錄能夠放置多個任務,該目錄下存放當前任務執行時須要的模塊或依賴 └── tasks.py # 任務的文件,名稱必須是這個!!!
在main.py中
# 主程序 from celery import Celery # 建立celery實例對象 app = Celery("luffy") # 經過app對象加載配置 app.config_from_object("mycelery.config") # 自動搜索並加載任務 # 參數必須必須是一個列表,裏面的每個任務都是任務的路徑名稱 # app.autodiscover_tasks(["任務1","任務2"]) app.autodiscover_tasks(["mycelery.sms","mycelery.cache"]) # 啓動Celery的命令 # 強烈建議切換目錄到項目的根目錄下啓動celery!! # celery -A mycelerymain worker --loglevel=info
在config.py中
# 任務隊列的連接地址 broker_url = 'redis://127.0.0.1:6379/15' # 結果隊列的連接地址 result_backend = 'redis://127.0.0.1:6379/14'
在tasks.py中寫邏輯
# celery的任務必須寫在tasks.py的文件中,別的文件名稱不識別!!! from mycelery.main import app @app.task # name表示設置任務的名稱,若是不填寫,則默認使用函數名作爲任務名 def send_sms(): print("發送短信!!!") @app.task # name表示設置任務的名稱,若是不填寫,則默認使用函數名作爲任務名 def send_sms2(): print("發送短信任務2!!!")
官方文檔http://docs.jinkan.org/docs/celery/getting-started/index.html
celery定時任務文檔:http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html
在rest_framework中已經有2個分頁器的功能的類分別是PageNumberPagination和LimitOffsetPagination,能夠自定義一個類繼承模塊提供的類就能夠自定義分頁器。
PageNumberPagination:這個類展現數據是從第m條數據開始,到m+1 ..... 一致到第n條數據,共展示n-m條數據
LimitOffsetPagination:這個類展現數據是從第m條數據開始,日後偏移n條數據,共展示m+n條數據
兩個類區別如圖所示,一個是經過首位數據的id來展現數據,一個是首id+偏移來展現數據
以PageNumberPagination爲例:
from rest_framework.pagination import PageNumberPagination class CustomPageNumberPagination(PageNumberPagination): # page_query_param = "" # 地址上面表明頁碼的變量名,默認爲page page_size = 5 # 每一頁顯示的數據量,沒有設置頁碼,則不進行分頁 # 容許客戶端經過指定的參數名來設置每一頁數據量的大小,默認是size page_size_query_param = "size" max_page_size = 20 # 限制每一頁最大展現的數據量 # 按條件篩選[分類]展現課程信息 from django_filters.rest_framework import DjangoFilterBackend from rest_framework.filters import OrderingFilter from .paginations import CustomPageNumberPagination class CourseListAPIView(ListAPIView): """課程列表""" queryset = Course.objects.filter(is_show=True,is_delete=False).order_by("orders") serializer_class = CourseModelSerializer filter_backends = [DjangoFilterBackend, OrderingFilter] # 設置支持設置的篩選過濾字段 filter_fields = ('course_category', ) # 設置支持設置的排序字段 ordering_fields = ('id', 'students', 'price') # 指定分頁器 pagination_class = CustomPageNumberPagination
在某些邏輯中可能會存在同時操做多個數據表,但不能100%保證執行成功,若是聽任報錯前的數據,會致使數據表出現不少無用數據,因此須要開啓事務
添加裝飾器
from django.db import transaction from rest_framework.views import APIView class OrderAPIView(APIView): @transaction.atomic # 開啓事務,當方法執行完成之後,自動提交事務 def post(self,request): ....
使用with語句:
from django.db import transaction from rest_framework.views import APIView class OrderAPIView(APIView): def post(self,request): .... with transation.atomic(): # 設置事務回滾的標記點 sid = transation.savepoint() .... try: .... except: transation.savepoint_rallback(sid) #報錯則回滾到標記點