1:web網(wǎng)站的設(shè)計(jì)哲學(xué)(MVC/MTV的設(shè)計(jì)哲學(xué))
創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司是一家服務(wù)多年做網(wǎng)站建設(shè)策劃設(shè)計(jì)制作的公司,為廣大用戶提供了網(wǎng)站設(shè)計(jì)制作、網(wǎng)站制作,成都網(wǎng)站設(shè)計(jì),廣告投放,成都做網(wǎng)站選創(chuàng)新互聯(lián),貼合企業(yè)需求,高性價比,滿足客戶不同層次的需求一站式服務(wù)歡迎致電。
2:Request && response
1: Request——用戶有5種方式對服務(wù)器發(fā)起請求
POST請求(正常情況下都會帶參數(shù)) 常用語表單場景
#get不帶參數(shù) get通過?加參數(shù) post請求的url格式如下
path('hello/', views.index, name='index'),
#關(guān)鍵字傳參數(shù) (?<參數(shù)名>參數(shù)類型)——視圖中直接通過參數(shù)名獲取值(最常用)
re_path('hello/(?P[0-9]{4})/(?P[0-9]{2})/', views.index, name='index')
]
2:Response——2大類3小類獲取到數(shù)據(jù)
request.method —— 判斷請求的方式
request.body —— 第一種獲取數(shù)據(jù)數(shù)據(jù)的方式
print(type(request.body)) # byte
print(QueryDict(request.body)) # QueryDict
print(QueryDict(request.body).dict) # dict
request.GET # 第二種方式獲取GET QueryDictrequest.GET.get('name','devops')
request.POST # 第二種獲取post數(shù)據(jù)方式 request.POST.getlist('id')
1. 安裝MySQL驅(qū)動
pip3 install mysqlclient
如果報錯,請參考:https://blog.51cto.com/qiangsh/2422115
2. 修改數(shù)據(jù)庫配置
$ cat devops/settings.py
# 注釋原有數(shù)據(jù)庫配置
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
#
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# }
# 使用mysql數(shù)據(jù)庫替換掉上面sqlite3
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'devops',
'USER': 'devops',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
3. 初始化數(shù)據(jù)庫(需要在setting中注冊APP)
# 查看現(xiàn)有的遷移文件的狀態(tài),是否同步到數(shù)據(jù)庫中
python manage.py showmigrations
# 同步models到本地?cái)?shù)據(jù)庫文件
python manage.py makemigrations
# 同步數(shù)據(jù)庫文件里的sql預(yù)計(jì)到數(shù)據(jù)庫執(zhí)行
python manage.py migrate
# 創(chuàng)建admin超級管理員(登錄Django Admin頁面使用)
python manage.py createsuperuser
# 啟動
python manage.py runserver 0.0.0.0:8000
1: HTML、CSS
$ view.py
return render(request, 'index.html', {"user":user})
$ index.html
姓名 年齡
{% for user in users %}
{{user.name}} {{user.age}}
{% endfor %}
$ login.html
2: bootstrap
3: 實(shí)戰(zhàn)——打通TV,模板繼承,渲染一個表格數(shù)據(jù)
$ cat hello/urls.py
app_name = 'hello'
urlpatterns = [
path('list/', views.list, name = 'list'),
]
第二步:編寫對于url的view,提供偽數(shù)據(jù)來處理用戶請求
$ cat hello/views.py
def list(request,*args,**kwargs):
users = [
{'username': 'qsh2', 'name_cn': 'qsh2', 'age': 18},
{'username': 'qsh3', 'name_cn': 'qsh3', 'age': 19},
{'username': 'qsh4', 'name_cn': 'qsh4', 'age': 20},
]
return render(request,'list.html',{'users':users})
第三步:模板繼承及渲染
$ cat templates/base.html # 模板
……
{% load static %}
{% block title %} 自動化運(yùn)維平臺 {% endblock %}
個人主頁
{% block breadcrunb %}
{% endblock %}
{% block content %}
{% endblock %}
……
$ cat templates/list.html # 子頁面繼承
{% extends "base.html" %}
{% block title %} 用戶權(quán)限管理系統(tǒng) {% endblock %}
{% block breadcrunb %}
用戶展示
{% endblock %}
{% block content %}
序號
用戶名
姓名
年齡
{% for user in users %}
{{ forloop.counter }}
{{ user.username }}
{{ user.name_cn }}
{{ user.age }}
{% endfor %}
{% endblock %}
效果圖
$ cat users/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
#UserProfile會被初始化為數(shù)據(jù)庫表名(users_userprofile)
class UserProfile(AbstractUser):
name_cn = models.CharField('中文名', max_length=30)
phone = models.CharField('手機(jī)', max_length=11, null=True, blank=True)
class Meta:
verbose_name = '用戶信息'
verbose_name_plural = verbose_name # 讓后臺顯示為'用戶信息'
def __str__(self):
return self.username
$ cat settings.py
ROOT_URLCONF = 'devops.urls'
AUTH_USER_MODEL = 'users.UserProfile'
python manage.py makemigrations
python manage.py migrate
打通MTV
$ cat devops/urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include('users.urls')),
]
$ cat users/urls.py
from django.urls import path, re_path
from . import views
app_name = 'users'
urlpatterns = [
path('userlist/', views.userlist, name = 'userlist'),
]
$ cat users/views.py
from django.shortcuts import render
from users.models import UserProfile
def userlist(request,*args,**kwargs):
#從.models 中獲取表中所有數(shù)據(jù)
users = UserProfile.objects.all()
print(users,type(users)) # , , , , ]>
return render(request,'list1.html',{'users':users})
$ cat settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR+"/templates"], # 添加模板目錄
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
STATIC_URL = '/static/'
#添加以下幾行
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
$ cat list1.html
{% extends 'base.html' %}
{% block title %}
用戶展示
{% endblock %}
{% block breadcrunb %}
用戶展示
{% endblock %}
{% block content %}
序號
用戶名
姓名
手機(jī)號
{% for user in users %}
{{ forloop.counter }}
{{ user.username }}
{{ user.name_cn }}
{{ user.phone }}
{% endfor %}
{% endblock %}
用戶登錄第一版——FBV+數(shù)據(jù)庫
$ cat devops/urls.py
urlpatterns = [
#訪問根路徑走 users.urls 路由規(guī)則
path('', include('users.urls')),
]
$ cat users/urls.py
from django.urls import path,re_path
from . import views
app_name = 'users'
urlpatterns = [
path("login/", views.login, name='login'),
]
$ cat users/views.py
from django.http import HttpResponse, QueryDict, HttpResponseRedirect
from django.shortcuts import render
from .models import UserProfile
# 引入密碼加密模塊,Django框架自帶的一套加密方法
from django.contrib.auth.hashers import make_password
def login(request, **kwargs):
data = ""
if request.method == "POST":
username = request.POST.get('username','qsh')
passwd = request.POST.get('password','123456')
#user = UserProfile.objects # users.UserProfile.objects
user = models.UserProfile.objects.filter(username=username).first()
print('user:', user,user.password) # user: qsh2 pbkdf2_sha256$150000$44dU9PmGegDb$Yv95GU+eFy9Yw/DwinEaOP6fH8nCkQ0ElAUxMfDoR8c=
print('make_password',make_password(passwd)) # 給輸入的密碼加密后字符
if user:
# 如果數(shù)據(jù)庫查詢出來的密碼(密文)和輸入密碼匹配(make_password模塊加密)
if user.password == make_password(passwd):
return HttpResponseRedirect("/userlist/")
else:
data = "your passwd is wrong"
else:
data = "user is not exist"
return render(request, 'login.html', {'data':data})
if request.method == "GET":
return render(request, 'login.html', {'data':data})
$ cat templates/login.html
第二個版本 引入CBV view (與歷史無半點(diǎn)關(guān)系,從頭來過)
$ cat devops/urls.py
from django.contrib import admin
from django.urls import path, re_path, include
urlpatterns = [
path('admin/', admin.site.urls),
path("", include('users.urls1')),
]
$ cat users/urls1.py
from django.urls import path, re_path
from users import views1
app_name = 'users'
urlpatterns = [
# http://ip:8000/
path("", views1.IndexView.as_view(), name='index'),
# http://ip:8000/login/
path("login/", views1.LoginView.as_view(), name='login'),
# http://ip:8000/logout/
path("logout/", views1.LogoutView.as_view(), name='logout'),
path("userlist/",views.userlist, name='userlist'),
]
$ cat users/views1.py
from django.views.generic import View
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.contrib.auth import authenticate, login, logout
from django.urls import reverse
class IndexView(View):
"""
首頁
"""
def get(self, request):
return render(request, 'list1.html')
class LoginView(View):
"""
登錄模塊
"""
def get(self, request):
return render(request, "login.html")
def post(self, request):
username = request.POST.get("username", None)
password = request.POST.get("password", None)
print(username)
user = authenticate(username=username, password=password)
print(user)
if user:
if user.is_active:
# 默認(rèn)為當(dāng)前登錄用戶創(chuàng)建session
login(request, user)
# 登錄成功則跳到首頁
# return HttpResponseRedirect('/')
# 命名空間的寫法
return HttpResponseRedirect(reverse("users:userlist"))
else:
return render(request, "login.html", {"msg": "用戶未激活!"})
else:
return render(request, "login.html", {"msg": "用戶名或密碼錯誤!"})
class LogoutView(View):
"""
登出功能
"""
def get(self, request):
logout(request)
return HttpResponseRedirect(reverse("users:login"))
實(shí)現(xiàn)效果
用戶認(rèn)證版本迭代
class IndexView(View):
"""
首頁
"""
def get(self, request):
return render(request, 'list1.html')
class IndexView(View):
"""
首頁
"""
def get(self, request):
if not request.user.is_authenticated:
return HttpResponseRedirect(reverse("users:login"))
return render(request, 'list1.html')
沒登錄不會進(jìn)入用戶列表頁,而是跳轉(zhuǎn)到登錄頁
# CBV應(yīng)用裝飾器, django的bug,不能直接對類進(jìn)行裝飾,必須使用 method_decorator,把裝飾器當(dāng)作參數(shù)傳進(jìn)去。
from django.utils.decorators import method_decorator
from django.contrib.auth import authenticate, login, logout,decorators
class IndexView(View):
"""
首頁
"""
# login_url 用戶沒有通過測試時跳轉(zhuǎn)的地址,默認(rèn)是 settings.LOGIN_URL
@method_decorator(decorators.login_required(login_url='/login/'))
def get(self, request):
return render(request, 'list1.html')
from django.contrib.auth.mixins import LoginRequiredMixin
# LoginRequiredMixin驗(yàn)證用戶
class IndexView(LoginRequiredMixin, View):
"""
首頁
"""
# 用戶沒有通過或者權(quán)限不夠時跳轉(zhuǎn)的地址,默認(rèn)是 settings.LOGIN_URL.
login_url = '/login/'
# 把沒通過檢查的用戶重定向到?jīng)]有 "next page" 的非登錄頁面時,把它設(shè)置為 None ,這樣它會在 URL 中移除。
redirect_field_name = 'redirect_to' # http://127.0.0.1:8000/login/?redirect_to=/
def get(self, request):
return render(request, 'list1.html')