Django框架使用指南
基于python3.6 和 django2.1
創(chuàng)建項(xiàng)目和應(yīng)用
新建一個(gè)項(xiàng)目
django-admin startproject back
cd back # 進(jìn)入到該項(xiàng)目的文件夾
django-admin startapp people # 新建一個(gè) people 應(yīng)用(app)
urls.py
網(wǎng)址入口,關(guān)聯(lián)到對(duì)應(yīng)的views.py中的一個(gè)函數(shù)(或者generic類),訪問網(wǎng)址就對(duì)應(yīng)一個(gè)函數(shù)。
views.py
處理用戶發(fā)出的請(qǐng)求,從urls.py中對(duì)應(yīng)過來, 通過Response()將json格式數(shù)據(jù)返回給前端
models.py
與數(shù)據(jù)庫操作相關(guān),存入或讀取數(shù)據(jù)時(shí)用到這個(gè),當(dāng)然用不到數(shù)據(jù)庫的時(shí)候 你可以不使用。
serializer.py
用于序列化數(shù)據(jù), 驗(yàn)證數(shù)據(jù)
templates
放置html模板, drf一般用不到
filter.py
用于過濾, 有需求時(shí)候會(huì)用上
admin.py
后臺(tái),可以用很少量的代碼就擁有一個(gè)強(qiáng)大的后臺(tái)。
settings.py
Django 的設(shè)置,配置文件,比如 DEBUG 的開關(guān),靜態(tài)文件的位置等。
django常用命令
- python manage.py runserver 0.0.0.0:80000 啟動(dòng)服務(wù)器
- python manage.py makemigrations 生成遷移文件
- python manage.py migrate 遷移數(shù)據(jù)庫
- python manage.py migrate --fake 遷移數(shù)據(jù)庫遇到?jīng)_突
- python manage.py inspectdb 反向生模型(models)
- python manage.py collectstatic 收集靜態(tài)文件
- python manage.py createsuperuser 創(chuàng)建管理員
- python manage.py flush 清空數(shù)據(jù)庫
第三方包管理
pip install xxx 可以安裝第三方庫
安裝的第三方庫可以導(dǎo)出到一個(gè)文件里面
pip freeze > requirements.txt
通過requirements.txt安裝第三方包
pip install -r requirments.txt
配置
配置都是在setting.py中
數(shù)據(jù)庫
django默認(rèn)數(shù)據(jù)庫是sqllite, mysql等數(shù)據(jù)庫需要改相應(yīng)的配置
修改DjangoBlog/setting.py 修改數(shù)據(jù)庫配置,如下所示:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'grocerdb',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
"OPTIONS": {
'charset': 'utf8mb4',
"init_command": "SET default_storage_engine=INNODB;"
},
}
}
ldap配置
# ### ldap configuration ###
import ldap
from django_auth_ldap.config import LDAPSearch, PosixGroupType
base_dn = ''
AUTH_LDAP_SERVER_URI = ''
AUTH_LDAP_BIND_DN = ''
AUTH_LDAP_BIND_PASSWORD = ''
AUTH_LDAP_USER_SEARCH = LDAPSearch(base_dn, ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
AUTH_LDAP_ALWAYS_UPDATE_USER = True
AUTH_LDAP_USER_ATTR_MAP = { # key為數(shù)據(jù)庫字段名,value為ldap中字段名,此字典解決django model與ldap字段名可能出現(xiàn)的不一致問題
"username": "uid",
"first_name": "givenName",
"last_name": "sn",
"email": "mail"
}
AUTHENTICATION_BACKENDS = (
'django_auth_ldap.backend.LDAPBackend', # 配置為先使用LDAP認(rèn)證,如通過認(rèn)證則不再使用后面的認(rèn)證方式
'django.contrib.auth.backends.ModelBackend',
)
郵箱配置
# Email configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = ''
EMAIL_PORT = 25
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_SUBJECT_PREFIX = '[] '
EMAIL_USE_TLS = False # 與SMTP服務(wù)器通信時(shí),是否啟動(dòng)TLS鏈接(安全鏈接)port: EMAIL_PORT
EMAIL_USE_SSL = False # 與SMTP服務(wù)器通信時(shí),是否啟動(dòng)TLS鏈接(安全鏈接)port: EMAIL_PORT
SERVER_EMAIL = EMAIL_HOST_USER
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
開發(fā)流程
前端發(fā)送請(qǐng)求首先會(huì)由back目錄下的urls.py分發(fā)到各個(gè)View, 底層view實(shí)現(xiàn)了http的get, post, delete, patch, update, 等方法drf框架對(duì)這些方法進(jìn)行了最基本的實(shí)現(xiàn), 只需要繼承相應(yīng)的mixin就可以, 比如post方法要繼承CreateModelMixin, serializer是用來序列化數(shù)據(jù), 驗(yàn)證數(shù)據(jù)的, 下面是一個(gè)restful風(fēng)格的api具體實(shí)現(xiàn):
首先定義一個(gè)model:
from django.db import models
class Opid(models.Model):
eng = models.TextField(blank=True, null=True)
jpn = models.TextField(blank=True, null=True)
Setting.py 里配置app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'opid'
]
遷移數(shù)據(jù)庫
python manage.py makemigrations
python manage.py migrate
View
業(yè)務(wù)邏輯放在view層
from rest_framework.viewsets import ModelViewSet
from .models import Opid
from .serializer import OpidSerializer
class OpidViewSet(ModelViewSet):
"""
ModelViewSet 方法繼承了全部的http方法
"""
serializer_class = OpidSerializer
queryset = Opid.objects.all()
Serializer
serializer主要是用來序列化數(shù)據(jù)成json, 驗(yàn)證等功能
opid目錄下新建serializer.py文件
from rest_framework import serializers
from .models import Opid
class OpidSerializer(serializers.ModelSerializer):
class Meta:
model = Opid
fields = '__all__'
urls
opid目錄下新建urls.py用于路由分發(fā)
from .views import OpidViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'opid', OpidViewSet, base_name='opid')
根目錄的urls文件
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from rest_framework.documentation import include_docs_urls
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
urlpatterns = [
# 后臺(tái)地址
path('admin/', admin.site.urls),
path('fz/api/v1/opid/', include('opid.urls')),
# 接口文檔地址
url(r'docs/', include_docs_urls(title="API文檔")),
]
前端請(qǐng)求方法對(duì)應(yīng)的url
- get /opid/ 獲取opid列表
- get /opid/1/ 獲取id為1的opid詳細(xì)
- post /opid/ 新規(guī)一個(gè)opid
- delete /opid/1/ 刪除id為1的opid
- update /opid/1/ 完全更新id為1的opid
- patch /opid/1 局部更新opid為1的opid
過濾
前端可以這樣搜索 /opid/?englishstring=xx&japanese=xx
from .filters import OpidFilter
from django_filters.rest_framework import DjangoFilterBackend
class OpidViewSet(ModelViewSet):
serializer_class = OpidSerializer
queryset = Opid.objects.all()
filter_backends = (DjangoFilterBackend,)
filter_class = OpidFilter
filters.py
import django_filters
from .models import Opid
from django.db.models import Q
class OpidFilter(django_filters.rest_framework.FilterSet):
englishstring = django_filters.CharFilter(field_name='eng')
japanese = django_filters.CharFilter(field_name='jpn')
japanese_english_opid = django_filters.CharFilter(method='japaneseOrEnglishOrOpidFilter', help_text='英語日語搜索')
def japaneseOrEnglishOrOpidFilter(self, queryset, name, value):
return Opid.objects.filter(Q(jpn__contains=value) | Q(eng__contains=value)| Q(opid__contains=value))
class Meta:
model = Opid
fields = ['englishstring', 'japanese', 'product']
分頁
前端可能發(fā)出這樣的請(qǐng)求 opid/?pageNo=1&pageSize=10 pageNo是當(dāng)前頁碼, pageSize是一頁有多少條數(shù)據(jù), drf自帶的分頁不是這種格式就需要自己重寫方法
view
from .filters import OpidFilter
from django_filters.rest_framework import DjangoFilterBackend
class OpidViewSet(ModelViewSet):
serializer_class = OpidSerializer
queryset = Opid.objects.all()
filter_backends = (DjangoFilterBackend,)
filter_class = OpidFilter
pagination_class = Pagination
from collections import OrderedDict
from rest_framework.response import Response
from rest_framework.pagination import LimitOffsetPagination
class Pagination(LimitOffsetPagination):
# 默認(rèn)每頁顯示的數(shù)據(jù)條數(shù)
# default_limit = 20
# URL中傳入的顯示數(shù)據(jù)條數(shù)的參數(shù)
limit_query_param = 'pageSize'
# URL中傳入的數(shù)據(jù)位置的參數(shù)
offset_query_param = 'pageNo'
def paginate_queryset(self, queryset, request, view=None):
self.count = self.get_count(queryset)
self.limit = self.get_limit(request)
if self.limit is None:
return queryset
_offset = self.get_offset(request)
if _offset == 1:
self.offset = 0
elif _offset == 0:
self.offset = _offset
else:
self.offset = (_offset - 1) * self.limit
self.request = request
if self.count > self.limit and self.template is not None:
self.display_page_controls = True
if self.count == 0 or self.offset > self.count:
return []
return list(queryset[self.offset:self.offset + self.limit])
def get_paginated_response(self, data):
return Response(OrderedDict([('count', self.count), ('results', data)]))
錯(cuò)誤消息通知
Sentry官網(wǎng)
Sentry是一個(gè)實(shí)時(shí)事件的日志聚合平臺(tái)。它專門監(jiān)測(cè)錯(cuò)誤并提取所有有用信息用于分析,不再麻煩地依賴用戶反饋來定位問題。
Sentry發(fā)展多年,幾乎沒有同類產(chǎn)品可與其媲美。它能覆蓋大部分的主流編程語言與框架,很適合應(yīng)用到實(shí)際生產(chǎn)環(huán)境中采集異常日志。
公司可以自己安裝服務(wù)器,也可以在它官網(wǎng)上注冊(cè)賬號(hào)(量大收費(fèi))
安裝sentry-sdk:
$ pip install --upgrade 'sentry-sdk==0.13.2'
setting.py中配置
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init(
dsn="https://<key>@sentry.io/<project>",
integrations=[DjangoIntegration()]
)