Django课堂笔记001
第1次-搭建环境
进入workspace_python目录,创建Django项目
django-admin startproject chapter04
进入chapter04目录,创建应用
python manage.py startapp booklist
第2次-路由系统
第3次-模型
定义模型
from django.db import models
# 定义books应用书籍模型类
class BookInfo(models.Model):
name = models.CharField(max_length=20, verbose_name="名称")
pub_date = models.DateField(verbose_name="发布日期")
readCount = models.IntegerField(default=0, verbose_name="阅读量")
commentCount = models.IntegerField(default=0, verbose_name="评论量")
is_delete = models.BooleanField(default=False, verbose_name="逻辑删除")
# 将查询结果以字符串形式显示
def __str__(self):
return self.name
class Demo(models.Model):
car_name = models.CharField(max_length=32, verbose_name='车牌号')
park_name = models.CharField(max_length=32)
come_date = models.CharField(max_length=32)
leave_date = models.CharField(max_length=32)
time = models.CharField(max_length=32)
# 将查询结果以字符串形式显示
def __str__(self):
return self.name
总结:
- Django中的模型用Python类的形式来定义
- 这个模型类定义在应用的models.py中,并且要继承models.Model类
- 非抽象的模型对应一张数据表
生成迁移文件
python manage.py makemigrations
输出内容
PS D:\workspace_python\chapter03> python manage.py makemigrations
Migrations for 'books':
books\migrations\0001_initial.py
- Create model BookInfo
- Create model Demo
会根据models.py文件生成一个中间文件,并保存在migrations目录中,如0001_initial.py
执行迁移文件
python manage.py migrate
插入数据
在对应的views.py文件中定义如下视图函数
def db_create(request):
models.Demo.objects.create(car_name='豫A12345', come_date='进来时间为3月2日', leave_date='离开日期为3月4日', time='1')
return HttpResponse("insert OK")
urls.py中添加
path('dbinsert/', views.db_create)
总结:
第4次-模板
准备环境
进入workspace_python目录,创建Django项目
django-admin startproject chapter04
进入chapter04目录,创建应用
python manage.py startapp booklist
将应用添加到settings.py的INSTALLEDAPP中
'booklist'
在booklist目录下views.py文件中创建一个视图函数test
from django.http import HttpResponse
def test(request):
return HttpResponse("test")
完成url与视频函数的映射
在booklist/urls.py中
from django.urls import path
from booklist import views
urlpatterns = [path('test/', views.test)]
在项目的urls.py的urlpatterns数组中添加如下
path('booklist/', include('booklist.urls'))
运行项目
python manage.py runserver
浏览器中输入url
http://127.0.0.1:8000/booklist/test/
变量的用法
第一步:定义视图函数
def checkfirst(request):
strlen = 'python'
num = 3
return render(request, 'test.html', {
'strlen': strlen, 'num': num})
在booklist下urls.py中配置子路由
from django.urls import path
from booklist import views
urlpatterns = [
path('test/', views.test),
path('checkfirst/', views.checkfirst)
]
第二步:项目目录下创建templates文件夹,在文件夹里创建test.html文件
<body>
<h1>内置过滤器1</h1>
<p>使用前{
{ strlen }}</p>
<p>使用后{
{ strlen|capfirst}}</p>
</body>
第四步:配置模板路径
在setting.py中,在TEMPLATES里添加路径
'DIRS': ['templates'],
第五步,启动服务器测试
python manage.py runserver
add过滤器的用法
test.html文件里添加,
<h1>一个值使用add过滤器</h1>
<p>使用前:{
{ num }}</p>
<p>使用后:{
{ num|add:4}}</p>
官方内置过滤器
https://docs.djangoproject.com/zh-hans/4.1/ref/templates/builtins/#filters
标签的使用
第一步,views.py文件里创建视图
class GF(object):
def __init__(self, name, age):
self.name = name
self.age = age
def chacktag(request):
data = {
'name': '张三',
'age': 25,
'likes': ['足球', '篮球', '排球'],
'teacher': {
'name': '李四',
'age': 50,
'sex': '男'
},
'gf': GF(name='王五', age=24)
}
return render(request, 'taguse.html', data)
第二步:在booklist应用下urls.py中配置子路由
path('taguse/',views.chacktag)
第三步,新建标签,taguse.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>标签的使用</h1>
{% if age < 18 %}
未成年
{% elif age == 18 %}
刚成年
{% else %}
已成年
{% endif %}
<h2>喜欢的球类</h2>
{% for like in likes %}
{
{ like }}
{% endfor %}
<h2>老师信息</h2>
{% for t in teacher.values %}
{
{ t }}
{% endfor %}
<h2>对象信息</h2>
姓名:{
{ gf.name }},年龄:{
{ gf.age }}
</body>
</html>
第四步,访问服务器,python manage.py runserver
taguse/
自定义过滤器
第一步在booklist应用下建立templatetags目录
这个目录必须是templatetags,不是这个名字会找不到定义的过滤器
第二步,在templatetags中创建filters.py,用于自定义过滤器和标签
from django import template
register = template.Library()
# 定义加过滤器
def examp(value, arg):
return value + arg
# 注册过滤器
register.filter('examp', examp)
第三步,使用自定义的过滤器
在taguse.html中使用
{
% load filters %}
先要使用load标签加载自定义标签
<p>年龄:{
{ age |examp:100 }}</p>
**注意:**如果有报异常,需要重启一下服务器
自定义标签
在上面的filters.py中增加自定义标签
# 自定义标签并注册
@register.simple_tag()
def current_time(format_str):
return datetime.now().strftime(format_str)
使用自定义标签
在taguse.html中增加下面代码
<h1>自定义标签</h1>
<p>日期时间:{% current_time '%b %d %Y %H:%M:%S' %}</p>
<p>now标签{% now 'jS F Y H:i' %}</p>
**注解:**标签的含义
https://m.w3schools.cn/django/ref_tags_now.asp
模板的继承
首先,templates下建立base.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<title>{% block title %}页面标题{% endblock %}</title>
</head>
<body>
{% block header %}
<h1>标题</h1>
{% endblock header %}
{% block main %}
<h2>页面内容</h2>
{% endblock %}
<br><br><br>
{% block footer %}
<div class="footer no-mp">
<div class="foot_link">
<a href="#">关于我们</a>
<span> | </span>
<a href="#">联系我们</a>
<span> | </span>
<a href="#">招聘人才</a>
<span> | </span>
<a href="#">友情链接</a>
</div>
<p>CopyRight © 2019 北京小鱼商业股份有限公司 All Rights Reserved</p>
<p>电话:010-****888 京ICP备*******8号</p>
</div>
{% endblock %}
</body>
</html>
然后,创建视图,views.py
def show_base_page(request):
return render(request, 'base.html')
创建子路由 path(‘base/’, views.show_base_page),
此时,浏览器访问base/,即可查看效果
然后定义一个继承该模板的子模版lists.html
{% extends 'base.html' %}
{% block title %}
列表页面
{% endblock %}
{% block header %}
<h1>书单</h1>
{% endblock header %}
{% block main %}
<a href="#">1.《鲁迅作品全集》</a><br>
<a href="#">2.《秋雨散文集》</a><br>
<a href="#">3.《黑暗森林》</a><br>
<a href="#">4.《月亮与六便士》</a><br>
{% endblock main %}
<br><br><br>
创建视图,
def show_page(request):
return render(request, 'lists.html')
添加路由
path('lists/', views.show_page),
此时,浏览器访问booklist/lists/,即可查看效果
第5次-视图
准备环境
创建django项目
django-admin startproject chapter05
创建goods应用
cd chapter05
python manage.py startapp goods
配置应用
在setting.py中,已安装app那里添加应用goods
配置主路由
chapter05的urls.py中
path('chapter05/', include('goods.urls')),
测试路由参数传递
1、定义视图函数
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
# 从url中接收参数id
def test(request, id):
s = '从url中接收来的str数据为:' + id;
print(s)
return HttpResponse(s)
2、在goods应用的urls.py中配置路由
from django.urls import path
from goods import views
urlpatterns = [
path('test/<str:id>/', views.test),
]
3、测试
http://127.0.0.1:8000/chapter05/test/1
展示商品
本质就是读取数据库中存取的商品数据,并在HTML中显示。
创建模型
goods/modles.py
from django.db import models
class Goods(models.Model):
"""商品SKU"""
# 可以利用null和blank属性使部分字段留空
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
name = models.CharField(max_length=50, verbose_name='名字')
price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='价格')
stock = models.IntegerField(default=0, verbose_name='库存')
sales = models.IntegerField(default=0, verbose_name='销量')
class Meta:
db_table = 'tb_goods'
verbose_name = '商品'
verbose_name_plural = verbose_name
def __str__(self):
return '%s: %s' % (self.id, self.name)
生成迁移文件并执行迁移
python manage.py makemigrations
python manage.py migrate
插入数据
利用数据文件goods.sql插入商品数据
INSERT INTO tb_goods (create_time, update_time, name, price, stock, sales) VALUES
('2019-09-11 17:28:21.804713', '2019-09-25 11:09:04.532866', 'Apple MacBook Pro 13.3英寸笔记本 银色', 11388, 5, 5),
('2019-09-12 06:53:54.575306', '2019-09-23 11:44:03.825103', 'Apple MacBook Pro 13.3英寸笔记本 深灰色', 11398, 0, 1),
('2019-09-14 02:14:04.599169', '2019-09-20 02:28:13.579856', 'Apple iPhone 11 Pro 256GB 香芋紫', 6499, 6, 4),
('2019-09-14 02:20:33.355996', '2019-09-14 17:27:12.736139', 'Apple iPhone 11 Plus 256GB 金色', 7988, 8, 2),
('2019-09-14 02:45:23.341909', '2019-09-14 17:27:17.181609', 'Apple iPhone 11 Plus 64GB 深空灰色', 6688, 10, 0),
('2019-09-14 02:49:40.912682', '2019-09-25 11:09:35.936530', 'Apple iPhone 11 Plus 256GB 深空灰色', 7988, 0, 5),
('2019-09-14 02:55:11.172604', '2019-09-14 17:27:28.772353', 'Apple iPhone 11 Plus 64GB 银色', 6688, 3, 0),
('2019-09-14 02:56:17.331169', '2019-09-14 17:27:34.536772', 'Apple iPhone 11 Plus 256GB 银色', 7988, 9, 1),
('2019-09-14 03:09:00.909709', '2019-09-14 17:27:40.624770', '华为 HUAWEI Pro 30 6GB+64GB 钻雕金', 3388, 4, 0),
( '2019-09-14 03:13:40.226704', '2019-09-25 11:06:55.087206', '华为 HUAWEI Pro 30 6GB+128GB 钻雕金', 3788, 3, 0),
( '2019-09-14 03:16:27.620102', '2019-09-25 10:56:51.267674', '华为 HUAWEI Pro 30 6GB+128GB 钻雕蓝', 3788, 5, 0),
( '2019-09-14 03:17:25.671905', '2019-09-14 17:28:06.649098', '华为 HUAWEI Pro 30 6GB+64GB 钻雕蓝', 3388, 5, 0),
( '2019-09-14 03:18:04.588296', '2019-09-14 17:28:23.886231', '华为 HUAWEI Pro 30 6GB+64GB 玫瑰金', 3388, 5, 0),
( '2019-09-14 03:19:03.691772', '2019-09-25 11:10:51.316291', '华为 HUAWEI Pro 30 6GB+128GB 玫瑰金', 3788, 0, 4),
( '2019-09-20 02:27:04.955931', '2019-09-20 02:27:04.956931', 'Apple iPhone 11 Pro 256GB 香芋紫', 6499, 6, 3);
配置模板
项目底下创建templates文件夹,
在settings.py中配置DIRS
在文件夹里创建goods.html文件
<html lang="en">
<head>
<title>商品列表</title>
</head>
<body>
<div>
<table id="myTable" cellpadding="1" cellspacing="0" border="1"
style="width:100%;max-width: 100%;margin-bottom: 20px ">
<caption align="top" style="font-size: 26px">商品列表</caption>
<thead>
<tr>
<th>编号</th>
<th>商品</th>
<th>价格</th>
<th>库存</th>
<th>销量</th>
<th>管理</th>
</tr>
</thead>
<tbody>
{% for row in goods %}
<tr align="center">
<td>{
{ forloop.counter }}</td>
<td>{
{ row.name }}</td>
<td>{
{ row.price }}</td>
<td>{
{ row.stock }}</td>
<td>{
{ row.sales }}</td>
<td>
<a href="/chapter05/delete/{
{ forloop.counter }}/">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</body>
</html>
定义视图函数
在应用的views.py文件中,定义get_goods()实现展示商品的功能。
from django import http
from django.template import loader
from goods.models import Goods
def test(request, id):
s = '从url中接收来的str数据为:' + id;
print(s)
return http.HttpResponse(s)
def get_goods(request):
"""展示商品"""
goods = Goods.objects.all() # 获取所有商品
context = {
'goods': goods,
}
template = loader.get_template('goods.html')
response = template.render(context, request)
return http.HttpResponse(response)
配置子路由
goods应用urls.py中添加
# 展示商品信息
path('goods/', views.get_goods),
测试
http://127.0.0.1:8000/chapter05/goods/
删除商品
本质就是获取用户要删除的商品id,在数据库中删除该id对应的记录,再重定向到商品列表页面,展示更新后的商品数据。
def del_goods(request, gid):
"""删除指定商品"""
print('---------即将删除gid为: ' + gid + '商品----------')
good = Goods.objects.get(id=gid)
good.delete()
return http.HttpResponseRedirect('/chapter05/goods/') # 重定向到首页
配置子路由
path('delete/<str:gid>/', views.del_goods),
新增商品
1、在html中新增表单模块
<div>
{# 表单一:添加 #}
<form method="post" action="/chapter05/add_goods/" cellpadding="1" cellspacing="0"
border="1">
{% csrf_token %}
<input type="submit" value="添加">
商品:<input type="text" name="good_name">
价格:<input type="text" name="good_price">
库存:<input type="text" name="good_stock">
销量:<input type="text" name="good_sales">
</form>
</div>
2、增加对应的视图函数
def add_goods(request):
"""添加商品"""
if request.method == 'POST':
good = Goods()
try:
good.name = request.POST.get('good_name')
good.price = request.POST.get('good_price')
good.stock = request.POST.get('good_stock')
good.sales = request.POST.get('good_sales')
good.save()
return redirect('/chapter05/goods/') # 快捷方式
except Exception as e:
return http.HttpResponseForbidden('数据错误')
3、配置子路由
path('add_goods/', views.add_goods)
4、测试
点击”添加“之后,注意列表的变化。
更新商品
1、在html中新增表单
<div>
{# 表单二:修改 #}
<form method="post" action="/chapter05/update/" cellpadding="1" cellspacing="0"
border="1">
{% csrf_token %}
<input type="submit" value="修改">
序号:<input type="text" name="good_num">
商品:<input type="text" name="good_name">
价格:<input type="text" name="good_price">
库存:<input type="text" name="good_stock">
销量:<input type="text" name="good_sales">
</form>
</div>
2、新增对应的视图函数
def update_goods(request):
"""编辑商品"""
print(request.method)
if request.method == 'POST':
goods = Goods.objects.all()
count = goods.count()
try:
num = request.POST.get('good_num')
for i in range(1, count + 1):
if i == int(num):
good = goods[i - 1]
good.name = request.POST.get('good_name')
good.price = request.POST.get('good_price')
good.stock = request.POST.get('good_stock')
good.sales = request.POST.get('good_sales')
good.save()
break
except Exception as e:
return http.HttpResponseForbidden('编辑失败')
return redirect('/chapter05/goods/')
3、配置子路由
path('update/', views.update_goods)
4、测试
修改之后,注意对应id一行数据的变化。
用类视图改造
以类的形式定义视图
class GoodsView(View):
def get(self, request):
return get_goods(request)
def post(self, request):
return add_goods(request)
配置路由
path('getorpost/', GoodsView.as_view())
注意这里的GoodsView.as_view(),它会根据请求的实际方式来决定调用get方法还是post方法
利用增加操作来修改为
<div>
{# 表单一:添加 #}
{# <form method="post" action="/chapter05/add/" cellpadding="1" cellspacing="0"#}
{# border="1">#}
<form method="post" action="/chapter05/getorpost/" cellpadding="1" cellspacing="0"
border="1">
{% csrf_token %}
<input type="submit" value="添加">
商品:<input type="text" name="good_name">
价格:<input type="text" name="good_price">
库存:<input type="text" name="good_stock">
销量:<input type="text" name="good_sales">
</form>
</div>
测试
http://127.0.0.1:8000/chapter05/getorpost/
第6次-后台管理系统admin
准备环境
1、创建django项目,应用
django-admin startproject chapter06
python manage.py startapp goods
在settings.py中注册goods应用
2、创建模型
goods/modles.py
from django.db import models
class Goods(models.Model):
"""商品SKU"""
# 可以利用null和blank属性使部分字段留空
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
name = models.CharField(max_length=50, verbose_name='名字')
price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='价格')
stock = models.IntegerField(default=0, verbose_name='库存')
sales = models.IntegerField(default=0, verbose_name='销量')
class Meta:
db_table = 'tb_goods'
verbose_name = '商品'
verbose_name_plural = verbose_name
def __str__(self):
return '%s: %s' % (self.id, self.name)
2、数据库迁移
python manage.py makemigrations
python manage.py migrate
创建管理员账号
python manage.py createsuperuser
Username: admin
Email address: admin@163.com #设置的邮箱为:[email protected]
Password: # 设置的密码为:12345678
Password (again):
Superuser created successfully.
设置系统语言
有以下两种方式:
- 在settings.py文件中将配置项LANGUAGE_CODE的值设置为“zh-Hans”。
- 在settings.py文件中将配置项MIDDLEWARE中添加中间件’django.middleware.locale.LocaleMiddleware’
将模型注册到后台管理系统
有两种注册模型的方式
在goods/admin.py中
装饰器注册
from django.contrib import admin
@admin.register(Goods)
class GoodsAdmin(admin.ModelAdmin):
pass
代码注册
from django.contrib import admin
from goods.models import Goods
class GoodsAdmin(admin.ModelAdmin):
pass
admin.site.register(Goods, GoodsAdmin)
设置应用名中文显示
在goods应用的_init__.py文件中添加如下设置,表示加载goods/apps.py文件中的GoodsConfig的配置信息。
default_app_config = 'goods.apps.GoodsConfig'
然后在goods/apps.py文件的GoodsConfig类中使用verbose_name设置应用的名称
class GoodsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'goods'
verbose_name = '商品'
管理数据库
列表页选项
下面几个选项均在goods/admin.py中GoodsAdmin类中添加
list_display选项
用于控制页面展示的字段,选项的值可以是元组,也可以是列表。
list_display = ('id', 'create_time', 'update_time', 'name', 'price', 'stock', 'sales',)
list_display_links选项
以链接形式展示字段
list_display_links = ('id', 'name',)
list_filter选项
list_filter = ('stock',)
list_per_page选项
list_per_page = 10
list_editable选项
页面是否可直接编辑
list_editable = ('name',)
编辑页选项
fields选项
用于控制编辑页要展示的字段,它的值是元组类型。
fields = ('name', 'price', 'stock',)
fields-set选项
对可编辑字段进行分组,不可与fields选项同时使用
fieldsets = (
('基本信息', {
'fields': ['name', 'stock', 'sales']}),
('价格信息', {
'fields': ['price']})
)
重写后台模板
(1)创建目录,templates和static,并在templates下创建admin目录;
(2)在templates/admin创建base_site.html,base_site.html代码如下
{% extends "admin/base.html" %}
{% load static %}
{% block title %}{
{ title }} | {
{ site_title|default:_('Django site admin') }}
{% endblock %}
{% block branding %}
<h1 id="site-name">
<a href="{% url 'admin:index' %}">
<!-- logo.png为网站logo图片-->
<img src="{% static 'logo.png' %}" height="40px"/>
</a>
</h1>
{% endblock %}
{% block nav-global %}{% endblock %}
在settings.py中配置模板路径
'DIRS': ['templates'],
(3)在setting.py文件中配置目录
STATIC_URL = 'static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
(4)把准备好的logo图片添加到static目录下边。
(5)运行看效果。
第7次-表单
准备环境
1、新建项目chapter07
django-admin startproject chapter07
2、新建应用goods
python manage.py startapp goods
3、在setting.py中,已安装app那里添加应用goods
4、项目底下创建templates文件夹,在文件夹里创建goods.html文件
在项目的setting.py文件中的BASE_DIR之后追加导包路径:
'DIRS': ['templates'],
goods.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>商品列表</title>
</head>
<body>
<div>
<table id="myTable" cellpadding="1" cellspacing="0" border="1"
style="width:100%;max-width: 100%;margin-bottom: 20px ">
<caption align="top" style="font-size: 26px">商品列表</caption>
<thead>
<tr>
<th>序号</th>
<th>名字</th>
<th>价格</th>
<th>库存</th>
<th>销量</th>
<th>管理</th>
</tr>
</thead>
<tbody>
{% for row in goods %}
<tr align="center">
<td>{
{ forloop.counter }}</td>
<td>{
{ row.name }}</td>
<td>{
{ row.price }}</td>
<td>{
{ row.stock }}</td>
<td>{
{ row.sales }}</td>
<td>
<a href="goods/{
{ row.id }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div>
{# 表单一:添加 #}
<form method="post" action="/" cellpadding="1" cellspacing="0"
border="1">
{% csrf_token %}
<input type="submit" value="添加">
商品:<input type="text" name="good_name">
价格:<input type="text" name="good_price">
库存:<input type="text" name="good_stock">
销量:<input type="text" name="good_sales">
</form>
</div>
<div>
{# 表单二:修改 #}
<form method="post" action="goods/" cellpadding="1" cellspacing="0"
border="1">
{% csrf_token %}
<input type="submit" value="修改">
序号:<input type="text" name="good_num">
商品:<input type="text" name="good_name">
价格:<input type="text" name="good_price">
库存:<input type="text" name="good_stock">
销量:<input type="text" name="good_sales">
</form>
</div>
</body>
</html>
5、在models里,实现商品管理需要用到商品模型类Goods
from django.db import models
class Goods(models.Model):
"""商品SKU"""
# 可以利用null和blank属性使部分字段留空
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
name = models.CharField(max_length=50, verbose_name='名字')
price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='价格')
stock = models.IntegerField(default=0, verbose_name='库存')
sales = models.IntegerField(default=0, verbose_name='销量')
class Meta:
db_table = 'tb_goods'
verbose_name = '商品'
verbose_name_plural = verbose_name
def __str__(self):
return '%s: %s' % (self.id, self.name)
6、生成迁移文件并执行迁移
python manage.py makemigrations
python manage.py migrate
7、在views.py文件里,展示商品和删除商品的逻辑。然后分别在类GoodView和UpdateDestoryGood中实现商品展示和删除的功能。views.py全部代码如下。
from django.shortcuts import render, redirect, reverse
from django.views import View
from django import http
from .models import Goods
# Create your views here.
class GoodView(View):
"""商品视图类"""
def get(self, request):
"""展示商品"""
goods = Goods.objects.all()
context = {
'goods': goods,
}
return render(request, 'goods.html', context)
def post(self, request):
"""添加商品"""
good = Goods()
try:
good.name = request.POST.get('good_name')
good.price = request.POST.get('good_price')
good.stock = request.POST.get('good_stock')
good.sales = request.POST.get('good_sales')
good.save()
# return redirect('/') # 快捷方式
return redirect(reverse('goods:info'))
except Exception as e:
return http.HttpResponseForbidden('数据错误')
class UpdateDestoryGood(View):
"""编辑或删除商品"""
def get(self, request, gid):
"""删除商品数据"""
try:
good = Goods.objects.get(id=gid)
good.delete()
except Exception as e:
return http.HttpResponseForbidden('删除失败')
return redirect(reverse('goods:info'))
def post(self, request, gid=0):
"""编辑商品"""
goods = Goods.objects.all()
count = goods.count()
try:
num = request.POST.get('good_num')
for i in range(1, count + 1):
if i == int(num):
good = goods[i - 1]
good.name = request.POST.get('good_name')
good.price = request.POST.get('good_price')
good.stock = request.POST.get('good_stock')
good.sales = request.POST.get('good_sales')
good.save()
break
except Exception as e:
return http.HttpResponseForbidden('编辑失败')
return redirect(reverse('goods:info'))
8、配置路由
(1)urls.py(保持根url不变)
from django.urls import path, include, re_path
re_path('^', include('goods.urls')),
(2)goods/urls.py
from django.urls import re_path
from . import views
app_name = 'goods'
urlpatterns = [
# 展示商品数据、添加商品
re_path(r'^$', views.GoodsView.as_view(), name='info'),
# 修改删除商品
re_path(r'^goods/(\d*)$', views.UpdateDestoryGood.as_view()),
]
基本概念补充
给URL命名
在path()函数或re_path()函数中使用参数name为URL命名,示例如下
urlpatterns = [
re_path(r'^$', views.GoodView.as_view(), name='info'),
]
反向解析
概念:通过URL的名字,获取到对应的URL。
方式:reverse(‘info’),
命名空间
在Django中,多个应用可能包含同名的URL,为了避免反向解析时产生混淆,可以命名空间来区分不同的应用。
只需在应用的urls.py文件中定义app_name变量,便可指定当前应用的命名空间,格式为“app_name=URL名称”
使用正则表达式匹配路由
语法格式
re_path(r'^goods/(\d*)$', views.UpdateDestoryGood.as_view())
类视图
假设来自同一URL的GET和POST请求,分别以函数视图和类视图来实现
函数视图的方式
from django.http import HttpResponse
def my_view(request):
if request.method == 'GET':
return HttpResponse('POST')
elif request.method == 'POST':
return HttpResponse('POST')
类视图的方式
from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self,request):
return HttpResponse('POST')
def post(self,request):
return HttpResponse('POST')
插入数据
利用数据文件goods.sql插入商品数据,
INSERT INTO tb_goods (create_time, update_time, name, price, stock, sales) VALUES
('2019-09-11 17:28:21.804713', '2019-09-25 11:09:04.532866', 'Apple MacBook Pro 13.3英寸笔记本 银色', 11388, 5, 5),
('2019-09-12 06:53:54.575306', '2019-09-23 11:44:03.825103', 'Apple MacBook Pro 13.3英寸笔记本 深灰色', 11398, 0, 1),
('2019-09-14 02:14:04.599169', '2019-09-20 02:28:13.579856', 'Apple iPhone 11 Pro 256GB 香芋紫', 6499, 6, 4),
('2019-09-14 02:20:33.355996', '2019-09-14 17:27:12.736139', 'Apple iPhone 11 Plus 256GB 金色', 7988, 8, 2),
('2019-09-14 02:45:23.341909', '2019-09-14 17:27:17.181609', 'Apple iPhone 11 Plus 64GB 深空灰色', 6688, 10, 0),
('2019-09-14 02:49:40.912682', '2019-09-25 11:09:35.936530', 'Apple iPhone 11 Plus 256GB 深空灰色', 7988, 0, 5),
('2019-09-14 02:55:11.172604', '2019-09-14 17:27:28.772353', 'Apple iPhone 11 Plus 64GB 银色', 6688, 3, 0),
('2019-09-14 02:56:17.331169', '2019-09-14 17:27:34.536772', 'Apple iPhone 11 Plus 256GB 银色', 7988, 9, 1),
('2019-09-14 03:09:00.909709', '2019-09-14 17:27:40.624770', '华为 HUAWEI Pro 30 6GB+64GB 钻雕金', 3388, 4, 0),
( '2019-09-14 03:13:40.226704', '2019-09-25 11:06:55.087206', '华为 HUAWEI Pro 30 6GB+128GB 钻雕金', 3788, 3, 0),
( '2019-09-14 03:16:27.620102', '2019-09-25 10:56:51.267674', '华为 HUAWEI Pro 30 6GB+128GB 钻雕蓝', 3788, 5, 0),
( '2019-09-14 03:17:25.671905', '2019-09-14 17:28:06.649098', '华为 HUAWEI Pro 30 6GB+64GB 钻雕蓝', 3388, 5, 0),
( '2019-09-14 03:18:04.588296', '2019-09-14 17:28:23.886231', '华为 HUAWEI Pro 30 6GB+64GB 玫瑰金', 3388, 5, 0),
( '2019-09-14 03:19:03.691772', '2019-09-25 11:10:51.316291', '华为 HUAWEI Pro 30 6GB+128GB 玫瑰金', 3788, 0, 4),
( '2019-09-20 02:27:04.955931', '2019-09-20 02:27:04.956931', 'Apple iPhone 11 Pro 256GB 香芋紫', 6499, 6, 3);
使用表单类
1、在goods应用中创建forms.py,在其中定义表单类,代码如下:
from django import forms
from django.forms import ModelForm
from django.forms import formset_factory
from . import models
from .models import Goods
class GoodForm(ModelForm):
class Meta:
model = Goods
fields = ['name', 'price', 'sales', 'stock']
2、添加
<div>
<form method="post" action="/">
{% csrf_token %}
<input type="submit" value="添加">
{
{ form }}
</form>
</div>
3、
<div>
<form method="post" action="goods/" cellpadding="1" cellspacing="0" border="1">
{% csrf_token %}
<input type="submit" value="修改">
序号: <input type="text" name="good_num">
{
{ form }}
</form>
</div>
from django import http
from django.shortcuts import render, redirect
# Create your views here.
from django.urls import reverse
from django.views import View
from goods.form import GoodForm
from goods.models import Goods
class GoodsView(View):
"""商品视图类"""
# 查询所有商品
def get(self, request):
# goods = Goods.objects.all()
# context = {'goodsList': goods}
# return render(request, 'goods.html', context)
# 使用表单
goods = Goods.objects.all()
form = GoodForm()
context = {
'goods': goods,
'form': form,
}
return render(request, 'goods.html', context)
def post(self, request):
# 创建空的商品对象
# print(request.POST)
# goods = Goods()
# goods.sales = request.POST.get("good_sales")
# goods.name = request.POST.get("good_name")
# goods.price = request.POST.get("good_price")
# goods.stock = request.POST.get("good_stock")
# goods.save()
# print("反向解析:" + reverse('goods:info'))
# return redirect('goods:info')
# 使用表单
good = Goods()
# 使用已提交的数据实例化NameForm
form = GoodForm(request.POST)
# 判断表单是否已验证,获取已验证的数据
if form.is_valid():
good_data = form.cleaned_data
good.name = good_data['name']
good.price = good_data['price']
good.stock = good_data['stock']
good.sales = good_data['sales']
try:
good.save()
except:
return http.HttpResponseForbidden('数据错误')
return redirect(reverse('goods:info'))
class UpdateDestoryGood(View):
"""删除和修改的视图类"""
def get(self, request, gid):
print('gid=' + gid)
goods = Goods.objects.get(id=gid)
goods.delete()
return redirect('goods:info')
def post(self, request, gid):
# 使用模板
# goods = Goods.objects.all()
# count = goods.count()
#
# num = request.POST.get('good_num') # 取到序号
# for i in range(1, count + 1):
# if i == int(num):
# good = goods[i - 1]
# good.name = request.POST.get('good_name')
# good.price = request.POST.get('good_price')
# good.stock = request.POST.get('good_stock')
# good.sales = request.POST.get('good_sales')
# good.save()
#
# return redirect(reverse('goods:info'))
# 使用表单
goods = Goods.objects.all()
count = goods.count()
form = GoodForm(request.POST)
good_num = request.POST.get('good_num')
if form.is_valid():
good_data = form.cleaned_data
for i in range(1, count + 1):
if i == int(good_num):
good = goods[i - 1]
good.name = good_data['name']
good.price = good_data['price']
good.stock = good_data['stock']
good.sales = good_data['sales']
try:
good.save()
break
except Exception as e:
return http.HttpResponseForbidden('编辑失败')
return redirect(reverse('goods:info'))
第8次-身份验证
准备环境
1、新建项目chapter08
django-admin startproject chapter08
2、新建应用goods
python manage.py startapp auth_app
3、在setting.py中,已安装app那里添加应用auth_app
4、项目底下创建templates文件夹
在项目的setting.py文件中的BASE_DIR之后追加导包路径:
'DIRS': ['templates'],
5、生成迁移文件并执行迁移,
python manage.py makemigrations
python manage.py migrate
创建User对象
User类提供了创建普通用户的方法create_user()和创建超级用户的方法create()_superuser()。
python manage.py shell
创建普通用户
from django.contrib.auth.models import User
ordinary_user=User.objects.create_user('chapter08','[email protected]','chapter08')
ordinary_user.save()
创建超级用户
super_user=User.objects.create_superuser('admin','[email protected]','admin')
super_user.save()
默认情况下,通过User类创建的用户默认保存在数据表auth_user中。
可以使用User对象的set_password()方法可以修改用户的密码。
from django.contrib.auth.models import User
u=User.objects.get(username='admin')
u.set_password('admin')
u.save()
Web用户登录退出
auth_app/views.py
# 用户登录
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
class LoginView(View):
'''登录类视图'''
def get(self, request):
return render(request, "login.html")
def post(self, request):
"""Post方式,用户名登录"""
username = request.POST['username'] # 用户名
password = request.POST['password'] # 密码
user = authenticate(username=username, password=password)
if user is not None:
login(request, user) # 用户登录
return redirect(reverse('auth_app:index'))
else:
return render(request, 'login.html', {
'account_errmsg': '用户名或密码错误'})
class LogoutView(View):
"""退出登录"""
def get(self, request):
logout(request)
# 重定向到登录页面
return redirect(reverse('auth_app:login'))
# 首页相关视图函数
class IndexView(View):
'''进入首页'''
def get(self, request):
return render(request, 'index.html')
'''用于保护某个视图函数(函数视图或类视图)只能被已登录的用户访问。
当用户尝试访问该视图函数时,如果用户未登录,
则会被重定向到登录页面,要求其先进行登录操作。'''
@login_required()
def user_center(request):
return render(request, 'userinfo.html')
在templates文件夹下边新建login.html
<html lang="en" xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<div style="width:400px;vertical-align:middle;margin: 0 auto;">
<form method="post">
{% csrf_token %}
<td><label>用户名</label></td>
<td><input type="text" name="username" placeholder="请输入用户名"></td>
<td><label>密码</label></td>
<td><input type="password" name="password" placeholder="请输入密码"></td>
<div style="color:red">{
{ account_errmsg }}</div>
<input type="submit" name="登录" style="height: 30px">
</form>
</div>
</body>
</html>
templates文件夹下新建index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<div class="index">
{% if user.is_authenticated %}
{
{ current_time }}
欢迎您:<em>{
{user.username}}</em>>
<span>|</span>
<a href="{% url 'auth_app:logout' %}" class="quit">退出</a>>
<span>|</span>
<a href="{% url 'auth_app:info' %}">用户中心</a>
{% else %}
<a href="{% url 'auth_app:login' %}">登录</a>
{% endif %}
</div>
</body>
</html>
templates文件夹下新建userinfo.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>用户中心页面</p>
<a href="{% url 'auth_app:logout' %}">退出登录</a>
</body>
</html>
配置根路由和子路由
根路由urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('auth_app.urls', namespace='auth_app')),
]
在auth_app应用下新建urls.py文件,子路由auth_app/urls.py代码如下:
from django.urls import path, include
from auth_app import views
app_name = 'auth_app'
urlpatterns = [
path('login/', views.LoginView.as_view(), name='login'),
path('info/', views.user_center, name='info'),
path('index/', views.IndexView.as_view(), name='index'),
path('logout/', views.LogoutView.as_view(), name='logout')
]
访问服务器,python manage.py runserver
登录,在浏览器中输入 http://127.0.0.1:8000/login/
显示登录成功的首页信息,点击用户中心,进入用户中心界面。
状态保持
Cookie
cookie是什么
Cookie是一小段文本信息,当您访问某个网站时,网站会将一个Cookie文件放置在您的计算机内。Cookie通常包含个人偏好设置、购物车中的商品信息或者一些用于跟踪用户行为的数据。
Cookie的用途有:
-
记录用户登录状态,方便用户在下次访问时不必再次输入用户名和密码。
-
记录用户偏好设置,如语言和字体大小等。
-
跟踪用户行为以用于广告和分析:通过分析cookie中的数据,网站可以更好地了解用户的兴趣和行为,以便提供更好的服务。
-
用于购物车:通过管理Cookie,网站可以在用户离开网站时保存他们购物车中的商品列表,便于用户下次继续购买。
-
提供个性化内容:通过利用Cookie中的信息,网站可以为每个用户提供相关的个性化内容。
用法
1、创建cookie_app应用,并把应用名添加到setting.py的INASTALLED_APP中。
2、配置路由
并分别在根urls.py和cookie_app/urls.py文件中配置URL。
根urls.py
path('cookie_app/', include('cookie_app.urls')),
cookie_app/urls.py
from django.urls import path, include
from cookie_app import views
urlpatterns = [
path('set_cookie/', views.set_cookie),
path('show_cookie/', views.show_cookie),
path('delete_cookie/',views.delete_cookie)
]
cookie_app/views.py
from django.http import HttpResponse
def set_cookie(request):
"""设置cookie"""
response = HttpResponse('设置cookie')
response.set_cookie('python', 'chapter08', max_age=600)
return response
def show_cookie(request):
cookie = request.COOKIES.get('python')
return HttpResponse(f'cookie的值是:{
cookie}')
def delete_cookie(request):
response = HttpResponse('删除cookie')
response.delete_cookie('python')
return response
在浏览器地址栏中输入“http://127.0.0.1:8000/cookie_app/set_cookie/”,此时Cookie已经设置完成,点击浏览器中的“查看网站信息”图标可以打开正在使用的Cookie信息,查看已设置的Cookie。
最后,在浏览器地址栏中输入“http://127.0.0.1:8000/cookie_app/show_cookie/”,此时页面响应Cookie的值。
最后,在浏览器地址栏中输入“http://127.0.0.1:8000/cookie_app/delete_cookie/”,此时通过查看网站信息查看Cookie是否删除。
Session
Session是什么,用途
Session是一种存储在服务器端的用于记录用户信息的机制。HTTP是一种无状态协议,每个请求都是独立的,服务器不知道两个请求是否来自同一个客户端。为了解决这个问题,Session被引入。Session可以存储在服务器端的内存、硬盘、数据库等不同的位置,用户在访问网站时,服务器会为每个访问用户创建一个Session ID,用于标识该用户的Session对象,Session ID会被存储在客户端的Cookie中,并在每个HTTP请求中传递回服务器。
Session的主要用途是记录用户信息,例如用户的登录信息、购物车内容、浏览历史、个人设置等。通过Session,程序可以识别不同的用户,并为每个用户提供个性化的服务。Session还可以用于跨页面传递数据,例如将用户输入数据传递到下一个页面。Session也可以用于实现网站的安全机制,例如记录用户最后一次操作时间,强制用户在一定时间内重新登录,防止非法访问。
Session的用法
1、创建session_app应用,并把应用名添加到setting.py的INASTALLED_APP中。
2、创建视图
session_app/views.py
from django.http import HttpResponse
# Create your views here.
def set_session(request):
"""设置session的name和value,和"""
request.session['python'] = 'chapter08'
request.session.set_expiry(8) # 设置过期时间,8秒
return HttpResponse('写入session')
# 获取session
def get_session(request):
value = request.session.get('python')
return HttpResponse(f"Python对应的 value值为:{
value}")
根路由
path('session_app/', include('session_app.urls'))
session_app/urls.py
from django.urls import path
from session_app import views
urlpatterns = [
path('set_session/', views.set_session),
path('get_session/', views.get_session),
]
python manage.py runserver
在浏览器地址栏中输入http://127.0.0.1:8000/session_app/set_session/并按下回车键,此时Session已写入完成。可在数据库中查询到
在浏览器地址中输入“http://127.0.0.1:8000/session_app/get_session/”,可看到Session中key值为“Python”所对应的value值。