安装django
pip3 install django
删除django
pip3 uninstall django
创建django项目
# django-admin startproject 创建的项目名 django-admin startproject mywebsite
运行django项目
# 运行时需要进入到django目录 python manage.py runserver
创建django-app(即django应用)
# python manage.py startapp 应用名称 python manage.py startapp news
注册django-app
# 在项目下的settings文件中进行注册 # 在INSTALLED_APPS中增加需要注册的应用名,如上news
修改django界面默认语言为中文
# 在项目下的settings文件中进行设置 # LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'zh-hans'
创建django后台管理员用户与密码
python manage.py createsuperuser
MVT
M——models
主要封装数据库,对数据库进行访问,对数据进行增删改查。
V——views
进行业务逻辑处理
T——templates
主要进行展示
URL
url标准语法
protocol://hostname[:port]/path/[:parameters][?query]#fragment
- protocol:协议,如http、https、ftp、mailto、ldap、file、news、telnet
- hostname:ip地址
- port:端口
- path:路径
- parameters:参数
- query:查询
- fragment:锚点
Path
path()标准语法
path(<route>, <view>, [name=None], [**kwargs])
- route:表示路径,从端口以后的URL地址,到/结束
- view:表示route匹配成功后,需要调用的视图,view必须是个函数,如果class必须使用as_view()转换为函数
- name:表示视图的别名
- **kwags:以字典形式传递的参数
路径转换器
path('AlexLu/Eva/<html>', views.web, name='web'), # 其中<html>为传递给函数views.web的参数
- str —— 用法:
<str:html>
匹配一个非空字符及,除去 ’/‘ ,默认使用的是这种方式 - int ——
<int:html>
匹配0或正整数 - slug ——
<slug:html>
由ASCII字母或数字组成,通过 ’-‘ 链接的字符串 - uuid ——
<uuid:html>
uuid格式的字符串 - path ——
<path:html>
匹配一个非空字符串,包括 ’/‘
path('index/<str:html>', views.index, name='index'), path('index/<path:home>', views.home, name='home'), path('page/<int:page>', views.page, name='page'), path('index/<int:numa>/<int:numb>', views.sum, name='sum'), path('slug/<slug:slugstr>', views.slugstr, name='slugstr'), path('uuid/<uuid:uuid>', views.uuid, name='uuid'), # --------------------------------------------------------------------- def index(request, html): return HttpResponse(html) def home(request, home): return HttpResponse('<h1>{}</h1>'.format(home)) def page(request, page): return HttpResponse('<h1>{}</h1>'.format(page)) def sum(request, numa, numb): return HttpResponse('<h1>{}</h1>'.format(numa+numb)) def slugstr(request, slugstr): return HttpResponse('<h1>{}</h1>'.format(slugstr)) def uuid(request, uuid): return HttpResponse('<h1 >{}</h1>'.format(uuid))
include
include的三种语法
1. module
- include(module, namespace=None)
2. namespace
- include(pattern_list)
3. pattern_list
- include((pattern_list, app_namespace), namespace=None)
include用法说明
- module —— 表示一个模块(模型)文件
- namespace —— 实例命名空间
- pattern_list —— 必须是一个可迭代的path()或re_path()清单
- app_namespace —— app命名空间
URL地址重定向
redirect(to, permanent=False, *args, **kwargs)
- to —— 指需要重新定位的位置,这个位置可以是一个视图,可以是一个url地址,也可以是一个模块
- permanent —— 默认为False,用来表示是否永久重定向
Reverse
reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
HTTP
HttpResponse
HttpResponse(content, content_type=None, status=None, charset=None, reason=None *args, **kwargs)
- content —— 返回给视图函数的内容
- content_type —— 返回给视图函数的类型
- text/html —— HTML文本字符串
- text/plain —— 纯文本
- text/css
- text/javascript
- application/xml —— xml文本
- application/json —— json文本
- multipart/form-data —— 上传文本
- status —— Http响应代码
- 200 —— 表示成功
- 404 —— 页面找不到
- charset —— 字符编码设置
常见的几种错误视图代码
- 404 page not found
- 找不到相应的页面
- 500 server error
- 服务器错误
- 400 bad request
- 无效的请求
- 403 HTTP forbidden
- HTTP禁止访问,权限不足
- 200 OK
- 请求成功
Http请求方式
- 介绍 —— HTTP 协议定义一些方法,以指明为获取客户端(如您的浏览器或我们的 CheckUpDown 机器人)所指定的具体网址资源而需要在 Web 服务器上执行的动作。则这些方法如下:
- OPTIONS( 选项 ) :查找适用于一个特定网址资源的通讯选择。 在不需执行具体的涉及数据传输的动作情况下, 允许客户端来确定与资源相关的选项以及 / 或者要求, 或是一个服务器的性能。
- GET( 获取 ) :检索由网址资源所确定的信息,如获取一个特定的网页或图片。这是最常用的方法。
- HEAD( 头 ) :除了服务器只反馈标头信息而不是网址资源所确定的信息本身外, 基本同于 GET ( 获取 ) 。 可用于获取一个请求所要求的响应实体的元信息 ( metainformation) ,而不需传输响应实体本身。 经常用来测试超文本链接的有效性, 可达性, 和最近的修改。
- POST( 投寄 ) :将数据提交到 Web 服务器,如 1 )在电子公告板,新闻组中,或向 邮件名单发送信息, 2 )提供输入数据 - 通常由一个公共网关接口(CGI) 表, 到 一个数据处理进程, 3 )直接将记录添加到一个数据库中。
- PUT( 放置 ) :将一个具体网址的数据设置( 置入 / 替换)成客户提交的新数据。例如,将新的网页上载给服务器。
- DELETE( 删除 ) :删除与网址资源相关的数据。例如,删除网页。
- TRACE( 跟踪 ) :运行请求信息的一个远程应用层回送。 实际上是一个 'ping', 用以测试 Web 服务器正在从客户端接收什么数据。
- CONNECT( 连接 ) :保留以便通过代理服务器和隧道一起使用(如 SSL )。这种方法只在 HTTP 1.1 版中定义, 而在先前的 1.0 版中却没有。
允许的HTTP请求方式——装饰器
限定http请求方式
require_http_methods([Mthods_list])
- Mthods_list为请求方式列表,如:[‘GET’, ‘POST’]
require_GET()
- 只允许使用get方式进行请求
require_POST()
- 只允许使用post方式进行请求
require_safe()
- 只允许使用get方法和head方法的装饰器
Render
标准语法:
render(<request>, <template_name>, context=None, content_type=None, status=None, using=None)
必选参数
- request —— 生成HttpRequest对象
- template_name —— 指定需要渲染的模板名称
可选参数
- context —— 上下文,必须是一个字典。在HTML文件中使用字典的Key,通过Key展示对应的value
- content_type —— 指定上下文类型
- status —— 响应状态码
- using —— 用于加载模板的引擎名称
- Django templates language
- jinjia2
过滤器
first
- 返回列表list的第一个值
last
- 返回列表list的最后一个值
length
- 返回变量值的长度,可以用于字符串、列表
linebrakebr
- 将纯文本文件中的换行转换为HTML中的换行符
linenumbers
- 显示行号
ljust
- 左对齐
rjust
- 右对齐
lower
- 全部小写
upper
- 全部大写
title
- 将首字母全部大写
wordcount
- 统计单词的数量
mysql
# 检查是否安装mysql ps -aux | grep 'mysql' # 安装服务端 sudo apt-get install mysql-server # 安装客户端 sudo apt-get install mysql-client # 启动服务 sudo service mysql start # 停止服务 sudo service mysql stop # 重启服务 sudo service mysql restart # 进入数据库 sudo mysql -uroot -p
- 取消mysql连接限制问题,否则每次进入数据库都需要在前面加上sudo
# 进入管理员模式 alexlu@alexlu-Ubuntu:~$ sudo su # 进入MySQL root@alexlu-Ubuntu:/home/alexlu# mysql # 查看用户权限 mysql> select user,plugin from mysql.user; # 更新root用户密码(此处密码设为‘root’) mysql> update mysql.user set authentication_string=PASSWORD('root'),plugin='mysql_native_password'; # 刷新设置 mysql> flush privileges; # 退出MySQL与root用户 mysql> exit; root@alexlu-Ubuntu:/home/alexlu# exit # 重启数据库服务 alexlu@alexlu-Ubuntu:~$ sudo service mysql restart # 尝试重新登陆(前面不加sudo) alexlu@alexlu-Ubuntu:~$ mysql -uroot -proot
数据库的创建与删除
# 展示当前数据库: mysql> show databases; # 创建数据库(django为数据库名称)-此处未设置中文编码 mysql> create database django; # 查看创建的数据库 mysql> show create database django; # 删除数据库 mysql> drop database django; # 创建支持中文编码的数据库 mysql> create database django charset='utf8';
表的创建与删除
# 查看当前使用的数据库 mysql> select database(); # 选择使用的数据库 mysql> use django_AlexLu; # 创建表 mysql> create table students( -> id int primary key auto_increment not null, -> name varchar(20), -> age int default 20 -> ); # 显示创建的表 mysql> show create table students; # 显示表结构 mysql> desc students; # 显示已创建的表 mysql> show tables; # 向表中插入数据 mysql> insert into students(name,age) values('Tom', 22); # 查询表中的数据 mysql> select * from students;
Django连接MySQL
- 设置数据库连接项
# 在django的settings.py文件中对DATABASES进行设置 DATABASES = { 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_AlexLu', 'USER': 'root', 'PASSWORD': 'root', 'HOST': 'localhost', 'PORT': 3306 } }
- 安装pymysql
pip install pymysql
- 配置pymysql
# 在django项目下的__init__.py中进行设置 import pymysql pymysql.install_as_MySQLdb()
- 可能会出现的错误
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.
- 解决办法
# 安装libmysqlclient-dev sudo apt-get install libmysqlclient-dev # 安装mysqlclient pip install mysqlclient # 修改django项目下的__init__.py(去掉上面第3步增加的两行内容)改为: import MySQLdb
- 补充(mysql开发包的安装)
# Ubuntu sudo apt-get install libmysqlclient-dev # CentOS yum install python-devel mysql-devel
MySQL数据库迁移
# 生成迁移文件 python manage.py makemigrations # 将迁移文件映射到数据库中 python manage.py migrate # 如需强制迁移需要在上方命令后面加上 应用名
ORM
- Object Relational Mapping
- ORM(类、对象、属性)——DB(数据表、数据行、字段)
流程说明
- 创建models
- 通过models创建迁移文件(makemigrations)
- 通过迁移文件映射到数据库中(migrate)
将数据库表格信息展示在django后台
# 在app下的admin.py中进行设置 from django.contrib import admin from .models import Articles admin.site.register(Articles)
设置django后台展示出表格更多的列
# 在app文件下的admin.py中进行设置 from django.contrib import admin from .models import Articles class AritclesAdmin(admin.ModelAdmin): list_display = ['id', 'title', 'content', 'author'] admin.site.register(Articles, AritclesAdmin)
设置django后台表结构显示中文列名
# 修改app下的模型文件models.py,在字段创建时设置中文名称 class Articles(models.Model): title = models.CharField('标题', max_length=20) author = models.CharField('作者', max_length=20) content = models.TextField('内容')
- 设置完成后需要重新对数据库进行迁移
数据库表格列字段设置为选项(性别为可选项)
class Students(models.Model): choices = [ ('male', '男'), ('female', '女') ] name = models.CharField(verbose_name='姓名', max_length=20, unique=True) age = models.CharField(verbose_name='年龄', max_length=10) gender = models.CharField(verbose_name='性别', max_length=10, choices=choices, default='male') is_deleted = models.BooleanField(default=False) introduce = models.TextField(verbose_name='自我介绍')
模型中的元数据(Meta)
设置django后台表名显示为中文
# 在app下的模型文件models.py中进行设置 class Articles(models.Model): title = models.CharField('标题', max_length=20) author = models.CharField('作者', max_length=20) content = models.TextField('内容') def __str__(self): return self.title class Meta: verbose_name_plural = '新闻列表' verbose_name = '新闻'
- 在表格模型定义中增加子类Meta,通过verbose_name_plural与verbose_name设置中文名称即可
设置django后台表结构列名的排序方式
# 在模型定义下的Meta子类中增加ordering字段进行设置 class Meta: verbose_name_plural = '用户列表' verbose_name = '用户' ordering = ['age', '-name'] # ordering = ['-id']
修改表格名称
# 同样是在Mate子类中增加db_table字段进行设置 class Meta: verbose_name_plural = '用户列表' verbose_name = '用户' ordering = ['age', '-name'] db_table = 'students'
数据查询(从数据库中获取数据)
流程
- Model(database) → QuerySet(views → context) → html(templates)
查询表中全部数据
# 在视图views定义中,通过context传递给需要渲染的html from django.shortcuts import render from .models import Students # Create your views here. def index(request): student_list = Students.objects.all() # 此处为获取表中所有数据 context = { 'students': student_list } return render(request, 'index.html', context)
# 在模板templates下的index.html中进行展示 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for student in students %} <h1>{{ student.name }}——{{ student.age }}</h1> {% endfor %} </body> </html>
- 需要配置好urls,此处忽略配置urls的内容,需要根据实际情况自行设置
查询表中某一条数据
# 在视图views定义中,通过context传递给需要渲染的html from django.shortcuts import render from .models import Magnate # Create your views here. def index(request): context = { 'result': Magnate.objects.get(pk=1) # 此处查询的值必须是唯一的 } return render(request, 'index.html', context)
# 在模板templates下的index.html中进行展示 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ result.name }}</h1> <h1>{{ result.age }}</h1> <h1>{{ result.gender }}</h1> <h1>{{ result.assets }}</h1> <h1>{{ result.company }}</h1> </body> </html>
查询表中多条数据(过滤条件的使用)
# 在视图views定义中,通过context传递给需要渲染的html from django.shortcuts import render from .models import Magnate # Create your views here. def index(request): context = { 'female_list': Magnate.objects.filter(gender='female') # 'male_list': Magnate.objects.exclude(gender='female') } return render(request, 'index.html', context)
# 在模板templates下的index.html中进行展示 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for female in female_list %} <h1>{{ female.name }}——{{ female.assets }}</h1> {% endfor %} </body> </html>
- filter —— 查询结果为满足条件的记录
- exclude —— 查询结果为不满足条件的记录
二次查询(多次查询)
# 在视图views定义中,通过context传递给需要渲染的html from django.shortcuts import render from .models import Magnate # Create your views here. def index(request): magnates = Magnate.objects.all().filter(gender='male').filter(assets=2125) context = { 'male_list': magnates } return render(request, 'index.html', context)
# 在模板templates下的index.html中进行展示 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for male in male_list %} <h1>{{ male.name }}——{{ male.assets }}</h1> {% endfor %} </body> </html>
查询后排序
# 在视图views定义中,通过context传递给需要渲染的html from django.shortcuts import render from .models import Magnate # Create your views here. def index(request): magnates = Magnate.objects.filter(gender='male').order_by('-age') context = { 'magnates': magnates } return render(request, 'index.html', context)
# 在模板templates下的index.html中进行展示 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for magnate in magnates %} <h1>{{ magnate.name }}——{{ magnate.gender }}——{{ magnate.age }}</h1> {% endfor %} </body> </html>
通过某个字段进行查询
# 在视图views定义中,通过context传递给需要渲染的html from django.shortcuts import render from .models import Magnate # Create your views here. def index(request): magnates = Magnate.objects.values('name', 'assets') context = { 'magnates': magnates } return render(request, 'index.html', context)
# 在模板templates下的index.html中进行展示 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for magnate in magnates %} <h1>{{ magnate.name }}——{{ magnate.gender }}——{{ magnate.age }}</h1> {% endfor %} </body> </html>
- 此处界面不会显示性别信息,因为在视图中查询时只设置了姓名与资产两个字段
- values() 后括号为空时,查询所有字段,等价于 all()
- values与all的区别为,前者以字典形式返回,后者以对象形式返回
模糊查询
以xxx开头或以xxx结尾
# views视图中filter括号中使用模糊匹配的字段即可 magnates = Magnate.objects.filter(company__startswith='阿里')
- 字段名__startswith:以xxx开头,对大小写敏感
- 字段名__isstartswith:以xxx开头
- 字段名__endswith:以xxx结尾,对大小写敏感
- 字段名__isendswith:以xxx结尾
in查询
# views视图中filter括号中使用 字段名__in 即可 results = Magnate.objects.filter(age__in=[45, 58, 50])
范围查询
# views视图中filter括号中使用范围查询的字段即可 results = Magnate.objects.filter(age__range=(20, 45))
- 范围查询使用元组用来表示范围,只适用于数值型字段
判断条件查询
# views视图中filter括号中使用条件判断的字段即可 results = Magnate.objects.filter(assets__gt=1000)
- 字段名__gt:大于
- 字段名__gte:大于等于
- 字段名__lt:小于
- 字段名__lte:小于等于
向数据库中插入数据
# 在视图views定义中,通过create设置需要插入的数据 Magnate.objects.create(name='AlexLu', age=50, gender='male', assets=666, company='创慧弘', introduce='CHH Co., Ltd.')
数据统计
# 在视图views定义中,通过count进行统计 from django.shortcuts import render from .models import Magnate # Create your views here. def index(request): magnates = Magnate.objects.filter(gender='male').count() context = { 'count': magnates } return render(request, 'index.html', context)
# 在模板templates下的index.html中进行展示 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{ count }}</h1> </body> </html>
Count - Sum - Avg - Max - Min
# 需要在视图中导入相关统计函数 from django.db.models import Count, Sum, Avg, Max, Min # 在视图中统计时通过aggregate进行调用 results = Magnate.objects.aggregate(Count('name'), Sum('assets'), Avg('assets'), Max('assets'), Min('assets'))
- 返回值为字典形式:
{'name__count': 10, 'assets__sum': 14446, 'assets__avg': 1444.6, 'assets__max': 2387, 'assets__min': 400}
- 也可通过filter过滤后调用对应的统计函数实现
表单
1. 创建表单
# 在应用下创建forms.py from django import forms class RegisterForms(forms.Form): user_name = forms.CharField(min_length=8, max_length=20, label='用户名', initial='请输入您的手机号/密码') password = forms.CharField(widget=forms.PasswordInput, min_length=8, max_length=16, label='密码', help_text='密码为8-16位数字字母组合') repassword = forms.CharField(widget=forms.PasswordInput, min_length=8, max_length=16, label='确认密码') age = forms.IntegerField(min_value=18, max_value=100, label='年龄') # age = forms.Field(widget=forms.NumberInput, label='年龄') email = forms.EmailField(label='邮箱', disabled=True) phone = forms.CharField(max_length=11, label='手机号码', label_suffix=':(+86)') introduce = forms.CharField(label='自我介绍', widget=forms.Textarea)
2. 创建表单视图(将表单传递到前端页面)
# 在应用下的views.py中进行创建 from django.shortcuts import render from .forms import RegisterForms from django.views import View class IndexForms(View): def get(self, request): forms = RegisterForms() return render(request, 'index.html', {'forms': forms})
3. 配置路由
# 在应用下的urls.py中进行配置 urlpatterns = [ path('', views.IndexForms.as_view(), name='form'), ]
4. 编写前端页面代码
{# 在应用下templates中创建index.html进行编写 #} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> <table> {{ forms.as_table }} {#渲染成表格#} <tr> <td><input type="submit" value="确认登陆" name="submit"></td> </tr> </table> </form> <hr> <form action="" method="post"> <div> {{ forms.as_p }} {#渲染成段落#} <td><input type="submit" value="确认登陆" name="submit"></td> </div> </form> <hr> <form action="" method="post"> <div> {{ forms.as_ul }} {#渲染成标签#} <td><input type="submit" value="确认登陆" name="submit"></td> </div> </form> </body> </html>
5. 前端界面美化(增加CSS样式)
方法一
{# 直接在index.html文件中增加样式 #} {# 在<head>标签中增加<style>标签设置相应控件的样式 #} <style> #id_username{ border-radius: 5px; } </style>
方法二
# 在表单文件forms.py中为控件绑定样式类 from django import forms class RegisterForms(forms.Form): username = forms.CharField(min_length=8, max_length=20, label='用户名', initial='请输入您的手机号/密码', widget=forms.TextInput(attrs={'class': 'custom-forms'})) password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='密码', help_text='密码为8-16位数字字母组合') repassword = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='确认密码') age = forms.IntegerField(min_value=18, max_value=100, label='年龄', widget=forms.TextInput(attrs={'class': 'custom-forms'})) # age = forms.Field(widget=forms.NumberInput, label='年龄') email = forms.EmailField(label='邮箱', disabled=True, widget=forms.TextInput(attrs={'class': 'custom-forms'})) phone = forms.CharField(max_length=11, label='手机号码', label_suffix=':(+86)', widget=forms.TextInput(attrs={'class': 'custom-forms'})) introduce = forms.CharField(label='自我介绍', widget=forms.Textarea(attrs={'class': 'custom-forms-textarea'}))
{# 在<head>标签中增加<style>标签设置控件对应样式类的属性 #} <style> .custom-forms{ border-radius: 5px; } .custom-forms-textarea{ border-radius: 15px; } </style>
6. 选择控件
# 直接在表单文件form.py中定义控件时设置 from django import forms class RegisterForms(forms.Form): choices_item = [ (1, '男'), (2, '女'), (3, '保密') ] # 下拉列表 gender = forms.ChoiceField(label='性别', choices=choices_item, nitial=3) # 单选 gender2 = forms.ChoiceField(label='性别', choices=choices_item, widget=forms.RadioSelect, initial=2) # 复选 gender3 = forms.MultipleChoiceField(label='性别', choices=choices_item, widget=forms.CheckboxSelectMultiple, initial=1)
7. 日期控件
from django import forms class RegisterForms(forms.Form): formats = [ '%Y-%m-%d', # '2019-6-30' '%m/%d/%Y', # '06/30/2019' '%m/%d/%y', # '06/30/19' ] # 日期输入框 birthday = forms.DateField(label='出生日期', input_formats=formats) year_list = [ 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 ] # 日期选择框 birthday2 = forms.DateField(label='出生日期', input_formats=formats, widget=forms.SelectDateWidget(years=year_list))
日期控件数据验证
# 在应用下的views.py中的控件类视图中通过forms.is_valid()进行验证 from django.shortcuts import render, HttpResponse from .forms import RegisterForms from django.views import View class IndexForms(View): def get(self, request): forms = RegisterForms() return render(request, 'index.html', {'forms': forms}) def post(self, request): forms = RegisterForms(request.POST) if forms.is_valid(): birthday = forms.cleaned_data.get('birthday') return render(request, 'home.html', {'birthday': birthday}) else: return HttpResponse('<h1>对不起,您输入的出生日期有误~!</h1>')
{# 可通过home.html获取数据并展示 #} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>欢迎登陆Django后台管理系统</title> </head> <body> <h1>{{ birthday }}</h1> </body> </html>
8. 获取表单数据
# django项目的应用下的forms.py from django import forms class RegisterForms(forms.Form): choices_item = [ (1, '男'), (2, '女'), (3, '保密') ] hobbies = [ (1, '足球'), (2, '篮球'), (3, 'Python') ] year_list = [ 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 ] username = forms.CharField(min_length=8, max_length=20, label='用户名', initial='请输入您的手机号/密码', widget=forms.TextInput(attrs={'class': 'custom-forms'})) password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='密码', help_text='密码为8-16位数字字母组合') repassword = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='确认密码') gender = forms.ChoiceField(label='性别', choices=choices_item, nitial=3) age = forms.IntegerField(min_value=18, max_value=100, label='年龄', widget=forms.NumberInput(attrs={'class': 'custom-forms'})) birthday = forms.DateField(required=False, label='出生日期', widget=forms.SelectDateWidget(years=year_list)) hobby = forms.MultipleChoiceField(label='爱好', choices=hobbies, widget=forms.CheckboxSelectMultiple) introduce = forms.CharField(label='自我介绍', widget=forms.Textarea(attrs={'class': 'custom-forms-textarea'}))
# 应用下的视图文件views.py中编写表单对应的类视图 from django.shortcuts import render, HttpResponse from .forms import RegisterForms from django.views import View class IndexForms(View): def get(self, request): forms = RegisterForms() return render(request, 'index.html', {'forms': forms}) def post(self, request): forms = RegisterForms(request.POST) if forms.is_valid(): username = forms.cleaned_data.get('username') password = forms.cleaned_data['password'] context = { # 以字典形式处理表单数据 'datalist': { 'username': username, 'password': password, 'repassword': repassword, 'age': age, 'gender': gender, 'birthday': birthday, 'hobby': hobby, 'introduce': introduce, }, # 以列表形式处理表单数据 'datalist2': [ username, password, repassword, age, gender, birthday, hobby, introduce, ], } return render(request, 'home.html', context=context) else: return HttpResponse('<h1>对不起,您输入的信息有误~!</h1>')
{# 通过home.html接收表单数据并展示 #} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>欢迎登陆Django后台管理系统</title> </head> <body> {#接收字典形式数据#} {% for k, v in datalist.items %} <h1>{{ k }}---{{ v }}</h1> {% endfor %} <hr> {#接收列表形式数据#} {% for field in datalist2 %} <h1>{{ field }}</h1> {% endfor %} </body> </html>
模型表单(ModelForm)
1. 在模型文件models.py中设置好数据库映射
from django.db import models class Magnate(models.Model): choices = [ ('male', '男'), ('female', '女') ] name = models.CharField(verbose_name='姓名', max_length=20, unique=True) age = models.CharField(verbose_name='年龄', max_length=10) gender = models.CharField(verbose_name='性别', max_length=10, choices=choices, default='male') assets = models.IntegerField(verbose_name='资产') company = models.CharField(verbose_name='公司', max_length=50) is_deleted = models.BooleanField(default=False) introduce = models.TextField(verbose_name='介绍') class Meta: verbose_name_plural = '富豪榜' verbose_name = '富豪' ordering = ['id']
2. 建立模型表单
# 在应用下的forms.py中进行建立 from django import forms from .models import Magnate class MagnatesForms(forms.ModelForm): class Meta: model = Magnate # 获取全部字段 # fields = '__all__' # 指定过滤掉字段‘isdeleted’ # exclude = ['is_deleted'] # 指定获取的字段列表 fields = ['name', 'age', 'assets', 'company']
3. 创建模型表单对应的视图
# 在应用下的views.py中进行创建 from django.shortcuts import render, HttpResponse from .models import Magnate from .forms import MagnatesForms from django.views import View class IndexMagnate(View): def get(self, request): forms = MagnatesForms() return render(request, 'index.html', {'forms': forms})
4. 前端页面展示模型表单
{# 在应用中templates下的index.html进行展示 #} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .custom-forms{ border-radius: 5px; } .custom-forms-textarea{ border-radius: 15px; } </style> </head> <body> <form action="" method="post"> <div> {{ forms.as_p }} {#渲染成段落#} <td><input type="submit" value="确认登陆" name="submit"></td> </div> </form> </body> </html>
5. 为模型表单页面配置路由
# 在项目的路由文件urls.py中通过include关联到应用路由 from django.contrib import admin from django.urls import path, include from news import urls as news_urls urlpatterns = [ path('admin/', admin.site.urls), path('', include(news_urls)), ]
# 在应用下的路由文件urls.py中将创建的模型表单视图与路径进行匹配 from django.urls import path from news import views urlpatterns = [ path('', views.IndexMagnate.as_view(), name='magnate'), ]
为模型表单增加字段
# 直接在forms.py中的模型表单定义中增加 # 此处增加了password与repassword两个字段 from django import forms from .models import Magnate class MagnatesForms(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='密码', help_text='密码为8-16位数字字母组合') repassword = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='确认密码') class Meta: model = Magnate # 获取全部字段 # fields = '__all__' # 指定过滤掉字段‘isdeleted’ # exclude = ['is_deleted'] # 指定获取的字段列表————可用来调整显示顺序 fields = ['name', 'gender', 'age', 'password', 'repassword', 'assets', 'company']
为模型表单渲染CSS样式
# 直接在forms.py中的模型表单定义下增加widgets通过字典为相应的字段绑定控件及CSS样式 from django import forms from .models import Magnate class MagnatesForms(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='密码', help_text='密码为8-16位数字字母组合') repassword = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='确认密码') class Meta: model = Magnate # 获取全部字段 # fields = '__all__' # 指定过滤掉字段‘isdeleted’ # exclude = ['is_deleted'] # 指定获取的字段列表————可用来调整显示顺序 fields = ['name', 'gender', 'age', 'password', 'repassword', 'assets', 'company'] widgets = { 'name': forms.TextInput(attrs={'class': 'custom-textinput'}), 'introduce': forms.Textarea(attrs={'class': 'custom-textinput', 'row': 30, 'cols': 80}), }
{# 在html中为控件设定CSS样式 #} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .custom-forms{ border-radius: 5px; } .custom-forms-textarea{ border-radius: 15px; } .custom-textinput{ border: 5px solid #00ff00; border-radius: 5px; } </style> </head> <body> <form action="" method="post"> <div> {{ forms.as_p }} {#渲染成段落#} <td><input type="submit" value="确认登陆" name="submit"></td> </div> </form> </body> </html>
表单的手动渲染
普通表单的手动渲染
# 利用前端知识在html中直接进行样式设置 <form action="" method="post"> <hr> <ul> <li style="list-style-type: none;"> <span style="color: #ff0000"> {{ forms.username.label }} : </span> <span> {{ forms.username }} </span> <span style="margin-left: 10px"> {{ forms.username.help_text }} </span> </li> </ul> <hr> <td><input type="submit" value="确认登陆" name="submit"></td> </form>
模型表单的手动渲染
# 直接在模型表单定义中增加前端需要界面展示的信息,并在html中进行渲染 from django import forms from .models import Magnate class MagnatesForms(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='密码', help_text='密码为8-16位数字字母组合') repassword = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'custom-forms'}), min_length=8, max_length=16, label='确认密码') class Meta: model = Magnate # 获取全部字段 # fields = '__all__' # 指定过滤掉字段‘isdeleted’ # exclude = ['is_deleted'] # 指定获取的字段列表————可用来调整显示顺序 fields = ['name', 'gender', 'age', 'password', 'repassword', 'assets', 'company'] widgets = { 'name': forms.TextInput(attrs={'class': 'custom-textinput'}), 'introduce': forms.Textarea(attrs={'class': 'custom-textinput', 'row': 30, 'cols': 80}), } help_texts = { 'name': '请输入中文姓名全称', } labels = { 'name': '中文姓名', }
模型表单的数据保存(MySQL)
# 连接好MySQL数据库,在模型表单视图中post方法内进行数据获取和保存 from django.shortcuts import render, HttpResponse from .models import Magnate from .forms import MagnatesForms from django.views import View class IndexMagnate(View): def get(self, request): forms = MagnatesForms() return render(request, 'index.html', {'forms': forms}) def post(self, request): forms = MagnatesForms(request.POST) if forms.is_valid(): forms.save() return HttpResponse('<h1>数据保存成功!</h1>') else: return HttpResponse('<h1>数据保存失败!</h1>')
未完待续
学习笔记是根据下方视频教程的思路进行初步整理,待内容完整后进行重新梳理。
最后感谢陈老师详细的教学视频。