使用django框架進行web項目開發需要了解的知識


1.虛擬環境的搭建

由於在每個項目所使用的解析器,當你運行別人的項目或者和別人合作開發一個項目,各個模塊的版本存在差異,創建虛擬環境可以讓你運行的環境與別人的保持一致,

虛擬環境的搭建在linue系統和window系統存在細微的差別

linux系統

創建虛擬環境:  mkvirtualenv  虛擬環境名

指定解析器器的版本: mkvirtualenv luffy -p python3(這個是指定python解析器使用python3,可以根據需求寫自己項目版本)

查看所有虛擬環境:workon

使用虛擬環境:workon  虛擬環境名稱

推出虛擬環境: deactivate

刪除虛擬環境: rmvirtualenv 虛擬環境名稱(不能刪除當前正在使用的虛擬環境,需要先退出再刪除)

如果當前系統中沒有mkvirtualenv命令,可以使用sudo apt-get install python-virtualenv和sudo easy_install virtualenvwrapper來安裝

window系統

安裝virtualenv:pip install virtualenv

創建虛擬環境:  virtualenv 虛擬環境名

安裝3.7版本python解釋器:  virtualenv -p F:\Python3.7\python37\python.exe 虛擬環境名

使用虛擬環境:在創建虛擬環境目錄下執行目錄文件  ./虛擬環境/Scripts/activate.bat

退出虛擬環境:在創建虛擬環境目錄下執行目錄文件  ./虛擬環境/Scripts/deactivate.bat

 2.項目中經常使用的模塊

https://www.cnblogs.com/mark--ping/p/11527445.html

 3.日志文件的配置

在項目中,由於需要人不能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',#字典后面是自定義異常的路徑
}

 

 4.用戶登陸表

雖然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',
]

 

5.外部接口的使用

極驗驗證:   https://www.geetest.com/first_page/

雲通訊發送短信: https://www.yuntongxun.com/

支付寶付款: https://open.alipay.com/platform/home.htm

保利威視頻加密:http://www.polyv.net/vod/

 

6.媒體文件的上傳

后端需要給前端發生圖片,視頻等媒體文件,需要創建一個目錄來存在這些文件,並且把該文件的目錄告訴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}),
]

 7.celery

使用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

8.分頁數據

在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

 

9.數據庫事物開啟與回滾

在某些邏輯中可能會存在同時操作多個數據表,但不能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) #報錯則回滾到標記點

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM