Django入门教程——数据模型建立
第二章:数据模型建立
教学目的
- 了解模板引擎的创建
- 理解模板引擎的基本语法
- 了解系统设计的基本原则,重点理解数据库的设计。
- 了解ORM概念,理解数据模型创建方法。
模板引擎设置
Django的核心组件包括:
- 模型(Model) :定义数据结构,通常与数据库交互。
- 模板(Template) :定义用户界面的外观,使用Django模板语言。
- 视图(View) :处理业务逻辑,从模型中获取数据,并将其传递给模板。
修改第一个视图样式
def index(request):
return HttpResponse("<h1 style='color:red'>我的第一个Django视图</h1>")
真正的项⽬⾥⾯我们不会这样去渲染HTML。视图仅仅是提供数据, 然后渲染部分是Django模板引擎的职责。
模板引擎:是混⼊了原始HTML和⼀些特殊标签 {% for … in… %} 和 {{ variable }} 的html命名的文件,用于高质量的渲染HTML页面结构。
注意:模板和静态文件可以存放在各个应用程序下面,但是我们建议通过一个公共文件夹来存放所有应用下面的模板文件。
模板引擎的基本设置
配置模板引擎文件存放位置
-
在项目根目录中创建
templates
文件夹,用于存放模板文件。 -
在项目根目录中创建
static
文件夹,用于存放静态文件,页面中用到的 js、图片、css文件 -
在
settings.py
配置模版文件路径TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], #① 'APP_DIRS': False,#② 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
- ①:定义了模板文件的位置,井且该目录的名称为templates, BASE_DIR
表示本项目的根目录 , 用os.path.join()
函数将两者连接起来,即模板目录的位置是相对根目录的templates
目录 - i吾句②:将
APP_DIRS
设置为 False , 即不再允许 Django 按照默认方式在应用目录中寻找模板文件
- ①:定义了模板文件的位置,井且该目录的名称为templates, BASE_DIR
配置静态文件存放位置
样式表、JS脚本、图片等都是静态文件。
在 settings.py
配置静态文件路径:
STATIC_URL = '/static/'
STATICFILES_DIRS = [(os.path.join(BASE_DIR, 'static'))]
- 第一行:指定访问静态文件的URL地址
- 第二行:指定了静态文件存放目录的位置
应用程序的其他配置
在 settings.py
配置文件中修改
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = False # 否则日期显示不一致
LANGUAGE_CODE
:设置项目的语言,如果用汉语,则设置为'zh-hans'
TIME_ZONE
: 设置时区,通常使用东八区USE_TZ
:是否进行时区转换,设为False,不进行转换,否则可能出现8个小时的时间错误。USE_I18N
:国际化,指的是设计应用程序,使其能够适应不同的语言和地区,而不需要进行工程上的更改,国际化影响日期、语言等格式问题
页面渲染
render()函数
render(request, template_name, context=None, content_type=None, status=None, using=None)
将给定的模板与给定的上下文字典组合在一起,并以渲染的文本返回一个 HttpResponse
对象。
-
必选参数
-
request
用于生成此响应的请求对象。
-
template_name
要使用的模板的全名(包含路径)。
-
-
可选参数
context
要添加到模板上下文的值的字典。 默认情况下,这是一个空的字典。 如果字典中的值是可调用的,则视图将在渲染模板之前调用它。重要:用于向页面传递值content_type
用于结果文档的MIME 类型。默认 ‘text/html’ ,取默认值。status
响应的状态代码默认为“200”,取默认值。using
用于加载模板的模板引擎的 :setting:NAME
,取默认值。
复习:Python三大重要数据类型
快速学习教程:https://www.runoob.com/python/python-while-loop.html
列表
列表类似其他语言中的数组,用来存放一系列数据,具有以下特点:
- 列表可以嵌套
- 可以是不同的数据类型
- 列表大小不限
-
列表的创建
list1 =list() #创建空列表 list2 =['程序员','网络工程师','数据库管理员','产品经理','项目经理','实施经理']
-
列表元素的修改
- 末尾添加元素
list2.append('数据挖掘')
- 中间添加元素
list2.insert(2,'数据工程师')
下标从0开始 - 删除指定元素
list2.remove('数据工程师')
- 清空列表
list2.clear()
- 末尾添加元素
-
修改列表的值
list2[2] = '数据管理员'
修改第三个元素为数据管理员,下标从0开始 -
截取列表语法:
list[start:end]
从start到end-1,下标从0开始,可以是负数 -
列表生成式
list1 =range(1,10) list2 =[item*2 for item in list1] print('==列表1:',list(list1)) print('==列表2:',list2)
range(start, stop[, step])
函数:生成一个序列数据- start: 计数从 start 开始。默认是从 0 开始。例如 range(5) 等价于 range(0, 5)
- stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是 [0, 1, 2, 3, 4] 没有 5
- step:步长,默认为 1。例如:range(0, 5) 等价于 range(0, 5, 1)
list( seq )
函数:把一个类似类表的对象转为列表
元组
- 元组与列表类似,写在小括号中的元素序列,列表是写在中括号中的元素序列
- 列表可以增删改,元组创建后不能修改
- 元组访问截取方式和列表相同
字典
- 字典是另一种可变容器模型,且可存储任意类型对象。
- 字典的每个键值 key=>value 对用冒号 : 分割,每个对之间用逗号(,)分割,整个字典包括在花括号 {} 中
-
字典的创建
dict1 =dict() # 创建空字典 dict2= {'name':'张三','age':18} dict3 = dict(name='李四',age=18,gender='女') print("===字典2:",dict2) print("===字典3:",dict3)
-
字典的访问
print(dict2['name']) print(dict2.get('gender','男'))
-
字典的修改与添加
dict2['gender']='男' # 添加元素 dict3['gender']='男' #修改元素
-
字典几个常用函数
dict.clear()
删除字典内所有元素dict.items()
返回字典的键-值元组列表,常用于字典的遍历dict.keys()
返回字典中的所有键,需要通过list()函数转成列表dict.values()
返回字典中的所有值,需要通过list()函数转成列表pop(key[,default])
删除字典 key(键)所对应的值,返回被删除的值。dict.update(dict2)
把字典dict2的键/值对更新到dict里,用于两个字典合并
模板语法
-
输出变量:
{{变量名}}
使用双括号来输出变量<div>我所在公司:{{name}}</div>
-
输出列表
#view def tpl(request): name ="升阳" roles = ['程序员','网络工程师','数据库管理员','产品经理','项目经理','实施经理'] return render(request,'tpl.html',{'name':name,"roles":roles})
#html <h2>核心职位</h2> <div>{{roles.0}}</div> <div>{{roles.1}}</div>
5行和6行通过列表的下标进行元素的访问
<h2>全部职位</h2> <ul> {% for item in roles %} <li>{{item}}</li> {% endfor %} </ul>
循环访问列表中的所有元素
-
输出字典
user_info = {"name":"升阳","age":20,"sex":"男"}
<h2>人员信息</h2> <h5>人员信息列</h5> <ul> {% for item in user_info.keys %} <li>{{item}}</li> {% endfor %} </ul>
输出字典中的键
<h5>人员信息值</h5> <ul> {% for item in user_info.values %} <li>{{item}}</li> {% endfor %} </ul>
输出字典中的值
<h5>人员信息键值对</h5> <ul> {% for k,v in user_info.items %} <li>{{k}} = {{v}}</li> {% endfor %} </ul>
输出字典中的键值对
-
列表字典嵌套输出,常用的一种数据结构
user_list = [ {"name":"张三","age":22,"gender":"男"}, {"name":"柴桑","age":30,"gender":"男"}, {"name":"浔阳","age":24,"gender":"男"}, {"name":"李四","age":42,"gender":"女"}, {"name":"王五","age":32,"gender":"男"}, {"name":"赵六","age":22,"gender":"女"}, ]
<hr> <h2>员工信息</h2> <h5>首席工程师</h5> <div>{{user_list.0.name}}</div>
输出第一个行的元素
<h5>所有工程师</h5> <ul> {% for item in user_list %} <li>姓名:{{item.name}},年龄:{{item.age}}</li> {% endfor %} </ul>
输出所有元素
-
判断语句
<h5>所有女工程师</h5> <ul> {% for item in user_list %} {% if item.gender == '女' %} <li>姓名:{{item.name}},年龄:{{item.age}},性别:{{item.gender}}</li> {% endif %} {% endfor %} </ul>
单分支结构
<h5>三十岁以上或者女工程师</h5> <ul> {% for item in user_list %} {% if item.gender == '女' %} <li>姓名:{{item.name}},年龄:{{item.age}},性别:{{item.gender}}</li> {% elif item.age > 30 %} <li>姓名:{{item.name}},年龄:{{item.age}},性别:{{item.gender}}</li> {% endif %} {% endfor %} </ul>
多条件
<h5>红色显示所有女工程师</h5> <ul> {% for item in user_list %} {% if item.gender == '女' %} <li style="color: red;">姓名:{{item.name}},年龄:{{item.age}},性别:{{item.gender}}</li> {% else %} <li>姓名:{{item.name}},年龄:{{item.age}},性别:{{item.gender}}</li> {% endif %} {% endfor %} </ul>
数据模型建立
ORM简介
动态网站就是当用户发起访问请求时 ,网站实时地从数据库提取内容并呈现在网页上,在这类动态网站中,大多数是通过数据库实现对数据的保存和读取的,所以数据库是网站最基本和底层的组成部分。
Python 本身有读取数据库的模块可以通过 SQL 语句直接实现程序和数据库的交互 。 Django 用另外一种方式解决了这个问题 ,在这种方式中不需要开发者使用 SQL 语句,而是使用更 Python 化的方式实现对数据库的操作,这就是 ORM,对象关系映射。
ORM 的作用是在关系型数据库和业务实体对象之间进行映射,这样在操作业务对象时,就不需要再去和复杂的 SQL 语句打交道,只需简单地操作对象的属性和方法。
Django 的 ORM 表现方式就是编写数据模型类,这些类可 以 写到任何文件中,通常写在每个应用的 models.py
文件中 , 每个数据模型类都是 django .db.models.Model
的子类。
当数据模型类写好之后,通过执行 Django 的数据迁移操作就能够创建相应的数据库表,以后如果要修改数据库表的结构,只需要修改数据模型类,迁移数据就能够实现数据库结构的调整。
数据模型设计(数据表设计)
创建并设置数据库
-
创新数据库
-
在
settings.py
配置mysql数据库链接。DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "employ", "USER": "root", "PASSWORD": "sunrise123", "HOST": "127.0.0.1", "PORT": "3306", } }
- 把数据库引擎ENGINE修改为
django.db.backends.mysql
- NAME——数据库名称
- USER——数据库用户名
- PASSWOD——数据库密码
- HOST——数据库服务器地址
- PORT——数据库端口地址
- 把数据库引擎ENGINE修改为
-
安装mysql数据的第三方模块
pip install mysqlclient
-
在APP的
models.py
文件中创建实体类# 部门信息 class Department(models.Model): name = models.CharField(max_length=100,verbose_name='部门名称') index = models.IntegerField(verbose_name='排序',null=True,blank=True) def __str__(self): return self.name # 员工信息 class Employee(models.Model): name = models.CharField(max_length=100,verbose_name='姓名') depart = models.ForeignKey(to="Department", on_delete=models.CASCADE,verbose_name='部门') job_number = models.CharField(max_length=50,verbose_name='工号') gender_choices = ( (1,'男'), (2,'女') ) gender = models.IntegerField(choices=gender_choices,default=1,verbose_name='性别',null=True,blank=True) birthday = models.DateField(verbose_name='出生日期',null=True,blank=True) phone = models.CharField(max_length=11,verbose_name='手机号码',null=True,blank=True) email = models.EmailField(verbose_name='邮箱',null=True,blank=True) address = models.CharField(max_length=255,verbose_name='家庭住址',null=True,blank=True) nation = models.CharField(max_length=50,verbose_name='民族',null=True,blank=True) marital_choices = ( (1,'已婚'), (2,'未婚') ) marital = models.IntegerField(choices=marital_choices,default=2,verbose_name='婚姻状况',null=True,blank=True) id_number = models.CharField(max_length=18,verbose_name='身份证号',null=True,blank=True) hiredate = models.DateField(verbose_name='入职日期') rank = models.CharField(max_length=50,verbose_name='职级',null=True,blank=True) # 家庭成员 class FamilyMember(models.Model): employee = models.ForeignKey(to="Employee", on_delete=models.CASCADE,verbose_name='员工ID') name = models.CharField(max_length=100,verbose_name='姓名') relationship_choices =( (1,'父子'), (2,'母子'), (3,'兄弟姐妹'), (4,'其他') ) relationship = models.IntegerField(choices=relationship_choices,verbose_name='家人关系') phone = models.CharField(max_length=11,verbose_name='手机号码') address = models.CharField(max_length=255,verbose_name='家庭住址',null=True,blank=True)
-
确保APP已经在settings.py中进行了注册
-
在终端中执行命令进行数据表的创建
python manage.py makemigrations python manage.py migrate
- makemigrations 准备好响应的SQL脚本
- migrate 根据脚本执行SQL语句进行表的创建
数据模型创建基本语法
常用数据类型以及参数
-
CharField(max_length=最大长度)
字符串类型,参数max_length
表示最大字符个数。 -
IntegerField
整数类型字段。 -
DecimalField(max_digits=10,decimal_places=2)
小数类型,参数max_digits
表示总位数,decimal_places
表示小数位数。 -
DateField([auto_now=False, auto_now_add=False])
日期类型字段,其中:
(1)auto_now
表示每次保存对象时,自动设置该字段为当前时间,用于“最后一次修改”时间戳,默认为False
;
(2)auto_now_add
表示对象第一次被创建时自动设置当前时间,用于创建的时间戳,默认为False
。 -
DateTimeField
日期时间类型字段,参数同DateField
-
ForeignKey
指定外键,对应一对多的关系。depart = models.ForeignKey(to="Department",to_field="id",on_delete=models.CASCADE,verbose_name='部门')
- to——表示与哪个表关联
- to_field——表示关联的字段
- on_delete=models.CASCADE ——表示级联删除,部门表删除,对应的人员也删除
models.CASCADE
:这是默认选项,意味着当父对象被删除时,与之关联的子对象也会被删除。models.PROTECT
:这个选项会阻止父对象的删除,如果存在与之关联的子对象。models.SET_NULL
:当父对象被删除时,将子对象的外键字段设置为NULL
。使用这个选项时,外键字段必须允许NULL
值。models.SET_DEFAULT
:当父对象被删除时,将子对象的外键字段设置为默认值。外键字段必须有一个默认值。models.DO_NOTHING
:这个选项不会做任何事情,Django 不会尝试自动删除关联的子对象。
-
选择性字段
gender_choices = ( (1,'男'), (2,'女') ) gender = models.IntegerField(choices=gender_choices,default=1,verbose_name='性别')
选择性字段的内容应该描述为元组类型,元组中第一个数为存放的数据,第二个为显示的内容
choices
参数指定选择器
常用公共参数
verbose_name
字段详细说明,重要一般都需要指定default
字段默认值,用于设置默认值约束。null
数据库范畴,表示该字段允许为空blank
后台管理页面表单验证的范畴,表示该字段允许为空
class Meta内部类
通过定义Model的内部类,来添加数据模型的一些选项。
- db_table属性允许自定义模型对应的数据库表名,遵循小写加下划线的命名规范,例如:
class Meta:
db_table = 'sys_user'
-
ordering属性用于指定数据库排序依据,支持多个字段和升/降序排列。
class Meta : ordering = (' -publish',)
-
unique_together 属性指定两个字段组合起来是唯一性。
class Meta : unique_together = (("ip", "port"),)
es`参数指定选择器
常用公共参数
verbose_name
字段详细说明,重要一般都需要指定default
字段默认值,用于设置默认值约束。null
数据库范畴,表示该字段允许为空blank
后台管理页面表单验证的范畴,表示该字段允许为空
class Meta内部类
通过定义Model的内部类,来添加数据模型的一些选项。
- db_table属性允许自定义模型对应的数据库表名,遵循小写加下划线的命名规范,例如:
class Meta:
db_table = 'sys_user'
-
ordering属性用于指定数据库排序依据,支持多个字段和升/降序排列。
class Meta : ordering = (' -publish',)
-
unique_together 属性指定两个字段组合起来是唯一性。
class Meta : unique_together = (("ip", "port"),)