第一章 初识Django
1. 安装django
pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple
django安装后的目录结构:
c:\python310
- python.exe
- Scripts
- pip.exe
- django-admin.exe #工具,创建django项目
- Lib
- 内置模块
- site-packages
- openpyxl
- python-docx
- flask
- django #框架的源码
2. 创建Djiango项目
django中项目会有一些默认的文件和默认文件夹
2.1 在终端
-
打开终端
-
进入某个目录(指定需要创建的目录)、
E:\> cd .\python_web\demo_django\
-
执行django的创建命令
django-admin.exe startproject 项目名
-
创建成功后的目录结构如下:
mysite - mysite - __init__.py - asgi.py - settings.py - urls.py - wsgi.py - manage.py
2.2 Pycharm
注意, python解释器目录和项目目录
-
使用pycharm企业版
-
直接在菜单中创建 Django菜单进行创建
-
通过命令行创建的是标准的,但是pycharm创建的,会增加一些新的目录 templates目录, 在settings.py里添加了写数据
TEMPLATES = [ 'DIRS':[os.path.join(BASE_DIR, 'templates')] ]
2.3 默认创建项目的文件介绍
mysite
- mysite
- __init__.py
- asgi.py # 接受网络请求(异步)
- settings.py # 项目配置文件, 配置数据库,密码,注册app等.
- urls.py # URL路径和函数的对应关系
- wsgi.py # 接受网络请求(同步)
- manage.py # 项目管理,启动项目,创建app, 数据管理
3. APP
-项目
- app 用户管理 [表结构,函数,HTML模板, CSS]
- app 订单管理 [表结构,函数,HTML模板, CSS]
- app 后台管理 [表结构,函数,HTML模板, CSS]
- app 网站
- app API
-
创建一个app
python manage.py startapp app01 python manage.py startapp app02
-
app的文件结构
--app01 - __init__.py - admin.py # django后台提供admin后台管理 - apps.py # app启动类 - migratioins # 数据库变更记录 - __init__.py - models.py # 【重要】, 对数据库进行操作 - tests.py # 单元测试 - views.py # 【重要】, url定义执行的函数
4. 快速上手
4.1 app注册
在settings.py中配置需要注册的app
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config'
]
4.2 编写url和 试图函数的对应关系
urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
#path('admin/', admin.site.urls),
path('index/', views.index)
]
4.3 编写视图函数
views.py
from django.shortcuts import render
# Create your views here.
def index(request): # 响应试图函数必须有个request参数
return HttpResponse("欢迎使用")
4.4 启动djiango项目
-
通过命令行启动
python manage.py runserver
-
pycharm启动
点击 启动按钮 进行启动
4.5 模板使用
views.py
def user_list(request):
# 默认会去app目录下,寻找templates目录,再在这个目录中查询user_list.html这个文件
# 如果跟目录下有user_list.html, 也只会在app里查找,如果需要使用根目录的,则需要更改settings里的配置
return render(request, "user_list.html")
当前app目录下,创建一个templates目录
4.6 静态文件
静态文件必须在当前的app目录下面的static目录
静态文件包含js, css, image等资源
- 在app目录下创建static目录
- 在html中, 顶部执行 {% load static %}
- 使用 “{% static ‘/css/sss.css’ %}”
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %}">
</head>
<body>
<h1>用户登陆</h1>
<input type="text" class="btn btn-primary" value="新建"/>
<img src="/static/img/11.jpg" alt=""/>
<script src="{% static 'js/jquery-3.7.1.min.js'}"></script>
<script src="{% static 'plugins/bootstrap/js/bootstrap.js'} %"></script>
</body>
</html>
5. 模板语法
本质上, 在html中写一些占位符, 由数据进行替代和处理
5.1 普通变量的传递
name="自定义标题1"
return render(request, "tpl.html", {"n1":name})
<div>{{n1}}</div>
5.2 数组的传递
roles = ["张三","李四","王五"]
return render(request, "tpl.html", {"roles":roles})
数组遍历
<table>
<thead>
<tr>
<th>id</th>
<th>姓名</th>
</tr>
</thead>
<tbody>
{% for item in roles %}
<tr>
<td>1</td>
<td>{{item}}</td>
</tr>
{% endfor %}
</tbody>
</table>
直接取数组元素
<div>
<span>{{roles.0}}</span>
<span>{{roles.1}}</span>
<span>{{roles.2}}</span>
</div>
5.3 字典的传递
userinfo = {"name":"bell","exp":1000, "lv":25 }
return render(request, "tpl.html", {"user":userinfo})
<div>
<div>{{user.name}}</div>
<div>{{user.lv}}</div>
</div>
字典用for进行循环
<!--字典也可以 for循环-->
<ul>
{% for item in user.keys %}
<li> {{item}} </li>
{% endfor %}
</ul>
<ul>
{% for k, v in user.items %}
<li> {{k}} = {{v}} </li>
{% endfor %}
</ul>
5.4 列表套字典
user_list = [
{"name":"zs", "age":23,"score":100},
{"name":"ls", "age":23,"score":100},
{"name":"ww", "age":23,"score":100},
]
return render(request, "tpl.html", {"user_list":user_list})
<!--列表里套字典 user_list.0.name, user_list.1.age-->
<ul>
{% for item in user_list %}
<li> {{item.name}} {{item.age}} {{item.score}} </li>
{% endfor %}
</ul>
5.5 模板中的条件语句
<!--模板中条件语句-->
{% if n1 == "自定义标题" %}
<a>aaaa</a>
{% elif n1 == "新" %}
<a>bbbb</a>
{% else %}
<a>cccc</a>
{% endif %}
第二章 Django开发
主题: 员工管理系统
1. 新建项目
> django-admin.exe startproject EmployeeSystem
2. 创建App并注册
> python manage.py startapp app01
EmployeeSystem/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config' #注册的app01
]
3. 设计表结构
'''
部门表
'''
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=32)
age = models.IntegerField(verbose_name="年龄")
account = models.DecimalField(verbose_name="账号余额", max_length=10, decimal_places=2, default=0)
create_time = models.DateTimeField(verbose_name="入职时间")
# 无约束
#depart = models.BigIntegerField(verbose_name="部门")
# 有约束
# -to, 与哪张表相关联, to_field,与哪个列相关联, djange自动关联;
# 在mysql,会自动 depart_id, 是由 django自动生产
# on_delete=models.CASCADE: 级联删除,即当department部门项删除后,该表关联的UserInfo也要被删除.
depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)
# 如果删除, 将员工置空,则需要可以置空,即
# depart = models.ForeignKey(to="Department", to_field="id", null=True, blank=True)
4. 在MySql中生成表
-
安装第三方库
pip install mysqlclient -i https://pypi.tuna.tsinghua.edu.cn/simple
-
工具链接MySql生成数据库
> mysql -u root -p > create database employee default charset utf8 collate utf8_general_ci;
-
修改配置文件,连接mysql
settings.py
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'employee', 'USER': 'root', 'PASSWORD': '123456', 'HOST': '127.0.0.1', 'PORT': 3306 } }
-
django命令生成数据库表
> python manage.py makemigrations > python manage.py migrate
创建的表结果如下:
mysql> desc app01_department; +-------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+----------------+ | id | bigint | NO | PRI | NULL | auto_increment | | title | varchar(32) | NO | | NULL | | +-------+-------------+------+-----+---------+----------------+
mysql> desc app01_userinfo; +-------------+---------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+---------------+------+-----+---------+----------------+ | id | bigint | NO | PRI | NULL | auto_increment | | name | varchar(16) | NO | | NULL | | | password | varchar(32) | NO | | NULL | | | age | int | NO | | NULL | | | account | decimal(10,2) | NO | | NULL | | | create_time | datetime(6) | NO | | NULL | | | gender | smallint | NO | | NULL | | | depart_id | bigint | NO | MUL | NULL | | +-------------+---------------+------+-----+---------+----------------+
5. 静态文件的管理
- 在app里创建static目录;
- 在app里创建templates目录;
6. 启动项目
> python manage.py runserver
7. 部门管理
- 原始方法,体验
-
部门列表
-
前端: depart_list.html
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户管理系统</title> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %}"> <link rel="stylesheet" href="{% static 'css/mystyle.css' %}"> </head> <body> <div class="container"> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">用户管理系统</a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="/depart/list/">部门管理</a></li> <li><a href="/user/list/">用户管理</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="#">登陆</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">张三 <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">个人资料</a></li> <li><a href="#">我的信息</a></li> <li role="separator" class="divider"></li> <li><a href="#">注销</a></li> </ul> </li> </ul> </div> </div> </nav> <div> <div class="container"> <div style="margin-bottom:10px"> <a class="btn btn-success" href="/depart/add"> <!-- target="_blank"--> <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> 新建部门 </a> </div> <div class="bs-example" data-example-id="table-within-panel"> <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading"><span class="glyphicon glyphicon-th-large" aria-hidden="true"></span> 部门列表</div> <!-- Table --> <table class="table table-bordered"> <thead> <tr> <th>ID</th> <th>部门名称</th> <th>操作</th> </tr> </thead> <tbody> {% for obj in queryset %} <tr> <th scope="row">{{obj.id}}</th> <td>{{obj.title}}</td> <td> <a class="btn btn-primary btn-xs" href="/depart/{{obj.id}}/edit/">编辑</a> <a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{obj.id}}">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </div> </div> <script src="{% static 'js/jquery-3.7.1.min.js'}"></script> <script src="{% static 'plugins/bootstrap/js/bootstrap.js'} %"></script> </body> </html>
说明: 1. 如果点击一个按钮, 需要打开新的标签也,则在<a>标签内,添加 target="_blank" 2. 对于get消息的url传递,可以在url中增加参数, 传递到后端, 见:编辑 href="/depart/{{obj.id}}/edit/">编辑</a>
-
后端: views.py
""" 部门列表 """ def depart_list(resq): # 取数据库中获取所有的部门列表 queryset = models.Department.objects.all() return render(resq, 'depart_list.html', {"queryset":queryset})
-
-
新增部门
-
前端(depart_add.html):
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>用户管理系统</title> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %}"> <link rel="stylesheet" href="{% static 'css/mystyle.css' %}"> </head> <body> <div class="container"> <nav class="navbar navbar-default"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">用户管理系统</a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="/depart/list/">部门管理</a></li> <li><a href="/user/list/">用户管理</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="#">登陆</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">张三 <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">个人资料</a></li> <li><a href="#">我的信息</a></li> <li role="separator" class="divider"></li> <li><a href="#">注销</a></li> </ul> </li> </ul> </div> </div> </nav> <div class="container"> <div class="panel panel-default"> <div class="panel-heading">添加部门</div> <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> <button type="submit" class="btn btn-primary">提交</button> </form> </div> </div> </div> </div> <script src="{% static 'js/jquery-3.7.1.min.js'}"></script> <script src="{% static 'plugins/bootstrap/js/bootstrap.js'} %"></script> </body> </html>
说明: 1. 默认在form提交post方法会报错, djiango要求需要在form中添加 {% csrf_token %} 2. 在form中,如果提交给本网页,则不需要在form标签中添加action.
-
后端(views.py):
from django.shortcuts import render, redirect """ 添加部门 """ def depart_add(resq): if resq.method == 'GET': return render(resq, 'depart_add.html') #获取通过post提交的数据 title = resq.POST.get("title") # 保存到数据库 models.Department.objects.create(title = title) # 重定向回部门列表 return redirect("/depart/list")
说明: 1. 重定向 redirect方法,需要在djiango.shortcuts中引入 2. 创建一个新的对象,直接调用models.Department.object.create(xxx)
-
-
编辑部门
-
前端(depart_edit.html):
参考depart_add.html
核心html:
<form method="post"> {% csrf_token %} <div class="form-group"> <label >标题</label> <input type="text" class="form-control" placeholder="标题" name="title" value="{{row_object.title}}"> </div> <button type="submit" class="btn btn-primary">提交</button> </form>
说明: 1. 编辑标题时,默认需要将当前选择的标题进行带上,这个由后端渲染网页时,带入
-
后端(views.py):
""" 编辑部门 http://127.0.0.1/depart/10/edit/ """ def depart_edit(resq, nid): # 获取的queryset row_object = models.Department.objects.filter(id=nid).first() if resq.method == 'GET': return render(resq, 'depart_edit.html', {"row_object":row_object}) #获取通过post提交的数据 title = resq.POST.get("title") models.Department.objects.filter(id=nid).update(title=title) return redirect("/depart/list")
说明: 1. 获取单独一个对象时,需要在query_set中调用first(), 来获取列表中的第一个 2. 修改方法时,是直接调用query_set对象的update方法,而不是逻辑对象depart对象的方法
-
-