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