[Django项目案例]搭建用户与商品后台管理系统
1 搭建流程
1.1 创建Django项目
1.2 配置数据库
1.3 创建app并载入Settings
1.4 配置时区与静态文件夹
1.5 定义模型类
1.5.1 字段分析
- User用户表
字段名 | 关键字 |
---|---|
账号 | account |
真实姓名 | name |
头像 | img |
密码 | password |
性别 | gender |
电话 | tel |
邮箱 | |
状态 | state |
创建时间 | createDatetime |
- Category商品种类表
字段名 | 关键字 |
---|---|
种类名称 | name |
上级分类 | pcategory |
种类路径 | path |
创建时间 | createDatetime |
1.5.2 定义类对象
- User表
import datetimeclass 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)# 0:男,1:女tel = models.CharField(max_length=11,null=True)email = models.EmailField(null=True)state = models.PositiveSmallIntegerField(default=1) # 1.启动,2:禁用 3 :后台管理员createDatetime = models.DateTimeField(default=datetime.datetime.now())
- Category表
import datetimeclass 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 makemigrationspython3.6.3 manage.py migrate
注:因为我的python版本有多个,所以修改了python.exe
1.7 创建测试数据
- 复制一份manage .py 为 build_models .py
- 加入内容,然后运行
#!/usr/bin/env pythonimport osimport sysif __name__ == "__main__":os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_15_week2_proj1.settings")try:from django.core.management import execute_from_command_lineexcept ImportError:# The above import may fail for some other reason. Ensure that the# issue is really that Django is missing to avoid masking other# exceptions on Python 2.try:import djangoexcept 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?")raiseexecute_from_command_line(sys.argv)# [加入以下内容] ---------------------------------------------------------------------------------------from user.models import *from goods.models import *import randomimport datetimefrom hashlib import md5def build_user():name_s = [ '张伟 ', '王伟 ', '王芳 ', '李伟 ', '王秀英 ', '李秀英 ', '李娜 ', '张秀英 ', '刘伟 ', '张敏 ', '李静 ', '张丽 ', '王静 ', '王丽 ', '李强 ', '张静 ', '李敏 ', '王敏 ', '王磊 ', '李军 ', '刘洋 ', '王勇 ', '张勇 ', '王艳 ', '李杰 ', '张磊 ', '王强 ', '王军 ', '张杰 ', '李娟 ', '张艳 ', '张涛 ', '王涛 ', '李明 ', '李艳 ', '王超 ', '李勇 ', '王娟 ', '刘杰 ', '王秀兰 ', '李霞 ', '刘敏 ', '张军 ', '李丽 ', '张强 ', '王平 ', '王刚 ', '王杰 ', '李桂英 ', '刘芳', ]for i in range(len(name_s)):User(account='%05d' % 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 = '%05d@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 AppConfigclass GoodsConfig(AppConfig):name = 'goods'# 加入verbose_name = '商品管理'
- goods/models .py:
from django.db import models# Create your models here.import datetimeclass 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='性别')# 0:男,1:女tel = models.CharField(max_length=11,null=True,verbose_name='手机号')email = models.EmailField(null=True,verbose_name='邮箱')state = models.PositiveSmallIntegerField(default=1,verbose_name='状态') # 1.启动,2:禁用 3 :后台管理员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)# 0:男,1:女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) # 1.启动,2:禁用 3 :后台管理员createDatetime = models.DateTimeField(default=datetime.datetime.now(),verbose_name='创建时间')class Meta():verbose_name = verbose_name_plural = '用户信息'
- 点击 增加 用户信息
3.4 配置增加页面
代码:
from django.contrib import adminfrom user.models import *# Register your models here.@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):# obj没有id,是新增的用户,密码需要加密if not obj.id: obj.password = md5(obj.password.encode('utf-8')).hexdigest()# obj有id,如果obj中的password与数据库中的password不一致,表示用户修改了密码,需要加密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
这些内容以后会在这篇博客上更新