[Django项目案例]搭建用户与商品后台管理系统
1 搭建流程1.1 创建Django项目1.2 配置数据库1.3 创建app并载入Settings1.4 配置时区与静态文件夹1.5 定义模型类1.5.1 字段分析1.5.2 定义类对象
1.6 数据迁移1.7 创建测试数据1.8 Admin注册模型类1.9 创建超级管理员1.10 登录后台管理
2 Admin首页定制2.1 app名字与表名配置2.2 header和title配置
3 字段显示配置3.1 展示与过滤3.2 配置字段的verbose_name3.3 choices设置3.3.1 choices的规则3.3.2 choices的格式3.3.3 User中添加choices选项
3.4 配置增加页面
4 定制显示内容4.1 显示图片4.2 显示编辑和删除按钮
5 重写save_model5.1 问题与需求5.2 save_model函数的作用5.3 重写
6 图片上传6.1 配置上传文件路径6.2 定义upload地址
剩余内容
1 搭建流程
1.1 创建Django项目
1.2 配置数据库
1.3 创建app并载入Settings
1.4 配置时区与静态文件夹
1.5 定义模型类
1.5.1 字段分析
User用户表
字段名关键字
账号account真实姓名name头像img密码password性别gender电话tel邮箱email状态state创建时间createDatetime
Category商品种类表
字段名关键字
种类名称name上级分类pcategory种类路径path创建时间createDatetime
1.5.2 定义类对象
User表
import datetime
class User(models
.Model
):
account
= models
.CharField
(max_length
=32,unique
=True)
name
= models
.CharField
(max_length
=16,null
=True)
img
= models
.ImageField
(null
=True)
password
= models
.CharField
(max_length
=32)
gender
= models
.PositiveSmallIntegerField
(default
=0)
tel
= models
.CharField
(max_length
=11,null
=True)
email
= models
.EmailField
(null
=True)
state
= models
.PositiveSmallIntegerField
(default
=1)
createDatetime
= models
.DateTimeField
(default
=datetime
.datetime
.now
())
Category表
import datetime
class Category(models
.Model
):
name
= models
.CharField
(max_length
=32)
pcategory
= models
.ForeignKey
('self',null
=True,on_delete
=models
.CASCADE
)
path
= models
.URLField
(max_length
=255)
createDatetime
= models
.DateTimeField
(default
=datetime
.datetime
.now
())
1.6 数据迁移
python3.6.3 manage.py makemigrations
python3.6.3 manage.py migrate
注:因为我的python版本有多个,所以修改了python.exe
1.7 创建测试数据
复制一份manage .py 为 build_models .py加入内容,然后运行
import os
import sys
if __name__
== "__main__":
os
.environ
.setdefault
("DJANGO_SETTINGS_MODULE", "django_15_week2_proj1.settings")
try:
from django
.core
.management
import execute_from_command_line
except ImportError
:
try:
import django
except ImportError
:
raise ImportError
(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
execute_from_command_line
(sys
.argv
)
from user
.models
import *
from goods
.models
import *
import random
import datetime
from hashlib
import md5
def build_user():
name_s
= [ '张伟 ', '王伟 ', '王芳 ', '李伟 ', '王秀英 ', '李秀英 ', '李娜 ', '张秀英 ', '刘伟 ', '张敏 ', '李静 ', '张丽 ', '王静 ', '王丽 ', '李强 ', '张静 ', '李敏 ', '王敏 ', '王磊 ', '李军 ', '刘洋 ', '王勇 ', '张勇 ', '王艳 ', '李杰 ', '张磊 ', '王强 ', '王军 ', '张杰 ', '李娟 ', '张艳 ', '张涛 ', '王涛 ', '李明 ', '李艳 ', '王超 ', '李勇 ', '王娟 ', '刘杰 ', '王秀兰 ', '李霞 ', '刘敏 ', '张军 ', '李丽 ', '张强 ', '王平 ', '王刚 ', '王杰 ', '李桂英 ', '刘芳', ]
for i
in range(len(name_s
)):
User
(
account
='d' % i
,
name
= name_s
[i
],
img
='img/%s.png' % i
,
password
= md5
(str(i
).encode
('ascii')).hexdigest
(),
gender
= random
.choice
([0,1]),
tel
= str(random
.choice
([1346,1350,1351,1360,1370,1372,1380,1390,1391,1590,1881,])) + str(random
.randint
(1000000,9999999)),
email
= 'd@qq.com' % i
,
state
= random
.choice
([1] * 10 + [2] * 2 + [3] * 1),
createDatetime
= datetime
.datetime
.now
() - datetime
.timedelta
(days
=random
.randint
(0,60)),
).save
()
def build_category():
h1_s
= [
'手机',
'运动鞋',
]
h2_s
= [
['华为','苹果','小米','oppo','vivo','三星','魅族','联想','飞利浦','索尼','酷派'],
['耐克','安踏','特步','361','乔丹','贵人年','adidas']
]
pcategory
= []
for i
in range(len(h1_s
)):
pcategory
.append
(Category
.objects
.create
(name
=h1_s
[i
],path
='/category/%s' % (i
+ 1)))
for i
in range(len(h2_s
)):
for j
in range(len(h2_s
[i
])):
Category
.objects
.create
(name
=h2_s
[i
][j
],path
='/category/%s-%s' % (i
+1,j
+1),pcategory
=pcategory
[i
])
build_user
()
build_category
()
把头像图片文件放入static中 注:图片只要满足上图的命名规则就可以
1.8 Admin注册模型类
格式:
@admin.register(被注册的模型类名) class 类名任意(admin.ModelAdmin): pass
1.9 创建超级管理员
1.10 登录后台管理
开启服务器
python3.6.3 manage.py runserver 8002
访问admin
http://127.0.0.1:8002/admin/
登录
2 Admin首页定制
2.1 app名字与表名配置
goods/app. py:
from django
.apps
import AppConfig
class GoodsConfig(AppConfig
):
name
= 'goods'
verbose_name
= '商品管理'
goods/models .py:
from django
.db
import models
import datetime
class Category(models
.Model
):
name
= models
.CharField
(max_length
=32)
pcategory
= models
.ForeignKey
('self',null
=True,on_delete
=models
.CASCADE
)
path
= models
.URLField
(max_length
=255)
createDatetime
= models
.DateTimeField
(default
=datetime
.datetime
.now
())
class Meta():
verbose_name
= verbose_name_plural
= '商品分类'
同理user/app .py
verbose_name
= '用户管理'
同理user/models. py的User类中
class Meta():
verbose_name
= verbose_name_plural
= '用户信息'
修改后结果
2.2 header和title配置
在任意一个admin .py中
admin
.site
.site_header
= 'XXX公司后台管理'
admin
.site
.index_title
= '后台系统'
admin
.site
.site_title
= '管理'
3 字段显示配置
3.1 展示与过滤
http://127.0.0.1:8002/admin/user/user/原界面显示
@admin
.register
(User
)
class UserAdmin(admin
.ModelAdmin
):
list_display
= ['account','name','img','gender','tel','email','state','createDatetime']
list_filter
= ['state','gender','createDatetime']
search_fields
= ['account','name','tel']
结果
3.2 配置字段的verbose_name
class User(models
.Model
):
account
= models
.CharField
(max_length
=32,unique
=True,verbose_name
='账号')
name
= models
.CharField
(max_length
=16,null
=True,verbose_name
='真实姓名')
img
= models
.ImageField
(null
=True,verbose_name
='头像')
password
= models
.CharField
(max_length
=32,verbose_name
='密码')
gender
= models
.PositiveSmallIntegerField
(default
=0,verbose_name
='性别')
tel
= models
.CharField
(max_length
=11,null
=True,verbose_name
='手机号')
email
= models
.EmailField
(null
=True,verbose_name
='邮箱')
state
= models
.PositiveSmallIntegerField
(default
=1,verbose_name
='状态')
createDatetime
= models
.DateTimeField
(default
=datetime
.datetime
.now
(),verbose_name
='创建时间')
class Meta():
verbose_name
= verbose_name_plural
= '用户信息'
修改后界面显示
3.3 choices设置
3.3.1 choices的规则
choice中的内容Django中规定大写
3.3.2 choices的格式
choice
= (
(【数据库中存储的值】,【显示的名称】
),
(【数据库中存储的值】,【显示的名称】
),
)
3.3.3 User中添加choices选项
添加choice的字段有:性别:gender ;状态:state
修改内容: -
代码
class User(models
.Model
):
GENDER_ITEM
= (
(0,'男'),
(1,'女')
)
STATE_ITEM
= (
(1,'启动'),
(2,'禁用'),
(3,'后台管理员'),
)
account
= models
.CharField
(max_length
=32,unique
=True,verbose_name
='账号')
name
= models
.CharField
(max_length
=16,null
=True,verbose_name
='真实姓名')
img
= models
.ImageField
(null
=True,verbose_name
='头像')
password
= models
.CharField
(max_length
=32,verbose_name
='密码')
gender
= models
.PositiveSmallIntegerField
(default
=0,verbose_name
='性别',choices
=GENDER_ITEM
)
tel
= models
.CharField
(max_length
=11,null
=True,verbose_name
='手机号')
email
= models
.EmailField
(null
=True,verbose_name
='邮箱')
state
= models
.PositiveSmallIntegerField
(default
=1,verbose_name
='状态',choices
=STATE_ITEM
)
createDatetime
= models
.DateTimeField
(default
=datetime
.datetime
.now
(),verbose_name
='创建时间')
class Meta():
verbose_name
= verbose_name_plural
= '用户信息'
点击 增加 用户信息
3.4 配置增加页面
代码:
from django
.contrib
import admin
from user
.models
import *
@admin
.register
(User
)
class UserAdmin(admin
.ModelAdmin
):
list_display
= ['account','name','img','gender','tel','email','state','createDatetime']
list_filter
= ['state','gender','createDatetime']
search_fields
= ['account','name','tel']
fieldsets
= [
[
'基础配置',{
'fields':['account','name','password','tel','email','gender'],
}
],
[
'高级配置',{
'fields':['img','state','createDatetime'],
'classes':('collapse',)
}
]
]
显示结果
4 定制显示内容
4.1 显示图片
修改内容 注:show_img方法中的obj代表每一行对应的User模型类页面显示
4.2 显示编辑和删除按钮
代码改动 显示结果 reverse格式:
reverse(‘admin:【app名字】_【模型类名字小写】_【change|delete|add】’,args(obj.id,))
5 重写save_model
5.1 问题与需求
问题:
通过admin增加一个User,admin会把表单对象保存,那么存储在数据库中的password是用户或管理员提交的原始密码,并没有加密。 需求:
新增用户,密码自动md5加密修改用户密码,密码自动md5加密
5.2 save_model函数的作用
def save_model(self, request, obj, form, change):
request是请求对象obj是增加或修改的模型类对象
5.3 重写
第一版
def save_model(self
, request
, obj
, form
, change
):
if not obj
.id:
obj
.password
= md5
(obj
.password
.encode
('utf-8')).hexdigest
()
elif User
.objects
.get
(id=obj
.id).password
!= obj
.password
:
obj
.password
= md5
(obj
.password
.encode
('utf-8')).hexdigest
()
return super(UserAdmin
,self
).save_model
(request
,obj
,form
,change
)
第二版
def save_model(self
, request
, obj
, form
, change
):
if not obj
.id or User
.objects
.get
(id=obj
.id).password
!= obj
.password
:
obj
.password
= md5
(obj
.password
.encode
('utf-8')).hexdigest
()
return super(UserAdmin
,self
).save_model
(request
,obj
,form
,change
)
6 图片上传
6.1 配置上传文件路径
settings .py中
MEDIA_ROOT
= os
.path
.join
(BASE_DIR
,'static')
6.2 定义upload地址
如果不重写upload地址,提交的任何文件,都默认存储到MEDIA_ROOT中,文件名为上传的原文件名
需求:
上传的图片存储在static/img下,文件名由uuid生成,后缀保留原后缀
def uploadfile(instance
,filename
):
suffix
= filename
.rsplit
('.')[-1]
filename_new
= '%s.%s' % (uuid
.uuid4
().__str__
(),suffix
)
filepath
= os
.path
.join
('img',filename_new
)
return filepath
剩余内容
Category的内容和User类似,大家自己练习
重写filter重写query_set加载css和js
这些内容以后会在这篇博客上更新