Django框架使用指南
基于python3.6 和 django2.1
創(chuàng)建項目和應用
新建一個項目
django-admin startproject back
cd back # 進入到該項目的文件夾
django-admin startapp people # 新建一個 people 應用(app)
urls.py
網(wǎng)址入口,關聯(lián)到對應的views.py中的一個函數(shù)(或者generic類)咆耿,訪問網(wǎng)址就對應一個函數(shù)男窟。
views.py
處理用戶發(fā)出的請求潮饱,從urls.py中對應過來, 通過Response()將json格式數(shù)據(jù)返回給前端
models.py
與數(shù)據(jù)庫操作相關粮坞,存入或讀取數(shù)據(jù)時用到這個,當然用不到數(shù)據(jù)庫的時候 你可以不使用鬼悠。
serializer.py
用于序列化數(shù)據(jù), 驗證數(shù)據(jù)
templates
放置html模板, drf一般用不到
filter.py
用于過濾, 有需求時候會用上
admin.py
后臺债鸡,可以用很少量的代碼就擁有一個強大的后臺。
settings.py
Django 的設置庸论,配置文件职辅,比如 DEBUG 的開關,靜態(tài)文件的位置等聂示。
django常用命令
- python manage.py runserver 0.0.0.0:80000 啟動服務器
- 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
可以安裝第三方庫
安裝的第三方庫可以導出到一個文件里面
pip freeze > requirements.txt
通過requirements.txt
安裝第三方包
pip install -r requirments.txt
配置
配置都是在setting.py
中
數(shù)據(jù)庫
django默認數(shù)據(jù)庫是sqllite, mysql等數(shù)據(jù)庫需要改相應的配置
修改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認證秀鞭,如通過認證則不再使用后面的認證方式
'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服務器通信時,是否啟動TLS鏈接(安全鏈接)port: EMAIL_PORT
EMAIL_USE_SSL = False # 與SMTP服務器通信時扛禽,是否啟動TLS鏈接(安全鏈接)port: EMAIL_PORT
SERVER_EMAIL = EMAIL_HOST_USER
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
開發(fā)流程
前端發(fā)送請求首先會由back
目錄下的urls.py
分發(fā)到各個View, 底層view實現(xiàn)了http的get, post, delete, patch, update, 等方法drf框架對這些方法進行了最基本的實現(xiàn), 只需要繼承相應的mixin就可以, 比如post方法要繼承CreateModelMixin, serializer是用來序列化數(shù)據(jù), 驗證數(shù)據(jù)的, 下面是一個restful風格的api具體實現(xiàn):
首先定義一個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è)務邏輯放在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, 驗證等功能
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 = [
# 后臺地址
path('admin/', admin.site.urls),
path('fz/api/v1/opid/', include('opid.urls')),
# 接口文檔地址
url(r'docs/', include_docs_urls(title="API文檔")),
]
前端請求方法對應的url
- get /opid/ 獲取opid列表
- get /opid/1/ 獲取id為1的opid詳細
- post /opid/ 新規(guī)一個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ā)出這樣的請求 opid/?pageNo=1&pageSize=10 pageNo是當前頁碼, 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):
# 默認每頁顯示的數(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)]))
錯誤消息通知
Sentry官網(wǎng)
Sentry是一個實時事件的日志聚合平臺锋边。它專門監(jiān)測錯誤并提取所有有用信息用于分析,不再麻煩地依賴用戶反饋來定位問題编曼。
Sentry發(fā)展多年豆巨,幾乎沒有同類產(chǎn)品可與其媲美。它能覆蓋大部分的主流編程語言與框架掐场,很適合應用到實際生產(chǎn)環(huán)境中采集異常日志往扔。
公司可以自己安裝服務器,也可以在它官網(wǎng)上注冊賬號(量大收費)
安裝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()]
)