Django学习笔记

安装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(数据表、数据行、字段)

流程说明

  1. 创建models
  2. 通过models创建迁移文件(makemigrations)
  3. 通过迁移文件映射到数据库中(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>')

未完待续

以上学习笔记是根据视频教程 Python之Django企业开发实战 的思路进行初步整理,待内容完整后进行重新梳理。

最后感谢陈老师详细的教学视频。

posted @ 2019-09-05 01:02  AlexLu0711  阅读(888)  评论(0编辑  收藏  举报