【前端开发学习】7.Django
文章目錄
- 1 初識(shí)Django
- 1.1 django的安裝
- 1.2 創(chuàng)建django項(xiàng)目
- 1.3 兩種創(chuàng)建方式的對(duì)比
- 1.4 默認(rèn)文件介紹
- 1.5 APP的創(chuàng)建和說(shuō)明
- 1.6 啟動(dòng)運(yùn)行django
- 1.7 模板和靜態(tài)文件
- 1.8 模板語(yǔ)法
- 1.9 請(qǐng)求和響應(yīng)
- 1.10 orm數(shù)據(jù)庫(kù)操作
- 1.11 ORM 數(shù)據(jù)庫(kù)案例:用戶(hù)管理
- 2 案例
- 2.1 創(chuàng)建項(xiàng)目和 APP
- 2.2 表結(jié)構(gòu)的創(chuàng)建
- 2.3 生成數(shù)據(jù)庫(kù)
- 2.4 部門(mén)管理
- 2.5 數(shù)據(jù)庫(kù)數(shù)據(jù)
- 2.6 添加部門(mén)頁(yè)面
- 2.7 部門(mén):添加
- 2.8 部門(mén):刪除
- 2.9 部門(mén):編輯
- 2.10 模板繼承
- 2.11 用戶(hù)管理:列表
- 2.12 用戶(hù)管理:添加
- 1. 思路
- 2. 原始方法
- 3.Form
- 4. ModelForm
- 5. 使用 ModelForm 添加用戶(hù)
- 6. 添加的錯(cuò)誤提示
- 2.13 用戶(hù)管理:編輯
- 2.14 用戶(hù)管理:刪除
- 3 案例:靚號(hào)管理
- 3.1 表結(jié)構(gòu)
- 3.2 靚號(hào)列表
- 3.3 新建靚號(hào)
- 3.4 編輯靚號(hào)
- 3.5 刪除靚號(hào)
- 3.6 靚號(hào)管理:手機(jī)號(hào)搜索
- 3.7 靚號(hào)管理:分頁(yè)
- 4 時(shí)間選擇組件
- 5 BootStrap 樣式父類(lèi)
- 6 views 函數(shù)拆分
- 7 案例:管理員
- 7.1
1 初識(shí)Django
1.1 django的安裝
pip install django1.2 創(chuàng)建django項(xiàng)目
- cmd命令行創(chuàng)建
- Pycharm 【需要專(zhuān)業(yè)版】
1.3 兩種創(chuàng)建方式的對(duì)比
- 命令行,創(chuàng)建的項(xiàng)目是比較標(biāo)準(zhǔn)的;
- Pycharm,與命令行方式對(duì)比:
- 增加了templates目錄;【刪除】
- setting.py中,TEMPLATES = [{ ‘DIRS’: [’ ******* ']}] 【DIRS中的內(nèi)容刪除】
1.4 默認(rèn)文件介紹
mysite
- manage.py 【項(xiàng)目管理,啟動(dòng)項(xiàng)目、創(chuàng)建APP、數(shù)據(jù)管理】- 不修改,常用
- mysite
- __ init __.py
- settings.py 【項(xiàng)目配置文件】- 常常操作
- urls.py 【URL和函數(shù)的對(duì)應(yīng)關(guān)系】- 常常操作
- asgi.py 【接收網(wǎng)絡(luò)請(qǐng)求「異步式」】- 不修改
- wsgi.py 【接收網(wǎng)絡(luò)請(qǐng)求「同步式」】- 不修改
1.5 APP的創(chuàng)建和說(shuō)明
1. APP 的例子
-
項(xiàng)目
- app,用戶(hù)管理 【表結(jié)構(gòu)、函數(shù)、HTML模板、CSS】
- app,訂單管理 【表結(jié)構(gòu)、函數(shù)、HTML模板、CSS】
- app,后臺(tái)管理 【表結(jié)構(gòu)、函數(shù)、HTML模板、CSS】
- app,網(wǎng)站 【表結(jié)構(gòu)、函數(shù)、HTML模板、CSS】
- app,API 【表結(jié)構(gòu)、函數(shù)、HTML模板、CSS】
- …
注意,我們開(kāi)發(fā)比較簡(jiǎn)潔,用不到多 APP ,通常情況下,項(xiàng)目創(chuàng)建一個(gè) APP 即可。
2. 創(chuàng)建 APP,在終端輸入:
python manage.py startapp app013. APP 默認(rèn)文件介紹
- app01
- __ init __.py
- admin.py【固定,不用動(dòng)】 django默認(rèn)提供了admin后臺(tái)管理
- apps.py 【固定,不用動(dòng)】 app啟動(dòng)類(lèi)
- migrations 【固定,不用動(dòng)】 數(shù)據(jù)庫(kù)字段變更記錄
- __ init __.py
- models.py 【重要】 對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作
- tests.py【固定,不用動(dòng)】 單元測(cè)試
- views.py 【重要】 函數(shù)
1.6 啟動(dòng)運(yùn)行django
1. 注冊(cè) app 【setting.py】
2. 編寫(xiě) URL 和視圖函數(shù)的對(duì)應(yīng)關(guān)系 【urls.py】
3. 編寫(xiě)視圖函數(shù) 【views.py】
4. 啟動(dòng) Django 項(xiàng)目
命令行啟動(dòng)
python manage.py runserver
1.7 模板和靜態(tài)文件
1. templates 模板
2. 靜態(tài)文件
在開(kāi)發(fā)過(guò)程中,一般將 「圖片、CSS、js」都會(huì)當(dāng)作靜態(tài)文件處理。
(1)在 app 目錄下創(chuàng)建static文件夾
(2)引用靜態(tài)文件
1.8 模板語(yǔ)法
1. 本質(zhì):在 HTML 中寫(xiě)一些占位符,由數(shù)據(jù)對(duì)這些占位符進(jìn)行替換和處理。
2. 案例:偽聯(lián)通新聞中心
(1)在 urls.py 創(chuàng)建函數(shù)的對(duì)應(yīng)關(guān)系
(2)在 views 中編寫(xiě)函數(shù)
(3)在 templates 的 news.html 編寫(xiě)模板語(yǔ)法
(4)頁(yè)面展示
1.9 請(qǐng)求和響應(yīng)
1.
2. 案例:用戶(hù)登錄
(1)發(fā)生如下錯(cuò)誤,只需要在 form 表單中偽造跨站請(qǐng)求 {% csrf_token %} 。
(2)最終代碼:
(3)效果展示
1.10 orm數(shù)據(jù)庫(kù)操作
ORM
- 創(chuàng)建、修改、刪除數(shù)據(jù)庫(kù)中的表;(不用寫(xiě)SQL語(yǔ)句)【無(wú)法創(chuàng)建數(shù)據(jù)庫(kù)】
- 操作表中的數(shù)據(jù)(不用寫(xiě)SQL語(yǔ)句)。
1. 安裝第三方庫(kù)
pip install mysqlclient==1.4.12. 創(chuàng)建數(shù)據(jù)庫(kù)
- 首先在終端啟動(dòng) mysql:
- 登錄 mysql(已經(jīng)將初始密碼設(shè)為 0 )
- 創(chuàng)建數(shù)據(jù)庫(kù)(其中 gx 是數(shù)據(jù)庫(kù)名稱(chēng)):
3. django 連接數(shù)據(jù)庫(kù)
在 settings.py 文件中進(jìn)行配置和修改。
更改默認(rèn) DATABASES :
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql', # 引擎'NAME': 'gx', # 數(shù)據(jù)庫(kù)名字'USER': 'root', # 用戶(hù)名'PASSWORD': '123456', # 密碼'HOST': '127.0.0.1', # 哪臺(tái)機(jī)器安裝了MySQL - 本機(jī)'PORT': '3306',} }4. django 創(chuàng)建表
(1)在 models.py 文件中:
等同于:
create table app01_userinfo(id bigint auto_increment primary key, # django自動(dòng)添加name varchar(32),password varchar(64),age int )(2)在 pycharm 終端輸入,注意, app 需要提前注冊(cè):
python manage.py makemigrations python manage.py migrate至此,表已經(jīng)創(chuàng)建成功。
5. django 修改表
(1) 刪除某個(gè)列:
- 注釋該列;
- 在 pycharm 終端輸入:
(2)添加某個(gè)列:
- 在 python 代碼中輸入該列;
- 在 pycharm 終端輸入:
(3)但是,對(duì)于 添加列 需要注意,由于已存在的列可能已有數(shù)據(jù),所以新增列必須要指定對(duì)應(yīng)的數(shù)據(jù):
- 選擇 1,手動(dòng)輸入一個(gè)值;
- 選擇 2,回到代碼設(shè)置默認(rèn)值;
- 允許為空;
總結(jié):對(duì)表結(jié)構(gòu)進(jìn)行調(diào)整
- 在 models.py 文件中進(jìn)行操作類(lèi);
- 輸入命令:
python manage.py makemigrations
python manage.py migrate
6. 操作表中的數(shù)據(jù)
1.11 ORM 數(shù)據(jù)庫(kù)案例:用戶(hù)管理
1. 展示用戶(hù)列表
- url;
- 函數(shù)
- 獲取所有用戶(hù)信息;
- HTML 渲染;
2. 添加用戶(hù)
- url;
- 函數(shù)
- GET,看到頁(yè)面,輸入內(nèi)容;
- POST,提交,寫(xiě)入到數(shù)據(jù)庫(kù)。
(1)在 urls.py 中添加 path:
(2)編寫(xiě)函數(shù) info_add :
(3)編寫(xiě) info_add.html ,注意要有 {% csrf_token %} ,使得跨站網(wǎng)址請(qǐng)求能夠成功。
(4)效果展示
3. 刪除用戶(hù)
- url;
- 函數(shù)
(1)在 urls.py 添加 path:
(2) 在 views.py 中編寫(xiě)相關(guān)代碼:
(3)結(jié)果展示:(當(dāng)然在 /info/list.html 中也做了修改)
2 案例
2.1 創(chuàng)建項(xiàng)目和 APP
在終端進(jìn)入項(xiàng)目的存儲(chǔ)路徑,然后創(chuàng)建項(xiàng)目:
E:\PycharmProjects>django-admin.exe startproject day16創(chuàng)建APP:
E:\PycharmProjects\day16>python manage.py startapp app01注冊(cè) APP ,修改 setting.py :
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01.apps.App01Config', ]2.2 表結(jié)構(gòu)的創(chuàng)建
models.py
from django.db import models# Create your models here.class Department(models.Model):"""部門(mén)表"""title = models.CharField(verbose_name='標(biāo)題', max_length=32)class UserInfo(models.Model):"""員工表"""name = models.CharField(verbose_name="姓名", max_length=16)password = models.CharField(verbose_name="密碼", max_length=64)age = models.IntegerField(verbose_name="年齡")account = models.DecimalField(verbose_name="賬戶(hù)余額", max_digits=10, decimal_places=2, default=0)create_time = models.DateTimeField(verbose_name="入職時(shí)間")# 1. 有約束# - to,與哪張表關(guān)聯(lián)# - to_field,表中的哪一列關(guān)聯(lián)# 2. django自動(dòng)# - 寫(xiě)的 depart# - 實(shí)際生成 depart_id# 3. 部門(mén)表被刪除# 3.1 級(jí)聯(lián)刪除depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)# 3.2 置空# depart = models.ForeignKey(to="Department", to_field="id", null=True, blank=True, on_delete=models.SET_NULL)gender_choices = ((1, "男"),(2, "女"),)gender = models.SmallIntegerField(verbose_name="性別", choices=gender_choices)2.3 生成數(shù)據(jù)庫(kù)
表結(jié)構(gòu)創(chuàng)建成功:
2.4 部門(mén)管理
depart_list.html
2.5 數(shù)據(jù)庫(kù)數(shù)據(jù)
views.py
from django.shortcuts import render from app01 import models # Create your views here.def depart_list(request):"""部門(mén)列表"""# 去數(shù)據(jù)庫(kù)中獲取所有部門(mén)列表# [對(duì)象, 對(duì)象, 對(duì)象]queryset = models.Department.objects.all()return render(request, 'depart_list.html', {'queryset': queryset})depart_list.html
<tbody>{% for obj in queryset %}<tr><td>{{ obj.id }}</td><td>{{ obj.title }}</td><td><a class="btn btn-primary btn-xs">編輯</a><a class="btn btn-danger btn-xs">刪除</a></td></tr>{% endfor %}</tbody>2.6 添加部門(mén)頁(yè)面
views.py
def depart_add(request):"""添加部門(mén)"""return render(request, 'depart_add.html')depart_list.html
<div style="margin-bottom: 10px"><a class="btn btn-success" href="/depart/add/" >新建部門(mén)</a> </div>depart_add.html
<div class="container"><div class="panel panel-default"><div class="panel-heading"><h3 class="panel-title">部門(mén)列表</h3></div><div class="panel-body"><form><div class="form-group"><label>標(biāo)題</label><input type="text" class="form-control" placeholder="標(biāo)題" name="title" /></div><div class="form-group"><div class="col-sm-offset-2 col-sm-10"><button type="submit" class="btn btn-primary">保 存</button></div></div></form></div></div>2.7 部門(mén):添加
views.py
# 導(dǎo)入redirect from django.shortcuts import render, redirect def depart_add(request):"""添加部門(mén)"""if request.method == "GET":return render(request, 'depart_add.html')# 獲取用戶(hù)POST提交過(guò)來(lái)的數(shù)據(jù)title = request.POST.get("title")# 保存到數(shù)據(jù)庫(kù)models.Department.objects.create(title=title)# 重定向到部門(mén)列表return redirect('/depart/list')depart_add.html
<div class="panel-body"><form method="post">{% csrf_token %}<div class="form-group"><label>標(biāo)題</label><input type="text" class="form-control" placeholder="標(biāo)題" name="title"/></div><div class="form-group"><button type="submit" class="btn btn-primary">提交</button></div></form>2.8 部門(mén):刪除
views.py
def depart_delete(request):"""刪除部門(mén)"""# 獲取IDnid = request.GET.get('nid')# 刪除models.Department.objects.filter(id=nid).delete()# 重定向回部門(mén)列表return redirect("/depart/list/")depart_list.html
<a class="btn btn-danger btn-xs" href="/depart/delete/?nid= {{ obj.id }}">刪除</a>2.9 部門(mén):編輯
urls.py
/< 正則表達(dá)式 >/
urlpatterns = [# http://127.0.0.1:8000/depart/1/edit/path('depart/<int:nid>/edit/', views.depart_edit), ]views.py
def depart_edit(request, nid):"""修改部門(mén)"""if(request.method == "GET"):# 根據(jù)nid 獲取它的數(shù)據(jù) [object,]row_object = models.Department.objects.filter(id=nid).first()return render(request, 'depart_edit.html', {"title": row_object.title})# 獲取用戶(hù)提交的數(shù)據(jù)title = request.POST.get("title")# 更新數(shù)據(jù)models.Department.objects.filter(id=nid).update(title=title)# 重定向回部門(mén)列表界面return redirect("/depart/list/")depart_edit.html
<input type="text" class="form-control" placeholder="標(biāo)題" name="title" value="{{ title }}"/>2.10 模板繼承
layout.html
{% load static %} <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}"> </head> <body> <div>{% block content %}{% endblock%} </div> <script src="{% static 'jquery/jquery.min.js' %}"></script> <script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script> </body> </html>children.html
{% extends 'layout.html' %}{% block content %}<!--新增內(nèi)容-->{% endblock %}當(dāng)然, 也可以定義多個(gè)模板:
layout.html
{% load static %} <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title>{% block css %}{% endblock%} </head> <body> <div>{% block content %}{% endblock%} </div>{% block js %}{% endblock%} </body> </html>children.html
{% extends 'layout.html' %}{% block css %}<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}"> {% endblock%}{% block content %} <!--新增內(nèi)容--> {% endblock %}{% block js %}<script src="{% static 'jquery/jquery.min.js' %}"></script> {% endblock%}2.11 用戶(hù)管理:列表
urls.py
path('user/list/', views.user_list),views.py
def user_list(request):"""用戶(hù)管理"""# 獲取所有用戶(hù)信息queryset = models.UserInfo.objects.all()# python 寫(xiě)法# for obj in queryset:# id = obj.id# name = obj.name# password = obj.password# age = obj.age# account = obj.account# create_time = obj.create_time.strftime("%Y-%m-%d")# gender = obj.get_gender_display()# title = obj.depart.title # 根據(jù)id自動(dòng)去關(guān)聯(lián)的表中獲取哪一行的數(shù)據(jù)depart對(duì)象return render(request, 'user_list.html', {"queryset": queryset})效果展示
2.12 用戶(hù)管理:添加
1. 思路
-
原始方法:比較復(fù)雜,因此最終不采用;
缺點(diǎn)
- 用戶(hù)提交數(shù)據(jù)沒(méi)有校驗(yàn);
- 發(fā)生錯(cuò)誤的時(shí)候,頁(yè)面沒(méi)有錯(cuò)誤提示;
- 頁(yè)面上,每一個(gè)字段都需要我們重新寫(xiě)一遍;
- 關(guān)聯(lián)數(shù)據(jù)需要手動(dòng)獲取并通過(guò)循環(huán)才能展示在頁(yè)面。
-
Django 組件
- Form 組件 【簡(jiǎn)便】
- ModelForm 組件 【最簡(jiǎn)便】【最推薦】
2. 原始方法
views.py
def user_add(request):"""添加用戶(hù)"""if request.method == "GET":context = {'gender_choices': models.UserInfo.gender_choices,'depart_list': models.Department.objects.all()}return render(request, 'user_add.html', context)# 獲取用戶(hù)提交的數(shù)據(jù)user = request.POST.get('user')pwd = request.POST.get('pwd')age = request.POST.get('age')account = request.POST.get('ac')ctime = request.POST.get('ctime')gender = request.POST.get('gd')depart_id = request.POST.get('dp')# 添加到數(shù)據(jù)庫(kù)中models.UserInfo.objects.create(name=user, password=pwd, age=age,account=account, create_time=ctime,gender=gender, depart_id=depart_id)# 返回到用戶(hù)列表界面return redirect("/user/list")user_add.html
<div class="container"><div class="panel panel-default"><div class="panel-heading"><h3 class="panel-title">用戶(hù)列表</h3></div><div class="panel-body"><form method="post">{% csrf_token %}<div class="form-group"><label>姓名</label><input type="text" class="form-control" placeholder="姓名" name="user"/></div><div class="form-group"><label>密碼</label><input type="text" class="form-control" placeholder="密碼" name="pwd"/></div><div class="form-group"><label>年齡</label><input type="text" class="form-control" placeholder="年齡" name="age"/></div><div class="form-group"><label>余額</label><input type="text" class="form-control" placeholder="余額" name="ac"/></div><div class="form-group"><label>入職時(shí)間</label><input type="text" class="form-control" placeholder="入職時(shí)間" name="ctime"/></div><div class="form-group"><label>性別</label><select class="form-control" name="gd">{% for gender in gender_choices %}<option value="{{ gender.0 }}">{{ gender.1 }}</option>{% endfor %}</select></div><div class="form-group"><label>部門(mén)</label><select class="form-control" name="dp">{% for item in depart_list %}<option value="{{ item.id }}">{{ item.title }}</option>{% endfor %}</select></div><div class="form-group"><button type="submit" class="btn btn-primary">提交</button></div></form></div></div> </div>3.Form
views.py
class MyForm(Form):user = forms.CharField(wiget=forms.Input)pwd = form.CharField(wiget=forms.Input)age= form.CharField(wiget=forms.Input)account = form.CharField(wiget=forms.Input)create_time = form.CharField(wiget=forms.Input)gender = form.CharField(wiget=forms.Input)depart_id = form.CharField(wiget=forms.Input)def user_add(request):form = MyForm() # 實(shí)例化return render(request, 'user_add.html', {"form": form})user_add.html
form.user 相當(dāng)于 input user
<form method="post">{{ form.user }}{{ form.pwd }} <!--<input type="text" class="form-control" placeholder="姓名" name="user"/>--></form>進(jìn)一步優(yōu)化,使用循環(huán):
<form method="post">{ for field in form %}{{ field }}{% endfor %} </form>4. ModelForm
models.py
class UserInfo(models.Model):"""員工表"""name = models.CharField(verbose_name="姓名", max_length=16)password = models.CharField(verbose_name="密碼", max_length=64)age = models.IntegerField(verbose_name="年齡")account = models.DecimalField(verbose_name="賬戶(hù)余額", max_digits=10, decimal_places=2, default=0)create_time = models.DateTimeField(verbose_name="入職時(shí)間")depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)gender_choices = ((1, "男"),(2, "女"),)gender = models.SmallIntegerField(verbose_name="性別", choices=gender_choices)views.py
class MyForm(ModelForm):class Meta:model = UserInfofields = ["name", "password", "age"] def user_add(request):form = MyForm() # 實(shí)例化return render(request, 'user_add.html', {"form": form})user_add.html
form.user 相當(dāng)于 input user
<form method="post">{{ form.user }}{{ form.pwd }} <!--<input type="text" class="form-control" placeholder="姓名" name="user"/>--></form>進(jìn)一步優(yōu)化,使用循環(huán):
<form method="post">{ for field in form %}{{ field }}{% endfor %} </form>5. 使用 ModelForm 添加用戶(hù)
views.py
from django import formsclass UserModelForm(forms.ModelForm):class Meta:model = models.UserInfofields = ["name", "password", "age", "account", "create_time", "depart", "gender"]def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)# 循環(huán)找到所有插件,添加class="form-control"for name, field in self.fields.items():field.widget.attrs = {"class": "form-control", "placeholder": field.label}def user_model_form_add(request):"""添加用戶(hù) ModelForm版本"""form = UserModelForm()return render(request, 'user_model_form_add.html', {"form": form})models.py
重寫(xiě)字段,保證 depart 作為用戶(hù)列表的外鍵能夠以字符形式顯示。
class Department(models.Model):"""部門(mén)表"""title = models.CharField(verbose_name='標(biāo)題', max_length=32)def __str__(self):return self.titleuser_model_form_add.html
{% extends 'layout.html' %}{% block content %} <div class="container"><div class="panel panel-default"><div class="panel-heading"><h3 class="panel-title">用戶(hù)列表</h3></div><div class="panel-body"><form method="post">{% csrf_token %}{% for field in form %}<div class="form-group"><label>{{ field.label }}</label>{{ field }}</div>{% endfor %}<div class="form-group"><button type="submit" class="btn btn-primary">提交</button></div></form></div></div> </div> {% endblock %}效果圖
6. 添加的錯(cuò)誤提示
views.py
重寫(xiě)字段 name ,用于數(shù)據(jù)驗(yàn)證(name 字段至少為 3 個(gè)字符),
name = forms.CharField(min_length=3, label="用戶(hù)名"):
user_model_form_add.html
注意,網(wǎng)頁(yè)自帶的驗(yàn)證先取消 novalidate ,方便展示我們代碼實(shí)現(xiàn)數(shù)據(jù)驗(yàn)證的效果。
field.errors.0 顯示當(dāng)前的第一個(gè)錯(cuò)誤。
效果圖:
2.13 用戶(hù)管理:編輯
- 點(diǎn)擊編輯, 跳轉(zhuǎn)到編輯界面(將編輯行的 ID 攜帶過(guò)去);
- 編輯頁(yè)面(默認(rèn)數(shù)據(jù),根據(jù)ID獲取并設(shè)置到頁(yè)面中)
- 提交
- 錯(cuò)誤提示
- 數(shù)據(jù)校驗(yàn)
- 數(shù)據(jù)庫(kù)更新
user_list.html
<a class="btn btn-primary btn-xs" href="/user/{{ obj.id }}/edit/">編輯</a>urls.py
編輯用戶(hù)需要獲取用戶(hù)的id
views.py
def user_edit(request, nid):"""編輯用戶(hù)"""# 根據(jù)id去數(shù)據(jù)庫(kù)獲取編輯行的數(shù)據(jù)row_object = models.UserInfo.objects.filter(id=nid).first()if request.method == "GET":# 加入instance參數(shù),原有的值會(huì)顯示在輸入框form = UserModelForm(instance=row_object)return render(request, 'user_edit.html', {'form': form})form = UserModelForm(data=request.POST, instance=row_object)if form.is_valid():form.save()return redirect('/user/list/')return render(request, 'user_edit.html', {"form":form})效果圖
2.14 用戶(hù)管理:刪除
user_list.html
修改刪除標(biāo)簽
<a class="btn btn-danger btn-xs" href="/user/{{ obj.id }}/delete/">刪除</a>urls.py
path('user/<int:nid>/delete/', views.user_delete)views.py
def user_delete(request, nid):models.UserInfo.objects.filter(id=nid).delete()return redirect('/user/list/')3 案例:靚號(hào)管理
3.1 表結(jié)構(gòu)
class PrettyNum(models.Model):"""靚號(hào)表"""mobile = models.CharField(verbose_name="手機(jī)號(hào)", max_length=11)# 想要允許為空 null=True, blank=Trueprice = models.IntegerField(verbose_name="價(jià)格", default=0)level_choices = ((1, "1級(jí)"),(2, "2級(jí)"),(3, "3級(jí)"),(4, "4級(jí)"),)level = models.SmallIntegerField(verbose_name="級(jí)別", choices=level_choices, default=1)status_choices = ((1, "已占用"),(2, "未使用"),)status = models.SmallIntegerField(verbose_name="狀態(tài)", choices=status_choices, default=2)3.2 靚號(hào)列表
- URL;
- 函數(shù)
- 獲取所有靚號(hào);
- 結(jié)合 html + render 將所有靚號(hào)展現(xiàn)出來(lái);
layout.html
<li><a href="/pretty/list/">靚號(hào)管理</a></li>urls.py
path('pretty/list/', views.pretty_list),views.py
def pretty_list(request):"""靚號(hào)管理"""# order_by :降序queryset = models.PrettyNum.objects.all().order_by("-level")return render(request, 'pretty_list.html', {'queryset': queryset})pretty.html
{% extends 'layout.html' %} {% block content %}<div class="container"><div style="margin-bottom: 10px"><a class="btn btn-success" href="#">新建靚號(hào)</a></div><div class="panel panel-default"><div class="panel-heading"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>用戶(hù)列表</div><table class="table table-bordered"><thead><tr><th>ID</th><th>手機(jī)號(hào)</th><th>價(jià)格</th><th>級(jí)別</th><th>狀態(tài)</th><th>操作</th></tr></thead><tbody>{% for obj in queryset %}<tr><td>{{ obj.id }}</td><td>{{ obj.mobile }}</td><td>{{ obj.price }}</td><td>{{ obj.get_level_display }}</td><td>{{ obj.get_status_display }}</td><td><a class="btn btn-primary btn-xs" href="#">編輯</a><a class="btn btn-danger btn-xs" href="#">刪除</a></td></tr>{% endfor %}</tbody></table></div></div> {% endblock %}3.3 新建靚號(hào)
- 列表點(diǎn)擊跳轉(zhuǎn):/pretty/add/
- URL
- ModelForm 類(lèi)
- 函數(shù)
- 實(shí)例化類(lèi)對(duì)象;
- 通過(guò) render 將對(duì)象傳入到 HTML 中;
- 模板循環(huán)展示所有對(duì)象;
- 點(diǎn)擊提交
- 數(shù)據(jù)校驗(yàn); 【兩種方法】
- 保存到數(shù)據(jù)庫(kù);
- 跳轉(zhuǎn)回靚號(hào)列表;
urls.py
path('pretty/add/', views.pretty_add),views.py
from django.core.validators import RegexValidator from django.core.validators import ValidationError class PrettyModelForm(forms.ModelForm):# 驗(yàn)證:方式1 字段+正則# mobile = forms.CharField(# label="手機(jī)號(hào)",# validators=[RegexValidator(r'^1[3-9]\d{9}$', '手機(jī)號(hào)格式錯(cuò)誤')],# )class Meta:model = models.PrettyNum# fields = ["mobile", "price", "level", "status"]fields = "__all__"# exclude = ['level']def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)for name, field in self.fields.items():field.widget.attrs = {"class": "form-control", "placeholder": field.label}# 驗(yàn)證:方式2 鉤子方法 def clean_mobile(self):txt_mobile = self.cleaned_data['mobile']if len(txt_mobile) != 11:# 驗(yàn)證不通過(guò)raise ValidationError("格式錯(cuò)誤")# 驗(yàn)證通過(guò)return txt_mobile def pretty_add(request):"""添加靚號(hào)"""if request.method == "GET":form = PrettyModelForm()return render(request, 'pretty_add.html', {'form': form})# POST提交數(shù)據(jù),數(shù)據(jù)校驗(yàn)form = PrettyModelForm(data=request.POST)if form.is_valid():form.save()return redirect('/pretty/list/')# 校驗(yàn)失敗else:return render(request, 'pretty_add.html', {'form': form})pretty_list.html
<a class="btn btn-success" href="/pretty/add/">新建靚號(hào)</a>pretty_add.html
效果圖
數(shù)據(jù)校驗(yàn)的補(bǔ)充:數(shù)據(jù)庫(kù)的手機(jī)號(hào)需要唯一
使用正則表達(dá)式判斷 「手機(jī)號(hào)是否已經(jīng)存在」
# True/False exists = models.PrettyNum.objects.ilter(mobile="100000000").exists()效果圖:
views.py
3.4 編輯靚號(hào)
urls.py
path('pretty/<int:nid>/edit/', views.pretty_edit),views.py
class PrettyEditModeleForm(forms.ModelForm):# disabled參數(shù),該字段不可以編輯# mobile = forms.CharField(disabled=True, label="手機(jī)號(hào)")class Meta:model = models.PrettyNum#fields = ["price", "level", "status"]fields = "__all__"def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)for name, field in self.fields.items():field.widget.attrs = {"class": "form-control", "placeholder": field.label}# 驗(yàn)證:方式2def clean_mobile(self):# 當(dāng)前編輯行的id# self.instance.pktxt_mobile = self.cleaned_data['mobile']# 手機(jī)號(hào)是否唯一的判斷exists = models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()if exists:raise ValidationError("手機(jī)號(hào)已存在")if len(txt_mobile) != 11:# 驗(yàn)證不通過(guò)raise ValidationError("格式錯(cuò)誤")# 驗(yàn)證通過(guò)return txt_mobile def pretty_edit(request, nid):"""編輯靚號(hào)"""# 根據(jù)id去數(shù)據(jù)庫(kù)獲取編輯行的數(shù)據(jù)row_object = models.PrettyNum.objects.filter(id=nid).first()if request.method == "GET":form = PrettyEditModeleForm(instance=row_object)return render(request, 'pretty_edit.html', {'form': form})form = PrettyEditModeleForm(data=request.POST, instance=row_object)if form.is_valid():form.save()return redirect('/pretty/list/')return render(request, 'pretty_edit.html', {'form': form})pretty_list.html
<a class="btn btn-primary btn-xs" href="/pretty/{{ obj.id }}/edit/">編輯</a>pretty_edit.html
{% extends 'layout.html' %} {% block content %}<div class="container"><div class="panel panel-default"><div class="panel-heading"><h3 class="panel-title">編輯靚號(hào)</h3></div><div class="panel-body"><form method="post" novalidate>{% csrf_token %}{% for field in form %}<div class="form-group"><label>{{ field.label }}</label>{{ field }}<span style="color: red">{{ field.errors.0 }}</span></div>{% endfor %}<div class="form-group"><button type="submit" class="btn btn-primary">提交</button></div></form></div></div> </div>{% endblock %}效果圖
數(shù)據(jù)校驗(yàn):確保手機(jī)號(hào)的唯一性。
這和新建靚號(hào)中的校驗(yàn)不太一樣。新建靚號(hào)的時(shí)候,對(duì)于新輸入的手機(jī)號(hào),是和數(shù)據(jù)庫(kù)中的手機(jī)號(hào)相比判斷的。
編輯靚號(hào)中,如果你更改的是手機(jī)號(hào)除外的信息,此時(shí)也沒(méi)辦法通過(guò),因?yàn)槟憔庉嫼筇峤坏氖謾C(jī)號(hào)在數(shù)據(jù)庫(kù)中已經(jīng)存在了,因此在進(jìn)行校驗(yàn)的時(shí)候需要排除自身的手機(jī)號(hào)再判斷唯一性。
views.py
txt_mobile = self.cleaned_data['mobile']# 當(dāng)前編輯行的id # self.instance.pk exists = models.PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()if exists:raise ValidationError("手機(jī)號(hào)已存在")效果圖,編輯當(dāng)前手機(jī)號(hào)的級(jí)別:
3.5 刪除靚號(hào)
pretty_list.html
修改刪除標(biāo)簽
<a class="btn btn-danger btn-xs" href="/pretty/{{ obj.id }}/delete/">刪除</a>urls.py
path('pretty/<int:nid>/delete/', views.pretty_delete),views.py
def pretty_delete(request, nid):models.PrettyNum.objects.filter(id=nid).delete()return redirect('/pretty/list/')3.6 靚號(hào)管理:手機(jī)號(hào)搜索
數(shù)據(jù)庫(kù)搜索相關(guān)知識(shí)補(bǔ)充
models.PrettyNum.objects.filter(mobile="12345678920", id=5)# 以字典方式傳入 必須要加 ** data_list = {"mobile": "12345678920", "id": 5} models.PrettyNum.objects.filter(**data_list) models.PrettyNum.objects.filter(id=5) # 等于5 models.PrettyNum.objects.filter(id__gt=5) # 大于5 models.PrettyNum.objects.filter(id__gte=5) # 大于等于5 models.PrettyNum.objects.filter(id__lt=5) # 小于5 models.PrettyNum.objects.filter(id__lte=5) # 小于等于5 models.PrettyNum.objects.filter(mobile="123") # 等于 models.PrettyNum.objects.filter(mobile__startswith="123") # 以123開(kāi)頭 models.PrettyNum.objects.filter(mobile__endswith="123") # 以123結(jié)尾 models.PrettyNum.objects.filter(mobile__contains="123") # 包含123手機(jī)號(hào)搜索實(shí)現(xiàn)
本質(zhì):
在用戶(hù)列表界面增加一個(gè)輸入框,用來(lái)輸入查詢(xún)的手機(jī)號(hào)。
我們希望進(jìn)行搜索時(shí),條件會(huì)包含在網(wǎng)址里,即網(wǎng)址是 http://127.0.0.1:8000/pretty/list/?q=456 ,那么需要通過(guò) get 方式提交,即 <form method="get"> 。那么后端會(huì)通過(guò) request.GET.get 獲取到 name="q" 的輸入,將其放入字典 data_list ,作為數(shù)據(jù)庫(kù)搜索的條件 filter(**data_list) 。
要想讓輸入框能夠顯示查詢(xún)的手機(jī)號(hào),需要把輸入值 search_data 傳入前端,放在<input> 標(biāo)簽的 value 字段。
views.py
def pretty_list(request):"""靚號(hào)管理"""data_list = {}search_data = request.GET.get('q', "")if search_data:data_list["mobile__contains"] = search_dataqueryset = models.PrettyNum.objects.filter(**data_list).order_by("-level")return render(request, 'pretty_list.html', {'queryset': queryset, "search_data": search_data})pretty_list.html
<div style="margin-bottom: 10px" class="clearfix"><a class="btn btn-success" href="/pretty/add/">新建靚號(hào)</a><div style="float: right; width:300px"><form method="get"><div class="input-group"><input type="text" name="q" class="form-control" placeholder="Search for..."value="{{ search_data }}"><span class="input-group-btn"><button class="btn btn-default" type="submit"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button></span></div><!-- /input-group --></form></div></div>效果圖:
3.7 靚號(hào)管理:分頁(yè)
pagination.py
""" 自定義分頁(yè)組件 如果以后想要使用這個(gè)分頁(yè)組件,需要做如下幾件事:在視圖函數(shù)中:def pretty_list(request):# 1. 根據(jù)自己的情況去篩選數(shù)據(jù)queryset = models.PrettyNum.objects.filter(**data_list).order_by("-level")# 2. 實(shí)例化分頁(yè)對(duì)象page_objects = Pagination(request, queryset) # 封裝成組件context = {'search_data': search_data,'queryset': page_objects.page_queryset, # 分完頁(yè)的數(shù)據(jù)"page_string": page_objects.html() # 生成的頁(yè)碼}return render(request, 'pretty_list.html', context)# 在HTML中:{% for obj in queryset %}{{ obj.xx }}{% endfor %}<ul class="pagination">{{ page_string }}</ul> """ from django.utils.safestring import mark_safeclass Pagination(object):def __init__(self, request, queryset, page_size=10, page_param="page", plus=5):""":param request: 請(qǐng)求的對(duì)象:param queryset: 符合條件的數(shù)據(jù) (根據(jù)這個(gè)數(shù)據(jù)給他進(jìn)行分頁(yè)處理):param page_size: 每頁(yè)顯示多少條數(shù)據(jù):param page_param: 在URL中傳遞的獲取分頁(yè)的參數(shù) 例如:pretty/list/?page=1:param plus: 顯示當(dāng)前頁(yè)的前后幾頁(yè)(頁(yè)碼)"""import copyquery_dict = copy.deepcopy(request.GET)query_dict.mutable = Trueself.query_dict = query_dictself.page_param = page_parampage = int(request.GET.get(page_param, "1"))self.page = pageself.page_size = page_sizeself.start = (page - 1) * page_sizeself.end = page * page_sizeself.page_queryset = queryset[self.start:self.end]total_count = queryset.count()# 總頁(yè)碼數(shù)total_page_count, div = divmod(total_count, page_size)if div:total_page_count += 1self.total_page_count = total_page_countself.plus = plusdef html(self):# 計(jì)算當(dāng)前頁(yè)的前5頁(yè)與后5頁(yè)if self.total_page_count <= 2 * self.plus + 1:start_page = 1end_page = self.total_page_count + 1else:if self.page <= self.plus:start_page = 1end_page = 2 * self.plus + 1else:if (self.page + self.plus) > self.total_page_count:start_page = self.total_page_count - 2 * self.plusend_page = self.total_page_countelse:start_page = self.page - self.plusend_page = self.page + self.pluspage_str_list = []# 首頁(yè)self.query_dict.setlist(self.page_param, [1])page_str_list.append('<li><a href="?{}">首頁(yè)</a></li>'.format(self.query_dict.urlencode()))# 上一頁(yè)if self.page > 1:self.query_dict.setlist(self.page_param, [self.page - 1])prev = '<li><a href="?{}">上一頁(yè)</a></li>'.format(self.query_dict.urlencode())else:self.query_dict.setlist(self.page_param, [1])prev = '<li><a href="?{}">上一頁(yè)</a></li>'.format(self.query_dict.urlencode())page_str_list.append(prev)# 生成頁(yè)碼for i in range(start_page, end_page):self.query_dict.setlist(self.page_param, [i])if i == self.page:ele = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)else:ele = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)page_str_list.append(ele)# 下一頁(yè)if self.page < self.total_page_count:self.query_dict.setlist(self.page_param, [self.page + 1])prev = '<li><a href="?{}">下一頁(yè)</a></li>'.format(self.query_dict.urlencode())else:self.query_dict.setlist(self.page_param, [self.total_page_count])prev = '<li><a href="?{}">下一頁(yè)</a></li>'.format(self.query_dict.urlencode())page_str_list.append(prev)# 尾頁(yè)self.query_dict.setlist(self.page_param, [self.total_page_count])page_str_list.append('<li><a href="?{}">尾頁(yè)</a></li>'.format(self.query_dict.urlencode()))page_string = mark_safe("".join(page_str_list))return page_stringviews.py
from app01.utils.pagination import Paginationdef pretty_list(request):"""靚號(hào)管理"""data_list = {}search_data = request.GET.get('q', "")if search_data:data_list["mobile__contains"] = search_dataqueryset = models.PrettyNum.objects.filter(**data_list).order_by("-level")page_objects = Pagination(request, queryset) # 封裝成組件context = {'search_data': search_data,'queryset': page_objects.page_queryset, # 分完頁(yè)的數(shù)據(jù)"page_string": page_objects.html() # 生成的頁(yè)碼}return render(request, 'pretty_list.html', context)pretty_list.html
<div class="clearfix"><ul class="pagination">{{page_string}}<li><form method="get"><div class="input-group" style="width: 200px"><input type="text" name="page" class="form-control" placeholder="頁(yè)碼"><span class="input-group-btn"><button class="btn btn-default" type="submit">跳轉(zhuǎn)</button></span></div></form></li></ul></div>視頻3-10還有一半未看。
4 時(shí)間選擇組件
引入 bootstrap-datepicker
{% block css %}<link rel="stylesheet" href="{% static '/plugins/bootstrap-datepicker-master/dist/css/bootstrap-datepicker.min.css' %}"> {% endblock %} {% block js %}<script src="{% static '/plugins/bootstrap-datepicker-master/dist/js/bootstrap-datepicker.min.js' %}"></script><script src="{% static '/plugins/bootstrap-datepicker-master/dist/locales/bootstrap-datepicker.zh-CN.min.js' %}"></script> {% endblock %}user_add.html 時(shí)間函數(shù) ,其中 #dt 對(duì)應(yīng)入職時(shí)間的ID
<input type="text" id="dt" class="form-control" placeholder="入職時(shí)間" name="ctime"/> <script>$(function() {$('#dt').datepicker({format: 'yyyy-mm-dd',startDate: '0',language: "zh-CN",autoclose: true})})</script>user_model_form_add.html 時(shí)間函數(shù) ,modelform中的ID默認(rèn)為 ID_字段名,即 #id_create_time
<script>$(function() {$('#id_create_time').datepicker({format: 'yyyy-mm-dd',startDate: '0',language: "zh-CN",autoclose: true})})</script>5 BootStrap 樣式父類(lèi)
重復(fù)的內(nèi)容可以集成為父類(lèi), 比如樣式設(shè)置:
from django import formsclass BootStrapModelForm(forms.ModelForm):def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)# 循環(huán)找到所有插件,添加class="form-control"for name, field in self.fields.items():# 字段中有屬性,保留原有屬性,沒(méi)有屬性,才增加if field.widget.attrs:field.widget.attrs["class"] = "form-control"field.widget.attrs["placeholder"] = field.labelelse:field.widget.attrs = {"class": "form-control","placeholder": field.label}之后,所有涉及到樣式設(shè)置的 ModelForm 可以直接繼承 BootStrap ,比如:
class UserModelForm(BootStrapModelForm):6 views 函數(shù)拆分
由于已經(jīng)實(shí)現(xiàn)了許多功能,原本的 views 函數(shù)顯得復(fù)雜,此時(shí)可以新建一個(gè) views 目錄,將各個(gè)功能拆分成若干個(gè) .py 文件。
注意,原本的 views.py 需要?jiǎng)h除。
urls.py 也需要修改。
注意, models.py 函數(shù)不能像這樣拆分。
7 案例:管理員
7.1
參考資料:
總結(jié)
以上是生活随笔為你收集整理的【前端开发学习】7.Django的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 智能移动终端信息安全风险现状与展望
- 下一篇: html音乐播放器标签,打造属于自己的音