Django
虛擬環境
創建:virtualenv --no-site-packages -p python.exe的路徑 環境名
安裝與使用
安裝:pip install django==2.1.7
創建Django項目:django-admin startproject 項目名
創建django應用:python manage.py startapp 應用名
啟動,修改IP和端口
修改端口:python manage.py runserver 端口號
修改IP和端口:python manage.py runserver IP:端口號
數據庫簡單配置與遷移
修改settings.py文件中DATABASE的數據:NAME,USER,PASSWORD,HOST,PORT,OPTIONS
不管用不用,都必須遷移默認的模型 遷移django默認提供的模型:python manage.py migrate
管理后臺
訪問:IP:端口/admin/
創建賬號:python manage.py createsuperuser
模型
遷移
生成遷移文件: python manage.py makemigrations
執行遷移文件:python manage.py migrate
注意:當第一次遷移Django默認提供的表時,直接執行migrate命令即可
模型定義
-
字段定義
IntegerField:整型字段
CharField:字符串
BooleanField:布爾值
DateTimeField:年月日時分秒字段
DateField:年月日
TimeField:時間戳
ImageField:圖片
FloatField:浮點數
DecimalField:浮點數,指定了長度的浮點數
TextField:文本,textarea
AutoField:自增字段,不用定義
-
約束定義
max_length:最大長度
min_length:最小長度
unique:是否唯一
null:是否為空
default:默認值
auto_now_add和auto_now:互斥
模型操作
-
增
對象.save()
模型.objects.create(字段1=值1,字段2=值2,...)
-
刪
對象.delete()
模型.objects.filter().delete()
-
改
修改的對象.save()
模型.objects.filter().update(字段1=值1,字段2=值2,...)
-
查
all():queryset結果
first():取結果中第一個對象
last():取結果中最后一個對象
模型.objects.filter(字段='值')
-
模型.objects.get(條件)
條件必須成立
查詢結果只有一個
exclude(條件):過濾不滿足條件的信息
count():查詢結果的個數
values('字段'):將對象的內容序列化成字典/json
-
order_by('字段')
升序:order_by('字段')
降序:order_by('-字段')
-
contains:包含
- 模型.objects.filter(字段__contains='值')
startswith:以什么開頭
endswith:以什么結尾
-
大小于
大于,大于等于:gt,gte
小于,小于等于:lt, lte
-
aggregate:聚合
- Avg, Sum, Count, Max, Min
-
F:對比兩個屬性字段,可以進行加減算法
- 模型.objects.filter(字段1__gt=F('字段2'))
-
Q:用于與或非
或:Q(條件1) | Q(條件2)
非:~Q(條件1)
模型關系
一對一
OneToOneField(關聯模型)
-
模型定義
class A(): id = models.IntegerField()
class B(): aa = models.OneToOneField(A, related_name='cc')
已知:A對象a,查詢B對象 related_name沒定義時: a.b related_name已定義時: a.cc
已知:B對象b,查詢A對象 b.aa
注意:OneToOneField定義的字段可以寫在關聯模型的任意一方
一對多
ForeignKey(關聯模型)
-
模型定義
class A(): id
class B(): aa = ForeignKey(A, related_name='cc')
已知:A對象a,查詢B對象 related_name沒定義時: a.b_set.all() related_name已定義時: a.cc.all()
已知:B對象b,查詢A對象 b.aa
注意:ForeignKey定義的字段表示多的對方,因此只能放在'多'的模型中
多對多
ManyToManyField(關聯模型):會自動生成中間表
-
模型定義
class A(): id
class B(): aa = ManyToMany(A, related_name='cc')
已知:A對象a,查詢B對象 related_name沒定義時: a.b_set.all()
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n198" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">related_name已定義時:
a.cc.all()</pre>已知:B對象b,查詢A對象 b.aa.all()
注意:ManyToMany定義的字段可以寫在關聯模型的任意一方
中間表的添加:add()、刪除:remove()
字段中的on_delete參數值
models.CASCADE: 表示主鍵所在行的數據被刪,外鍵所在行的數據也會被刪,是完全關聯在一起的
models.PROTECT: 表示主鍵作為外鍵存在別的表中時,不讓刪除主鍵的數據
models.SET_NULL: 表示主鍵刪除,外鍵置空
模板
父模板:用于挖坑{% block name %} {% endblock %}
子模板:負責繼承父模板后,進行填坑
標簽:{% 標簽 %}
{% extends '父模板' %}
{% block name %} {% endblock %}
{% if 條件 %} {% else %} {% endif %}
{% ifequal 變量 值 %} {% endifequal %}
{% for i in [] %} {% endfor %}
解析靜態文件地址: {% static 'css/xxx.css' %} 繼承模板的時候,要有: {% load static %}
解析路由地址: {% url 'user:index' %}
變量:{{ 變量名 }}
{{ forloop.counter }}
{{ forloop.counter0 }}
{{ forloop.revcounter }}
{{ forloop.revcounter1 }}
{{ forloop.first }}
{{ forloop.last }}
{{ stu.course.all }}:通過學生查詢所有的課程信息
{{ stu.course.下標 }}
過濾器
- 定義:使用管道符 '|'
路由規則
path
轉換器:int, str, uuid, path
re_path
/(\d+)/(\w+)/
(?P<參數名>\d+)
include
urlpatterns = [ path('admin/', admin.site.urls), # 包含 # TODO:Django2.0以下寫法, path('goods/', include('goods.urls')), path('app/', include('app.urls')) ]
- 拆分路由地址,將不同應用的URL文件進行拆分
請求與響應
請求
method:判斷請求方式,主要GET/POST
path:獲取訪問的路由地址
FILES:獲取圖片或文件的信息
-
GET:獲取get請求方式的數據
get()
getlist()
POST:獲取post請求方式的數據
COOKIES:cookie內容
session:存儲在服務端的數據
響應
-
跳轉:HttpResponseRedirect()
-
無參
- HttpResponseRedirect(reverse('namespace:name'))
-
有參
HttpResponseRedirect(reverse('namespace:name', kwargs={'參數名': '值'}))
HttpResponseRedirect(reverse('namespace:name', args=(值, )))
-
頁面反向解析
- {% url 'namespace:name' 值1 值2 值3 ... %}
-
JsonResponse():響應json格式的數據
HttpResponse(字符串)
render(頁面)
用戶USER
使用django自帶的USER模塊
注冊:User.objects.create_user()
校驗:user = auth.authenticate(username, password)
登錄:auth.login(request, user)
退出:auth.logout(requset)
裝飾器:login_required() 要配合在setting里面設置才有用: LOGIN_URL = '/user/login/'
自定義USER模塊
登錄:request.session['user_id'] = user.id 添加鍵值對的時候,同時會把數據庫中創建的session_key傳給瀏覽器
-
退出
request.session.flush() 同時刪除數據庫和瀏覽器中的session
request.session.delete(session_key) 刪除數據庫中對應的session記錄
del request.session['user_id'] 刪除數據庫中之前添加的鍵值對,相當于刪除瀏覽器識別session的唯一標識
-
裝飾器
from django.http import HttpResponseRedirect from django.urls import reverse
from user.models import MyUser
def is_login(func):
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n352" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">def check(request, *args, **kwargs):
登錄的校驗
if 'user_id' in request.session:
user = MyUser.objects.get(pk=request.session['user_id'])
request.user = user
return func(request, *args, **kwargs)
else:
return HttpResponseRedirect(reverse('user:my_login'))
?
return check</pre>
中間件MIDDLEWARE
process_request(self, request):請求進來時直接進行攔截(應用場景:登錄校驗)
process_view(self, request, view_func, view_args, view_kwargs):調用view方法之前進行攔截調用
process_exception(self, request, exception):不主動調用,只有出現異常時才執行
process_response(self, response):最后響應瀏覽器時才調用
process_template_response():沒有應用場景
執行順序
中間件按照排列順序,從上往下依次執行process_request(), 如果返回None表示繼續訪問中間件或者方法, 如果return HttpResponse() 表示直接響應內容給瀏覽器
process_request()執行完畢后,從上往下執行process_view()
前面的方法沒有返回響應時,從下往上執行process_response()
文件上傳
安裝:pip install pillow
模型中定義字段:
icon = models.ImageField(upload_to='upload')
設置media文件夾路徑:
MEDIA_URL = 'media' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
展示圖片需要在工程目錄的urls.py文件中指定靜態文件路由:
static(MEDIA_URL, document_root=MEDIA_ROOT)
展示圖片:
前端中定義屬性<form enctype='multipart/form-data'>
表單驗證
定義
class UserForm(forms.Form):
forms.CharField
forms.IntegerField
forms.ImageField
def clean(self):
# 自動調用
return self.cleaned_data
def clean_字段(self):
# 校驗指定字段
return self.cleaend_data
?
forms = UserForm(request.POST, request.FILES)
驗證:form.is_valid()
驗證錯誤信息:form.errors
分頁
from django.core.paginator import Paginator
paginator = Paginator(所有數據,條數)
查看總頁數:paginator.num_pages
獲取某一頁的數據: page_data = paginator.page(頁碼)
paginator.page_range:相當于range(1,總頁碼數)
page_data = paginator.page(頁碼)
越界會報錯
page_data.has_next():是否有下一頁
page_data.has_previous:是否有上一頁
page_data.next_page_number:下一頁頁碼
page_data.previous_page_number:上一頁頁碼
page_data.paginator:獲取paginator對象
權限
RBAC
用戶表--權限表--角色表:
都是多對多關聯關系
用戶和權限:user_permissions字段
用戶和角色:groups字段
角色和權限:permissions字段
權限列表
1.通過用戶查詢權限表
2.通過用戶查詢角色,角色查詢權限
權限獲取
獲取所有權限:包括用戶對應角色權限和用戶對應權限表,user.get_all_permissions()
獲取用戶組權限:user.get_group_permissions()
權限校驗裝飾器
- @permission_required('應用名.權限名')
模板中
解析當前用戶的權限,是個集合: {{ perms.user }}:{'應用名.權限名'}
{% if perms.user.add_users %}