赞
踩
学习视频来源:最新Python的web开发全家桶
代码仓库:https://gitee.com/m_engmeng/django-learning
Django中项目会有一些默认的文件和文件夹
django-admin startproject mysite
python manage.py startapp myApp
windows命令展示目录结构:
输入:tree
此时展现的是所有文件夹的路径所构成的树。
如果想连文件夹中的文件都展示,则输入:tree /f命令,可以显示所有资源。
mysite
- manage.py [项目的管理,启动项目、创建app、数据管理][不用改]
- mysite
- __init__.py
- settings.py [项目配置][**经常更改**]
- urls.py [URL和函数的对应关系] [**经常更改**]
- asgi.py [接收异步网络请求][不用改]
- wsgi.py [接受同步网络请求][不用改]
- 项目
- app: 用户管理 [独立的表结构、函数、HTML模板、CSS]
- app: 订单管理 [独立的表结构、函数、HTML模板、CSS]
- app: 后台管理 [独立的表结构、函数、HTML模板、CSS]
- app: 网站 [独立的表结构、函数、HTML模板、CSS]
- app: API [独立的表结构、函数、HTML模板、CSS]
...
APP 目录:
E:. │ manage.py │ ├─myApp │ │ admin.py [ 固定,不用动] django默认提供了admin后台管理 │ │ apps.py [ 固定,不用动] app启动类 │ │ models.py [ 重要 ] ,对数据库操作 │ │ tests.py [ 做单元测试] │ │ views.py [ 重要 ] 函数 │ │ __init__.py │ │ │ └─migrations [ 固定,不用动] 数据库变更记录 │ __init__.py │ └─mysite │ asgi.py │ settings.py │ urls.py │ wsgi.py │ __init__.py └─__pycache__ settings.cpython-310.pyc __init__.cpython-310.pyc
运行前确保app已注册
编写URL和视图函数的对应关系 (urls.py)
from myApp import views
urlpatterns = [
# path('admin/', admin.site.urls),
# 后面只要访问 xxx.com/index -> 就会对应views文件中的index函数
path('index/', views.index)
]
from django.shortcuts import render, HttpResponse
# Create your views here.
# request 是默认参数,要加上
def index(request):
return HttpResponse("欢迎使用")
在对应的app目录下创建templates文件夹,里面放置html文件
在开发过程中一般将:
如果想要引入static文件夹下的文件应作如下修改:
STATIC_URL = '/static/'
STATICFILES_DIRS=(
os.path.join(BASE_DIR,'static'),
)
<p>
<img src="{% static 'img/ger.jpg' %}" alt="germany" width="420" height="320">
</p>
本质上:在HTML中写一些占位符,由数据对这些占位符进行替换和处理。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tql</title> </head> <body> <h1> Django模板语法学习 </h1> <!-- 通过在函数中传入的字典的键来获取其值 --> <div> {{ n1 }}</div> <div> {{ n2 }} </div> <hr /> <h2> 列表 </h2> <!-- 获取列表中的值 --> <div> {{ n2.0 }} </div> <div> {{ n2.1 }} </div> <div> {{ n2.2 }} </div> <div> {{ n2.3 }} </div> <!-- 通过循环获取列表中的值 --> <div> {% for item in n2 %} <span> {{ item }} </span> {% endfor %} </div> <hr /> <h2> 字典 </h2> <div> {{ n3 }} </div> <!-- 根据字典的键获取值 --> <div> {{ n3.伯 }} </div> <div> {{ n3.仲 }} </div> <div> {{ n3.叔 }} </div> <div> {{ n3.季 }} </div> <!-- 遍历字典的键值对 --> <ul> {% for key,value in n3.items %} <li> {{key}} = {{value}}</li> {% endfor %} </ul> <hr /> <h2> 条件语句 </h2> <!-- 条件判断 --> {% if n1 == '季' %} <h3>疾行</h3> {% elif n1 == '霁月' %} <h3>霁月</h3> {% else %} <h3>霁月壬</h3> <button type="button" class="btn btn-info">信息</button> {% endif %} </body> </html>
重定向: 浏览器向某个网站发送请求,网站返回给浏览器一个新的URL,浏览器去访问这个新的URL地址
# request 是一个对象,封装了用户发送过来的所有请求相关数据 # 1. [请求] 获取请求方式 print("用户请求的方式: " + request.method) # 2. [请求] 在URL上传递值,例如 例如: http://123.249.26.154:5900/something/?n1=1&n2=2 print(request.GET) # 3. [请求]在请求体中提交数据,目前是空值 print(request.POST) # 4. [响应]HttpResponse("返回内容"),内容字符串内容返回给请求者 return HttpResponse("返回内容") # 5. [响应]读取HTML的内容 + 渲染(替换) => 最终都转化为字符串返回给用户浏览器 return render(request, 'something.html', {"title":"Hello"}) # 6. [响应] 让浏览器重定向到其他的页面 return redirect("http://www.baidu.com")
Django 提供ORM框架来操控数据库
pip install mysqlclient
ORM可以帮助我们做两件事:
create database mydb DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
DATABASES = {
'default':{
'ENGINE':'django.db.backends.mysql',
'NAME':'mydb', # 数据库名字
'USER':'root',
'PASSWORD':'meng_19210504',
'HOST':'127.0.0.1',
'PORT':'3306',
}
}
class UserInfo(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
age = models.IntegerField()
"""
上面的语句等同于
create table myapp_userinfo(
id bigint auto_increment primary key,
name varchar(32),
password varchar(64),
age int
)
"""
如果不想要某个表了,将class类注释后,重新执行 runsql.bat
- python3 manage.py makemigrations
- python3 manage.py migrate
age = models.IntegerField(default=2)
data = models.IntegerField(null=True, blank=True)
UserInfo.objects.create(name=“poker”, password=“123”, age=25)
# 删除数据
UserInfo.objects.filter(id=2).delete()
# 删除表中所有数据
UserInfo.objects.all().delete()
data_list = UserInfo.objects.all()
print(data_list)
for obj in data_list:
print(obj.id, obj.name, obj.password, obj.age)
UserInfo.objects.filter(name="roker").update(age=35)
urls.py
urlpatterns = [
# path('admin/', admin.site.urls),
# 后面只要访问 xxx.com/index -> 就会对应views文件中的index函数
path('info/list/', views.info_list),
path('info/add/', views.info_add),
path('info/delete/', views.info_delete),
]
views.py中的info_list函数
def info_list(request):
# 获取表中所有数据
data_list = UserInfo.objects.all()
return render(request, 'info_list.html', {"data_list":data_list})
info_list.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 新 Bootstrap 核心 CSS 文件 --> <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <style> </style> </head> <body> <a href="/info/add">添加</a> <table border="1" class="table table-hover"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>密码</th> <th>年龄</th> </tr> </thead> <tbody> {% for obj in data_list %} <tr> <td> {{ obj.id }} </td> <td> {{ obj.name }} </td> <td> {{ obj.password }} </td> <td> {{ obj.age }} </td> <td> <!-- 非常巧妙 --> <a href="/info/delete?nid={{ obj.id }}">删除</a> </td> </tr> {% endfor %} </tbody> </table> <!-- jQuery文件。务必在bootstrap.min.js 之前引入 --> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> </body> </html>
views.py中的info_add函数
def info_add(request): if request.method == 'GET': return render(request, 'info_add.html') else: # 获取用户提交的数据 name = request.POST.get("name") password = request.POST.get("pwd") age = request.POST.get("age") # 如果name或者password或者age有一个为空,就无法加入到数据库里面 if name=='' or password =='' or age=='': err_msgs = ['用户名不能为空', '密码不能为空', '年龄不能为空'] name_err, pwd_err, age_err = '', '', '' if name == '': name_err = err_msgs[0] if password == '': pwd_err = err_msgs[1] if age == '': age_err = err_msgs[2] return render(request, 'info_add.html', {"name_err":name_err, "pwd_err":pwd_err, "age_err":age_err}) # 添加到数据库 UserInfo.objects.create(name=name, password=password, age = age) # 自动跳转 return redirect("/info/list/")
info_add.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 新 Bootstrap 核心 CSS 文件 --> <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <style> </style> </head> <body> <form class="form-horizontal" role="form" action="/info/add/" method="post"> {% csrf_token %} <div class="form-group"> <label for="name" class="col-sm-2 control-label">用户名</label> <div class="col-sm-10"> <input type="text" class="form-control" id="name" name="name" placeholder="请输入名字"> </div> <label for="name_err" class="col-sm-2 control-label"></label> <div class="col-sm-10" style="color:red" name="name_err"> {{ name_err }} </div> </div> <div class="form-group"> <label for="pwd" class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input type="text" class="form-control" id="pwd" name="pwd" placeholder="请输入密码"> </div> <label for="pwd_err" class="col-sm-2 control-label"> </label> <div class="col-sm-10" style="color:red" name="pwd_err"> {{ pwd_err }} </div> </div> <div class="form-group"> <label for="age" class="col-sm-2 control-label">年龄</label> <div class="col-sm-10"> <input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄"> </div> <label for="age_err" class="col-sm-2 control-label"></label> <div class="col-sm-10" style="color:red" name="age_err"> {{ age_err }} </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <div class="checkbox"> <label> <input type="checkbox">请记住我 </label> </div> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">登录</button> </div> </div> </form> <!-- jQuery文件。务必在bootstrap.min.js 之前引入 --> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> </body> </html>
views.py中的info_delete函数
def info_delete(request):
nid = request.GET.get("nid")
UserInfo.objects.filter(id=nid).delete()
return redirect("/info/list/")
当开发项目的时候,网页的导航栏等信息在多个网页中是相同的,所以为了降低每个网页的代码量,可以将网页中的相同的元素抽取出来,形成一个html文件,然后其他的网页继承该模板,在该模板上增加内容即可。
例如: 模板文件 layout.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 新 Bootstrap 核心 CSS 文件 --> <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <style> </style> </head> <body> {% block content %} {% endblock %} <!-- jQuery文件。务必在bootstrap.min.js 之前引入 --> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> </body> </html>
继承文件:list.html
{% extends 'layout.html' %} {% block content %} <body> <a href="/info/add">添加</a> <table border="1" class="table table-hover"> <thead> <tr> <th>ID</th> <th>姓名</th> <th>密码</th> <th>年龄</th> </tr> </thead> <tbody> {% for obj in data_list %} <tr> <td> {{ obj.id }} </td> <td> {{ obj.name }} </td> <td> {{ obj.password }} </td> <td> {{ obj.age }} </td> <td> <!-- 非常巧妙 --> <a href="/info/delete?nid={{ obj.id }}">删除</a> </td> </tr> {% endfor %} </tbody> </table> {% endblock %}
则在list.html文件中自动使用layout.html中的内容,将两块内容自动拼接。
如果想要不仅在网页的<body></body>
部分增添内容,还想要在<style></style>,<script></script>
等中添加内容,只需要多定义几个变量即可,示例如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 新 Bootstrap 核心 CSS 文件 --> <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> {% block style %} {% endblock %} </head> <body> {% block content %} {% endblock %} <!-- jQuery文件。务必在bootstrap.min.js 之前引入 --> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> {% block script %} {% endblock %} </body> </html>
可以看到,可以在任何地方自行添加要补充的内容,同时要注意 {}中的block这个是不能变的,block后面跟的是自定义的变量,变量名自定义
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Index</title> <!-- 新 Bootstrap 核心 CSS 文件 --> <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-default"> <div class="container"> <!-- Brand and toggle get grouped for better mobile display --> <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> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li><a href="#">部门管理</a></li> <li><a href="#">部门管理</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">poker <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <!-- 增加部分 --> <div> {% block content %}{% endblock %} </div> <!-- jQuery文件。务必在bootstrap.min.js 之前引入 --> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> </body> </html>
path('depart/list/', views.depart_list)
- 1
def depart_list(request):
"""部门列表"""
depart_list = Department.objects.all()
return render(request, "depart_list.html", {"depart_list": depart_list})
{% extends 'depart_layout.html' %} <!-- 增加部分 --> {% block content %} <div class="container"> <div style="margin-bottom: 10px"> <a class="btn btn-primary" href="/depart/add/" target="_blank">新建部门</a> </div> <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading"> <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;"></span> <span> 部门列表 </span> </div> <!-- Table --> <table class="table table-vordered"> <thead> <tr> <th>ID</th> <th>名称</th> <th>操作</th> </tr> </thead> <tbody> {% for obj in depart_list %} <tr> <th>{{ 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> {% endblock %}
path('depart/add/', views.depart_add)
- 1
def depart_add(request):
"""添加部门"""
if request.method == "GET":
return render(request, "depart_add.html")
else:
# 获取用户提交的部门数据
depart_title = request.POST.get("depart_title")
# 保存用户提交的部门数据
Department.objects.create(title=depart_title)
return redirect("/depart/list/")
{% extends 'depart_layout.html' %} <!-- 增加部分 --> {% block content %} <div class="container"> <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading"> <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;"></span> <span> 新建部门 </span> </div> <div class="panel-body"> <form action="/depart/add/" method="post"> {% csrf_token %} <div class="form-group"> <label>部门名称</label> <input type="text" class="form-control" placeholder="部门名称" name="depart_title" /> </div> <button type="submit" class="btn btn-primary">保存</button> </form> </div> </div> </div> {% endblock %}
path('depart/delete/', views.depart_delete)
- 1
def depart_delete(request):
"""部门删除"""
nid = request.GET.get('nid')
Department.objects.filter(id=nid).delete()
# 重定向回部门列表
return redirect('/depart/list/')
<a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{ obj.id }}">删除</a>
path('depart/<int:nid>/edit/', views.depart_edit)
- 1
注: 其中<int:nid>
表示一个变量名为nid 的一个int变量,也就是如果要访问edit页面,必须在该位置传入一个int型整数
注:这里,函数的参数列表里面增加了一个nid变量,这正好对应了网页链接中的<int:nid>
表示的整数,
def depart_edit(request, nid):
"""部门编辑"""
if request.method=="GET":
# 根据nid获取数据
# 这里如果不加first()函数,获取到的数据是一个列表类型,所以需要first函数获取第一个值
row_object = Department.objects.filter(id=nid).first()
return render(request, 'depart_edit.html', {"row_object":row_object})
else:
# 如果是POST请求保存修改
depart_title = request.POST.get('depart_title')
Department.objects.filter(id=nid).update(title=depart_title)
# 重定向回部门列表
return redirect('/depart/list/')
{% extends 'depart_layout.html' %} <!-- 增加部分 --> {% block content %} <div class="container"> <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading"> <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;"></span> <span> 编辑部门 </span> </div> <div class="panel-body"> <form action="/depart/{{ row_object.id }}/edit/" method="post"> {% csrf_token %} <div class="form-group"> <label>部门名称</label> <!-- 这里 value就是默认值 --> <input type="text" class="form-control" placeholder="部门名称" name="depart_title" value="{{row_object.title }}" /> </div> <button type="submit" class="btn btn-primary">保存</button> </form> </div> </div> </div> {% endblock %} <!-- jQuery文件。务必在bootstrap.min.js 之前引入 --> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> </body> </html>
<a class="btn btn-primary btn-xs" href="/depart/{{ obj.id }}/edit/">编辑</a>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。