记录学习Django的过程

System: MacOS 12.0
Python: 3.8.9
Django: 2.2.1

初始

创建项目

  • 使用PyCharm

    新建Django项目File/New Project/Django

    如果没有提前安装Django则会自动安装最新版

  • 命令行

    创建项目命令django-admin startproject 项目名

    切换到项目目录

    启动项目python mange.py runserver

端口

默认端口为8000

修改端口号

  • PyCharm

    编辑项目,修改Host:Port

    11-21_19:27

  • 命令行运行

    python mange.py runserver ip:指定端口号

Index

一切就绪后通过访问127.0.0.1:8000就能看到Django初始界面

11-21_22:03

Django目录结构

1
2
3
4
5
6
7
8
9
10
|-- 项目名
| |-- __init__.py --> 声明该项目是Python包
| |-- setting.py --> 项目的配置文件
| |-- urls.py --> URL声明,管理资源地址
| |-- wsgi.py --> django自带的服务器
| |-- views.py --> 名称可自定义的视图文件
db.sqlite3 --> 文本型数据库
templates --> 返回页面
static --> 静态文件(图片,css,js等)
manage.py --> 项目运行文件

Views.py

  1. 函数名称: 见名知意,遵循标识符规则。
  2. request参数: Django 将请求的所有的内容都封装到对象中,然后传递给视图函数的第一个参数。
  3. 返回值: 必须要有响应对象,可以是HttpResponse 也可以是子类。
1
2
3
4
5
6
7
8
9
10
11
12
13
def index(request):
'''
作用: 所有的逻辑判断都在视图函数中完成
# 例如返回html页面,操作数据库等等
request参数: Django将请求的所有内容都封装到对象中,然后传递给视图函数的第一个参数
return: 必须要有响应对象,可以是HttpResponse也可以是子类
HttpResponse对象可以返回简单的字符串
'''
print(request.method)
print(request.headers)
print(request.path_info)
print(request.get_full_path())
return HttpResponse('index')

Render函数

1
2
3
4
5
6
7
# 导入函数
from django.shortcuts import render

def index():
# 返回页面
# render函数的第一个参数是视图函数的第一个参数
return render(request, 'index.html') # 该html会从templates文件夹下寻找

Urls.py

作用: 提供URL到视图函数之间的一个映射关系

URL先找到路由,然后路由再找到视图函数

1
2
3
4
5
urlpatterns = [
path('admin/', admin.site.urls),
# 第一个参数任意,第二个参数是函数名称(不是调用函数)
path('hello/', hello)
]

HelloWorld

在项目包下创建一个views.py文件

1
2
3
4
5
6
7
8
9
10
11
12
# 导入HttpResponse模块
from django.shortcuts import HttpResponse


def hello(request):
return HttpResponse('Hello,World')

'''
返回值也可以写成:
response = HttpResponse('Hello,World')
return response
'''

修改urls.py文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 从views导入hello函数
from Django_Learn import views

urlpatterns = [
path('hello/', views.hello),
]

'''
一个函数对应多个路由
path('hello1/', hello),
path('hello2/', hello),

项目首页显示
path('', index),
'''

从浏览器访问127.0.0.1:8000/hello即可看到HelloWorld

11-23_15:54

路由使用正则表达式

目的: 提高代码的复用率,减少代码冗余

urls.py

1
2
3
4
5
6
7
8
9
10
11
12
# 格式

# 导入re_path
from django.urls import path, re_path

# 使用
urlpatterns = [
re_path(r'^\d+/$', views.hello1), # 使用正则表达式
re_path(r'^hello/(w+)/$', views.hello2), # 分组匹配
re_path(r'^(?P<page>\d+)/$', views.hello3), #分组命名匹配 格式:(?P<组名称>正则表达式)。
]
# 值得注意的是: 分组和分组命令不能混用,一个路由中不能同时出现两种方法

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 使用正则匹配
def hello1(request):
return HttpResponse('hello 1...')


# 分组匹配
def hello2(request, args):
"""
:param request:
:param args: 名称任意。
:return:
"""
print(args)
return HttpResponse('hello 2...')


# 分组命名匹配
def hello12(request, page):
"""
:param request:
:param page: 参数名称必须要和组名称相同。
:return:
"""
print(page)
return HttpResponse('hello 3...')

Templates

在此文件夹下可以创建静态html文件

如果使用命令行创建项目,则需要手动创建此文件夹

且需要修改setting.py

1
2
3
4
5
TEMPLATES = [
{
'DIRS': [os.path.join(BASE_DIR, 'templates')],
},
]

模板

页面显示数据

数据的替换是在内存中完成,然后将最终的替换完成的页面,返回给浏览器,浏览器再进行展示。

  • views.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    def index2(request):
    # 相当于从数据库中获取的数据
    info_list = [
    {'name': 'zs', 'age': 18},
    {'name': 'lsi', 'age': 20},
    {'name': 'wangw', 'age': 22},
    ]
    # 第三个值:类型是字典。key 任意,value 为要在页面上显示的值
    return render(request, 'index2.html', {'info_list': info_list})
  • urls.py

    添加路由

    1
    2
    3
    ...
    path('index2/', views.index2),
    ...
  • index2.html

    1
    2
    3
    4
    5
    ...
    <body>
    {{ info_list }}
    </body>
    ...

    11-23_17:49

  • locals()函数

    它返回对所有局部变量的名称与值进行映射,即包括所有的局部变量,不用再重新定义一遍临时变量

    故,可以将上面views.py结尾处{'info_list': info_list}改为locals()

页面显示不同类型的数据

列表数据

  • views.py

    1
    2
    3
    4
    def index3(request):
    # 返回列表
    hero_list = ['枣庄王', '石家庄赵子龙', '包头吕布', '小鲁班']
    return render(request, 'index3.html', locals())
  • urls.py

    1
    2
    3
    ...
    path('index3/', views.index3),
    ...
  • index3.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ...
    <body>
    {{ hero_list }}
    {# 获取列表中的数据,方法:变量名称.索引 #}
    <br>
    {{ hero_list.1}}
    {# 石家庄赵子龙 #}
    </body>
    ...

    11-23_18:09

字典数据

  • views.py

    1
    2
    3
    def index4(request):  # 字典
    user_info = {'name': '尼古拉斯-赵四', 'age': 40, 'gender': '男'}
    return render(request, 'index4.html', locals())
  • urls.py

    1
    2
    3
    ...
    path('index4/', views.index4),
    ...
  • index4.html

    1
    2
    3
    4
    5
    6
    7
    8
    ...
    <body>
    {{ user_info }}
    {# 获取字典中的value,方法:变量名称.key #}
    <br>
    用户名是:{{ user_info.name }},今年:{{ user_info.age }}岁,性别为:{{ user_info.gender }}
    </body>
    ...

    11-23_18:13

组合数据类型

  • views.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def index4(request):  # 字典
    user_info = {'name': '尼古拉斯-赵四', 'age': 40, 'gender': '男'}

    # 组合型
    user_info_list = [
    {'name': '赵四', 'age': 40, 'gender': '男'}, {'name': '刘能', 'age': 30, 'gender': '男'}, {'name': '宋小宝', 'age': 20,
    'gender': '男'}
    ]
    person_info = {'name': '于谦', 'age': 29, 'hobby': ['抽烟', '喝酒', '烫头']}
    return render(request, 'index4.html', locals())
  • index4.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <body>
    {{ user_info }}
    {# 获取字典中的数据,方法:变量名称.key #}
    <br>
    用户名是:{{ user_info.name }},今年:{{ user_info.age }}岁,性别为:{{ user_info.gender }}
    <hr>
    <p>
    {# 获取列表中字典中的值 #}
    {{ user_info_list }}
    <hr>
    索引为1的字典中key为name的名字是:{{ user_info_list.1.name }}
    <br>
    索引为0的字典中key为name的名字是:{{ user_info_list.0.name }}
    </p>
    <hr>
    <p>
    {# 获取字典中列表中的值 #}
    {{ person_info }}
    <br/>
    字典中的列表索引为2的爱好是:{{ person_info.hobby.2 }}
    </p>
    </body>

    11-23_18:35

对象数据

  • views.py

    1
    2
    3
    4
    5
    6
    7
    8
    class Dog():
    def __init__(self, name):
    self.name = name
    pass

    def eat(self):
    return '爱吃骨头'
    pass

    def index5(request):

    # 创建对象
    dog_obj = Dog('大黄')
    return render(request, 'index5.html', locals())
1
- urls.py


path(‘index5/‘, views.index5),

1
2
3
4
5
6
7
8
9
10
11
12
- index5.html
```html
...
<body>
{# 获取对象中的属性值和调用方法#}
{{ dog_obj }} <br>
{# 获取属性: 对象名称.属性名称#}
{{ dog_obj.name }}<br/>
{# 调用方法:对象名称.方法名称#}
{{ dog_obj.eat }}
</body>
...

11-23_18:43

标签(Tags)

作用: 可以做一些简单的业务逻辑。

格式: {% 标签名称 %} {% end标签名称 %}

单分支

  • views.py

    1
    2
    3
    def tag(request):
    age = 16
    return render(request, 'tag.html', locals())
  • urls.py

    1
    2
    3
    ...
    path('tag/', views.tag),
    ...
  • tag.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ...
    <body>
    {# 单分支 #}
    {% if age < 18 %}
    如果年龄小于18岁,则输出如下内容:
    <br>
    <h2>
    好好学习,天天向上
    </h2>
    {% endif %}
    </body>
    ...

双分支

  • tag.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    ...
    <body>
    ...
    {# 双分支 #}
    {% if age < 16 %}
    如果年龄小于16岁,则输出如下内容:
    <br>
    <h2>
    好好学习,天天向上
    </h2>
    {% else %}
    如果年龄大于16岁,则输出如下内容:
    <br>
    <h2>
    欢迎来到成年人的世界
    </h2>
    {% endif %}
    </body>
    ...

多分支

  • tag.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    ...
    <body>
    ...
    {# 多分支 #}
    {% if age > 0 and age < 18 %}
    <h2>我是祖国的花朵...</h2>
    {% elif age >= 18 and age <= 30 %}
    <h2>我是小鲜肉...</h2>
    {% elif age > 30 and age <= 50 %}
    <h2>我是老腊肉...</h2>
    {% else %}
    <h2>我是....</h2>
    {% endif %}
    </body>
    ...

    11-23_18:58

ifequal

  • tag.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ...
    <body>
    ...
    {# ifequal #}
    如果变量值和常量相同则执行if体,否则不执行。<br>
    {% ifequal age 16 %}
    如果年龄为16则输出如下内容:<br>
    <h2>my age is {{ age }}...</h2>
    {% endifequal %}
    </body>
    ...

    11-23_19:03

for

格式:

1
2
3
{% for hero in  hero_list%}
{{ hero }}
{% endfor %}
forloop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
<body>
{% for hero in hero_list %}
<tr>
<td>
{# { forloop.counter }} {# 计数 #}
{# { forloop.revcounter }} {# 倒序计数 #}
{# { forloop.revcounter0 }} {# 倒序计数至0 #}
{# { forloop.first }} {# 第一个为True,其他为False #}
{# { forloop.last }} {# 最后一个为True,其他为False #}
</td>
<td>
{{ hero }}

</td>
<td>
<a href="#">编辑</a>
<a href="#">删除</a>
</td>
</tr>
{% endfor %}
...
</body>

11-23_19:10

for…empty

如果变量有值则执行循环,如果变量没有值,则执行 empty 中对应的内容。

  • views.py

    1
    2
    3
    4
    5
    def index4(request):
    ...
    null_list = []
    ...
    ...
  • index4.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <body>
    ...
    {% for nothing in null_list %}
    {{ nothing }} <br/>
    {% empty %}
    购物车空空的哦~,去看看心仪的商品吧~
    <a href="https://www.jd.com">去购物 ></a>
    {% endfor %}
    ...
    </body>

    11-23_21:55

static

需要在项目根目录自行创建

且需要修改setting.py

1
2
3
STATIC_URL = '/static/'
# 添加如下内容
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
  • html

    1
    2
    3
    <br>
    图片展示
    <img src="../static/wallpaper.jpg" width="546" height="364"/>
11-23_22:05
load static
1
2
{% load static %}
<img src="{% static 'wallpaper.jpg' %}" alt="图片展示" width="546" height="364">

效果同上

继承

提高代码的重用率

  • 创建父页面base.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ...
    <body>
    {# 相同的代码抽取出来,放到父页面中 #}
    <h1 style="background-color: orangered ; height: 50px; line-height: 2px; "></h1>
    {% block main %}

    {# 子页面不同的地方,通过block标签进行,预留位 #}

    {% endblock %}
    <h1 style="background-color: orangered ; height: 50px; line-height: 2px; "></h1>

    </body>
    ...
  • 创建子页面index.html

    1
    2
    3
    4
    5
    6
    7
    {% extends 'base.html' %}
    <h1>
    继承父类
    </h1>
    {% block main %}
    <h1>不使用父类代码</h1>
    {% endblock %}

    11-24_17:20

  • 创建父页面base.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ...
    <title>
    {% block title %}
    {% endblock %}
    </title>
    </head>
    <body>
    <h1 style="...">
    header
    </h1>
    {% block main %}

    {% endblock %}
    <h1 style="...">
    footer
    </h1>
    </body>
    ...
  • 创建子页面index.html

    1
    2
    3
    4
    5
    6
    7
    8
    {% block main %}
    <h1>
    index...
    </h1>
    {% endblock %}
    {% block title %}
    首页
    {% endblock %}

    可见使用了{% block main %}的h1标签正常显示了,而{% block title %}因为父页面中为空所以不显示

    11-24_17:26

include

提高代码的复用率

当页面代码相同部分较少,且内容不变,例如每个页面的footer部分

  • views.py

    1
    2
    3
    4
    ...
    def home(request):
    return render(request, 'home.html', locals())
    ...
  • urls.py

    1
    2
    3
    ...
    path('home/', views.home),
    ...
  • 创建home.html

    1
    2
    3
    4
    5
    6
    7
    8
    ...
    <body>
    <h1>
    我是home
    </h1>
    {% include 'footer.html' %}
    </body>
    ...
  • 创建footer.html

    1
    2
    3
    4
    5
    6
    7
    ...
    <body>
    <h1>
    我是footer
    </h1>
    </body>
    ...

    11-24_17:37

过滤器(Filters)

作用: 可以在变量被显示前修改它,过滤器使用管道字符

过滤器本质: 就是函数

格式: `{{ 数据|过滤器:可选参数 }}`

  • {{ 数据 |upper }}

    将数据变成大写

    1
    2
    # 假设name的值为zhangsan
    经过过滤器{{ name|upper}}输出结果为ZHANGSAN
  • {{ 数据|lower}}

    将数据变成小写

    1
    2
    # 假设name的值为ZHANGSAN
    经过过滤器{{ name|lower}}输出结果为zhangsan
  • {{ 数据|lower|upper}}

    先将数据变成小写再变成大写

    1
    2
    # 假设name的值为ZhangSan
    经过过滤器{{ name|lower|upper}}输出结果为ZHANGSAN
  • addslashes:添加反斜杠到任何反斜杠、单引号或者双引号前面

  • date:按指定的格式字符串参数格式化 date 或者 datetime 对象

  • length:返回变量的长度

  • default:当变量为空或False时提供默认值

  • filesizeformat:以格式显示文件大小,字典返回的是键值对的数量,集合返回的是去重后的长度

  • date:根据给定格式对一个日期变量进行格式化

  • truncatechars:如果字符串包含的字符总个数多于指定的字符数量,那么会被截断掉后面的部分。截断的字符串将以 结尾。

  • safe:将字符串标记为安全,不需要转义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
<body>
{# 格式: {{ 数据|过滤器 }} #}
<h1>home... 过滤器</h1>

{# 已设定msg为hello,msg1为[],link为https://www.baidu.com #}
{{ msg }} 转换为大写--> {{ msg|upper }} <br/>

{# 管道可以传递输出,与Linux管道一样 #}
{{ msg }} 转换为大写再转换为小写-->{{ msg|upper|lower }} <br/>
{{ msg }} 首字母大写-->{{ msg|title }} <br/>
{{ msg1|default:'我是默认值...' }} <br/>
{# safe: 将字符串标记为安全,不需要转义。 #}
{{ link }} -->> {{ link|safe }}
</body>
...

11-24_18:25

评论