跟b站武沛齐老师的视频学习
对学习过程进行一些记录以便复习 同时自我督促 :D冲鸭视频链接: 15天django入门到放弃-哔哩哔哩.
前言
之前所学 Django 的两个非主流做法:
- 自己创建 app —— Django 有特别的语句用于创建 app。
- 使用 pymysql —— Django 框架中自带 ORM,不需要自己写 sql 语句。
重新认识框架
创建 app:python manage.py startapp appname
结构:
- admin Django 自带后台管理相关配置
- models 写类,根据类创建数据库表
- tests 单元测试
- views 业务处理,可以是一个文件夹
路由系统
正则表达式
因为 GET 传参不利于 SEO(搜索引擎优化),修改传参方式:
原:静态路由
http://127.0.0.1:8000/edit/?nid=1
path(‘edit/’, views.edit),
def edit(request):
request.GET.get(‘nid’)
return HttpResponse(’…’)
现:动态路由
http://127.0.0.1:8000/edit/1
path(‘edit/(\w+)’, views.edit),
def edit(request, nid):
return HttpResponse(’…’)
几种表达方式:
url(r'^edit/(\w+)/(\w+)/', views.edit),
url(r'^edit/(?P<a1>\w+)/(?P<a2>\w+)/', views.edit),
url(r'^edit', views.edit), # editlsdfgag
url(r'^edit$', views.edit), # 终止符
url(r'^edit/(\w+).html', views.edit), # 伪静态
路由分发
urls.py
:
url(r'^app01/', include('app01.urls')),
app01 urls.py
:
url(r'^index.html$/', views.index),
总路由
...
`url(r'^', function),
]
def function(request):
...
别名反生成URL
后端:
url(r'^index.html$/', views.index, name='n1'),
def xxx(request):
v = reverse('n1') # v = '/index/'
url(r'^index/(\w+)/', views.index, name='n2'),
def xxx(request):
v = reverse('n2', args=(1, ) # v = '/index/1/'
url(r'^index/?P<a>(\w+)/', views.index, name='n3'),
def xxx(request):
v = reverse('n3', kwargs={'a1': 111} # v = '/index/111/'
前端:
<form method="POST" action="{% url 'n1' %}">
<form method="POST" action="{% url 'n2' i %}">
ORM 操作
Http请求:
url -> 视图(模板 + 数据)
ORM
操作表:创建表、修改表、删除表
操作数据行:增、删、改、查
不直接连接数据库,利用 pymysql 第三方工具连接数据库
默认:
SQLlite
默认:mysql -> MYSQLDB(修改 django 默认连接 MySQL 方式)
基础配置及建表
settings.py
中:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
改为:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'dbname',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': 'localhost',
'PORT': 3306,
}
}
在 __init__.py
中添加:
import pymysql
pymysql.install_as_MySQLdb()
在 settings.py
INSTALLED_APPS
中注册app;
在 app
models.py
中写表操作:
from django.db import models
class UserInfo(models.Model):
nid = models.BigAutoField(primary_key=True) # 可以不写,会自动生成一列 int 型自增主键 id
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
执行命令创建数据表:
python manage.py makemigrations
python manage.py migrate
若在已经有数据的表中增加列的两种方法:
age = models.IntegerField(null=True) # 可以为空
age = models.IntegerField(default=1) # 设置默认值
若设置外键,Django 会自动加上 _id:
from django.db import models
class UserGroup(models.Model):
title = models.CharField(max_length=32)
class UserInfo(models.Model):
nid = models.BigAutoField(primary_key=True)
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
age = models.IntegerField(default=1)
#ug_id
ug = models.ForeignKey(to="UserGroup", on_delete=models.DO_NOTHING, null=True)
migrations 文件夹中存放了每一次操作的记录:
表操作
def index(request):
from app01 import models
# 新增
models.UserGroup.objects.create(title='销售部')
models.UserInfo.objects.create(username='root', password='pwd', age=18, ug_id=1) # 注意:ug 代表一行数据,赋值时应给 ug_id 赋值
# 查找
group_list = models.UserGroup.objects.all() # 得到的数据形如: <QuerySet [<UserGroup: UserGroup object>, <UserGroup: UserGroup object>]>
group_list = models.UserGroup.objects.filter(id=1, title='销售部') # and关系
group_list = models.UserGroup.objects.filter(id__gt=1) # 小于 __lt
for row in group_list:
print(row.id, row.title) # 1 销售部
result = models.UserGroup.objects.filter(id=1).first() # 只取一个,得到数据为 object 类型
# 删除
models.UserGroup.objects.filter(id=1).delete()
# 更新
models.UserGroup.objects.filter(id=1).update('公关部')
关联(对象方式):
# 正向操作 外键字段
obj = models.UserInfo.objects.all().first()
print(obj.name, obj.age, obj.ut.title) # 可以一直关联下去
# 反向操作 表名_set
obj = models.UserType.objects.all().first()
for row in obj.userinfo_set.all():
print(row.name, row.age)
取部分列(values 方式):
# 正向
models.UserInfo.objects.all() # 得到对象
models.UserInfo.objects.all().values('id', 'name') # 得到字典
models.UserInfo.objects.all().values_list('id', 'name') # 得到元组
# 后两种方式跨表取值:
models.UserInfo.objects.all().values('ut__title')
# 反向
models.UserType.objects.values('id', 'title', 'userinfo') # 小写的表名 取到id
models.UserType.objects.values('id', 'title', 'userinfo__name')
视图函数
CBV( class base views)
FBV(function base views)
re_path(r"^login.html/$", views.Login.as_view()),
from django.views import View
class Login(View):
def dispatch(self, request, *args, **kwargs):
print('before')
obj = super(Login, self).dispatch(request, *args, **kwargs)
print('after')
return obj
def get(self, request):
return HttpResponse('login.get')
def post(self, request):
return HttpResponse('login.post')
分页
Django 自带
def index(request):
# for i in range(300):
# name = "root" + str(i)
# models.UserInfo.objects.create(username=name, age=0)
from django.core.paginator import Paginator, Page, EmptyPage, PageNotAnInteger
current_page = request.GET.get('page')
user_list = models.UserInfo.objects.all()
paginator = Paginator(user_list, 10)
# per_page: 每页显示条目数量
# count: 数据总个数
# num_pages:总页数
# page_range:总页数的索引范围,如: (1,10),(1,200)
# page: page对象
try:
posts = paginator.page(current_page)
except EmptyPage as e:
posts = paginator.page(1)
except PageNotAnInteger as e:
posts = paginator.page(1)
# has_next 是否有下一页
# next_page_number 下一页页码
# has_previous 是否有上一页
# previous_page_number 上一页页码
# object_list 分页之后的数据列表
# number 当前页
# paginator paginator对象
return render(request, 'index.html', {'posts': posts})
index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户列表</h1>
<ul>
{% for row in posts.object_list %}
<li>{{ row.username }}</li>
{% endfor %}
</ul>
<div>
{% if posts.has_previous %}
<a href="/index.html/?page={{ posts.previous_page_number }}">上一页</a>
{% endif %}
{% for num in posts.paginator.page_range %}
<a href="/index.html/?page={{ num }}">{{ num }}</a>
{% endfor %}
{% if posts.has_next %}
<a href="/index.html/?page={{ posts.next_page_number }}">下一页</a>
{% endif %}
</div>
</body>
</html>
自己写分页
class PageInfo(object):
def __init__(self, current_page, all_count, per_page):
"""
:param current_page: 当前页码
:param all_count: 总个数
:param per_page: 每页个数
"""
try:
self.current_page = int(current_page)
except Exception as e:
self.current_page = 1
self.per_page = per_page
# 计算总页数
all_pager, b = divmod(all_count, per_page)
if b:
self.all_pager = all_pager + 1
def start(self):
return ((self.current_page - 1) * self.per_page)
def end(self):
return (self.current_page * self.per_page)
def pager(self):
page_list = []
for i in range(1, self.all_pager):
if i == self.current_page:
temp = "<a style='display:inline-block; padding:5px; margin:5px; background-color:red;' href='/custom.html?page=%s'>%s </a>" % (i, i)
else:
temp = "<a style='display:inline-block; padding:5px; margin:5px;' href='/custom.html?page=%s'>%s </a>" % (i, i)
page_list.append(temp)
return ''.join(page_list) # 将列表中每个元素拼接
def custom(request):
# 获取总个数
all_count = models.UserInfo.objects.all().count()
current_page = request.GET.get('page')
page_info = PageInfo(current_page, all_count, 10)
user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()]
return render(request, 'custom.html', {'user_list': user_list, 'page_info': page_info})
custom.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户列表</h1>
<ul>
{% for row in user_list %}
<li>{{ row.username }}</li>
{% endfor %}
</ul>
{{ page_info.pager|safe }}
</body>
</html>
![](https://i-blog.csdnimg.cn/blog_migrate/5165fccb72db80b819bfd1c1731ecdf8.png)
完善并整合成一个 UTIL,utils.pager
:
class PageInfo(object):
def __init__(self, current_page, all_count, per_page, show_page, base_url):
"""
:param current_page: 当前页码
:param all_count: 总个数
:param per_page: 每页个数
"""
try:
self.current_page = int(current_page)
except Exception as e:
self.current_page = 1
self.per_page = per_page
self.show_page = show_page
self.base_url = base_url
# 计算总页数
all_pager, b = divmod(all_count, per_page)
if b:
self.all_pager = all_pager + 1
def start(self):
return ((self.current_page - 1) * self.per_page)
def end(self):
return (self.current_page * self.per_page)
def pager(self):
# page_list = []
# for i in range(1, self.all_pager):
# if i == self.current_page:
# temp = "<a style='display:inline-block; padding:5px; margin:5px; background-color:red;' href='/custom.html?page=%s'>%s </a>" % (i, i)
# else:
# temp = "<a style='display:inline-block; padding:5px; margin:5px;' href='/custom.html?page=%s'>%s </a>" % (i, i)
# page_list.append(temp)
# return ''.join(page_list) # 将列表中每个元素拼接
page_list = []
half = int((self.show_page - 1)/2)
if self.show_page > self.all_pager:
begin = 1
stop = self.all_pager + 1
else:
begin = self.current_page - half
begin = max(begin, 1)
stop = begin + self.show_page
stop = min(stop, self.all_pager + 1)
begin = stop - self.show_page
if self.current_page <= 1:
pre = "<li><a href='#'>上一页 </a></li>"
else:
pre = "<li><a href='%s?page=%s'>上一页 </a></li>" % (self.base_url, self.current_page - 1)
page_list.append(pre)
for i in range(begin, stop):
if i == self.current_page:
temp = "<li class='active'><a href='%s?page=%s'>%s </a></li>" % (self.base_url, i, i)
else:
temp = "<li><a href='%s?page=%s'>%s </a></li>" % (self.base_url, i, i)
page_list.append(temp)
if self.current_page >= self.all_pager:
next = "<li><a href='%s?page=#'>下一页 </a>>/li>" % (self.base_url)
else:
next = "<li><a href='%s?page=%s'>下一页 </a></li>" % (self.base_url, self.current_page + 1)
page_list.append(next)
return ''.join(page_list) # 将列表中每个元素拼接
调用:
def custom(request):
# 获取总个数
all_count = models.UserInfo.objects.all().count()
current_page = request.GET.get('page')
page_info = PageInfo(current_page, all_count, 10, 5, '/custom.html')
user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()]
return render(request, 'custom.html', {'user_list': user_list, 'page_info': page_info})
前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/plugins/bootstrap-3.4.1-dist/css/bootstrap.css">
</head>
<body>
<h1>用户列表</h1>
<ul>
{% for row in user_list %}
<li>{{ row.username }}</li>
{% endfor %}
</ul>
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{{ page_info.pager|safe }}
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</body>
</html>
![](https://i-blog.csdnimg.cn/blog_migrate/dca8dfa36971635e22a5c75cc16d0230.png)