Django——模型基础(单表)
1.ORM
在MVC或者说MTV设计模式中,模型(M)代表对数据库的操作。但操作数据库需要专门的SQL语句,而Python程序员不是专业的DBA,写的SQL语句可能有点次,于是就有人想到用python语法来操作,这就是ORM。
ORM 即:对象—关系—映射(从https://www.cnblogs.com/huang-yc/p/9652935.html盗来一张图,顺便吹下这位博主!)
简单又不太专业的说就是通过映射关系使得一个python语句对应一个SQL语句,这样python程序员无需关心ORM内部的细节,也不用很了解SQL语法,只要通过python就可以操作数据库了。
把代码敲一遍:
SQL语句
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# SQL的表 # 创建表: CREATE TABLE employee( id INT PRIMARY KEY auto_increment, name VARCHAR(20), gender BIT default 1, birthday DATA, department VARCHAR(20), salary DECIMAL (8,2) unsigned ); # 表记录 # 添加一条表记录: INSERT employee(name,gender,birthday,salary,department) VALUES("Alex",1,"1985-12-12",8000,"保洁部"); # 查询一条表记录: SELECT * FROM employee WHERE age=24; # 更新一条表记录: UPDATE employee SET birthday="1989-10-10" WHERE id=1; # 删除一条表记录: DELETE FROM employee WHERE name="Alex"
Python语句
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# python的类 class Employee(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max_length=32) gender=models.Booleanfield() birthday=models.DateField() depatment=models.CharField(max_length=32) salary=models.DecimalField(max_digits=8,decimal_places=2) # python类对象 # 添加一条表记录 emp=Employee(name="Alex",gender=True,birthday="1985-12-12",department="保洁部") emp.save() # 查询一条表记录 Employee.objects.filter(age=24) # 更新一条表记录 Employee.objects.filter(id=1).update(birthday="1989-10-10") # 删除一条表记录 Employee.objects.filter(name="Alex").delete()
2.单表操作
如前所说每个模型映射为一张数据库中的表,基本原则如下:
- 每个模型在Django中的存在形式为一个Python类
- 每个模型都是django.db.models.Model的子类
- 模型的每个字段(属性)代表数据表的某一列
- Django将自动为你生成数据库访问API
2.1创建表
跟上面一样,上代码:
from django.db import models # Create your models here. class User(models.Model): username = models.CharField( max_length=20, unique=True) password = models.CharField( max_length=256) email = models.EmailField() create_time = models.DateTimeField( auto_now_add=True)
2.2常用字段和参数
字段是模型中最重要的内容之一,也是唯一必须的部分。字段在Python中表现为一个类属性,体现了数据表中的一个列。字段决定数据库中对应列的数据类型,每个字段有一些特有的参数,例如,CharField需要max_length参数来指定VARCHAR数据库字段的大小。这里就列出一些常用的或常见的。
常见字段:
类型 说明 AutoField # 一个自动增加的整数类型字段。通常你不需要自己编写它,Django会自动帮你添加字段:id = models.AutoField(primary_key=True),这是一个自增字段,从1开始计数。如果你非要自己设置主键,那么请务必将字段设置为primary_key=True。Django在一个模型中只允许有一个自增字段,并且该字段必须为主键! BooleanField # 布尔值类型。默认值是None。在HTML表单中体现为CheckboxInput标签。如果要接收null值,请使用NullBooleanField。 CharField # 字符串类型。必须接收一个max_length参数,表示字符串长度不能超过该值。默认的表单标签是input text。最常用的filed,没有之一! CommaSeparatedIntegerField # 逗号分隔的整数类型。必须接收一个max_length参数。常用于表示较大的金额数目,例如1,000,000元。 DateField # class DateField(auto_now=False, auto_now_add=False, **options)日期类型。一个Python中的datetime.date的实例。在HTML中表现为TextInput标签。在admin后台中,Django会帮你自动添加一个JS的日历表和一个“Today”快捷方式,以及附加的日期合法性验证。两个重要参数:(参数互斥,不能共存) auto_now:每当对象被保存时将字段设为当前日期,常用于保存最后修改时间。auto_now_add:每当对象被创建时,设为当前日期,常用于保存创建日期(注意,它是不可修改的)。设置上面两个参数就相当于给field添加了editable=False和blank=True属性。如果想具有修改属性,请用default参数。例子:pub_time = models.DateField(auto_now_add=True),自动添加发布时间。 DateTimeField # 日期时间类型。Python的datetime.datetime的实例。与DateField相比就是多了小时、分和秒的显示,其它功能、参数、用法、默认值等等都一样。 DecimalField # 固定精度的十进制小数。相当于Python的Decimal实例,必须提供两个指定的参数!参数max_digits:最大的位数,必须大于或等于小数点位数 。decimal_places:小数点位数,精度。 当localize=False时,它在HTML表现为NumberInput标签,否则是text类型。例子:储存最大不超过999,带有2位小数位精度的数,定义如下:models.DecimalField(..., max_digits=5, decimal_places=2)。 DurationField # 持续时间类型。存储一定期间的时间长度。类似Python中的timedelta。在不同的数据库实现中有不同的表示方法。常用于进行时间之间的加减运算。但是小心了,这里有坑,PostgreSQL等数据库之间有兼容性问题! EmailField # 邮箱类型,默认max_length最大长度254位。使用这个字段的好处是,可以使用DJango内置的EmailValidator进行邮箱地址合法性验证。 FileField # class FileField(upload_to=None, max_length=100, **options)上传文件类型, http://www.liujiangblog.com/course/django/95 FilePathField # 文件路径类型 http://www.liujiangblog.com/course/django/95 FloatField # 参考整型 http://www.liujiangblog.com/course/django/95 ImageField # 图像类型 http://www.liujiangblog.com/course/django/95 IntegerField # 整数类型,最常用的字段之一。取值范围-2147483648到2147483647。在HTML中表现为NumberInput标签。 GenericIPAddressField # class GenericIPAddressField(protocol='both', unpack_ipv4=False, **options)[source],IPV4或者IPV6地址,字符串形式,例如192.0.2.30或者2a02:42fe::4在HTML中表现为TextInput标签。参数protocol默认值为‘both’,可选‘IPv4’或者‘IPv6’,表示你的IP地址类型。 NullBooleanField # 类似布尔字段,只不过额外允许NULL作为选项之一。 TextField # 大量文本内容,在HTML中表现为Textarea标签,最常用的字段类型之一!如果你为它设置一个max_length参数,那么在前端页面中会受到输入字符数量限制,然而在模型和数据库层面却不受影响。只有CharField才能同时作用于两者。 TimeField # 时间字段,Python中datetime.time的实例。接收同DateField一样的参数,只作用于小时、分和秒。 URLField # 一个用于保存URL地址的字符串类型,默认最大长度200。 UUIDField # 用于保存通用唯一识别码(Universally Unique Identifier)的字段。使用Python的UUID类。在PostgreSQL数据库中保存为uuid类型,其它数据库中为char(32)。这个字段是自增主键的最佳替代品,后面有例子展示。
常用参数:
参数 说明 null # 该值为True时,Django在数据库用NULL保存空值。默认值为False。 blank # True时,字段可以为空。默认False。和null参数不同的是,null是纯数据库层面的,而blank是验证相关的,与数据库无关。所以要小心一个null为False,blank为True的字段接收到一个空值可能会出bug或异常。 choices # 用于页面上的选择框标签,需要先提供一个二维的二元元组,第一个元素表示存在数据库内真实的值,第二个表示页面上显示的具体内容。 default # 字段的默认值,可以是值或者一个可调用对象。如果是可调用对象,那么每次创建新对象时都会调用 primary_key # 如果你为某个字段设置了primary_key=True,则当前字段变为主键,并关闭Django自动生成id主键的功能。primary_key=True隐含null=False和unique=True的意思。一个模型中只能有一个主键字段! db_index # 该参数接收布尔值。如果为True,数据库将为该字段创建索引。 unique # 设为True时,在整个数据表内该字段的数据不可重复。 # 注意:对于ManyToManyField和OneToOneField关系类型,该参数无效。 # 注意: 当unique=True时,db_index参数无须设置,因为unqiue隐含了索引。 verbose_name # 为字段设置一个人类可读,更加直观的别名。
2.3settings配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import pymysql pymysql.install_as_MySQLdb() DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'myblog', # 数据库名 'USER': 'root', # 数据库的用户名 'PASSWORD': 'pwd', # 数据库密码 'HOST': '', # 主机IP,默认本机 'PORT': '' # 主机端口,默认“3306” } }
要注意:NAME即数据库的名字,在mysql连接前该数据库必须提前手动创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建 USER和PASSWORD分别是数据库的用户名和密码。
最后通过两条数据库迁移命令即可在指定的数据库中创建表:
python manage.py makemigrations
python manage.py migrate
2.4记录表的增、删、改
增:两种方式
# 方式一:create user = models.User.objects.create(username="Alex",password="pwd",email="alex@163.com") # create方法的返回值即为新插入表的名为Alex的对象 #方式二:save user = models.User(username="Alex",password="pwd",email="alex@163.com") user.save()
删:
删除对象使用的是对象的delete()
方法。
user.delete()
你也可以一次性删除多个对象。每个 QuerySet 都有一个 delete() 方法,它一次性删除 QuerySet 中所有的对象。
例如,下面的代码将删除 pub_date 是2005年的Article对象:
models.Article.objects.filter(pub_date__year=2005).delete()
当Django删除一个对象时,它默认使用SQL的ON DELETE CASCADE约束,也就是说,任何有外键指向要删除对象的对象将一起被删除。例如:
u = models.User.objects.get(pk=1) # 下面的动作将删除该条Blog和所有的它关联的Article对象 u.delete()
这种级联的行为可以通过的ForeignKey的on_delete
参数自定义,如果不想级联删除,就可以设置on_delete为其他方式,如:
user = models.ForeignKey(to='User', on_delete=models.SET_NULL, blank=True, null=True)
注意,delete()
是唯一没有在Manager管理器上暴露出来的方法。这是刻意设计的一个安全机制,用来防止你意外地请求类似models.User.objects.delete()
的动作,而不慎删除了所有的条目。如果你确实想删除所有的对象,你必须明确地请求一个完全的查询集,像下面这样:
models.User.objects.all().delete()
改:
使用update()
方法可以批量为QuerySet中所有的对象进行更新操作。
models.User.objects.filter(name__contents="Alex").update(name="Eric")
要注意的是update()方法会直接转换成一个SQL语句,并立刻批量执行。它不会运行模型的save()方法,或者产生pre_save
或post_save
信号
2.5记录表的查询
查询的API较多,所以放在最后,而且这里仅列出少量常用API
方法 说明 all() # 获取所有对象 filter(**kwargs) # 根据条件过滤查询对象 exclude(**kwargs) # 排除满足条件的对象 order_by(*fileld) # 对查询集进行排序 reverse() # 反向排序 values(*fileld) # 返回一个特殊的的QuerySet,这个QuerySet中不是一个个models的实例化对象,而是根据*fileld查询的具体值的字典 values_list(*fileld) # 这个和values()类似,但是它返回的是元组,而不是字典 distinct() # 从返回的查询集中剔除重复记录 # 注意上面的API返回的是QuerySet对象,下面的API不返回QuerySet对象 get() # 获取单个对象 first() # 获取查询到的第一个对象 last() # 获取查询到的最后一个对象 count() # 统计查询的QuerySet中对象个数 exists() # 判断QuerySet中是否有对象,有返回True,无返回Flase 另:使用类似Python对列表进行切片的方法可以对QuerySet进行范围取值 models.User.objects.all()[:5] # 返回前5个对象 models.User.objects.all()[5:10] # 返回第6个到第10个对象 # 不支持负索引!
字段查询是指如何指定SQL WHERE子句的内容。它们用作QuerySet的filter(), exclude()和get()方法的关键字参数
常用字段查询参数(双下滑线的模糊查询):
参数 说明 contains # 区分大小写的包含匹配 icontains # 不区分大小写的包含匹配 in # 在...中的匹配 gt / gte # 大于 / 大于等于 lt / lte # 小于 / 小于等于 range # 范围匹配 date # 日期匹配 year / month / day # 年 / 月 / 日 匹配 startswith / istartswith # 区分大小写/不区分大小写 以...开头匹配 endswith / iendswith # 区分大小写/不区分大小写 以...结尾匹配 用法 models.User.objects.filter(id__gt=5) models.User.objects.filter(id__range=[10,15]) models.User.objects.filter(name__contains="Alex") models.User.objects.filter(name__icontains="ALEX") models.User.objects.filter(name__startswith="E") models.User.objects.filter(create_time__year=2016)