Django 14天从小白到进阶- Day2 搞定Models组件
本节内容
引子讲django的models之前, 先来想一想, 让你通过django操作数据库,你怎么做? 做苦思冥想,可能会这样写。 def index(request):
创建连接
很方便就实现了从数据库里取数据,事实上,很多人确实就是这么做的。但这样做会带来2个问题
那怎么办呢?ORM提供了新思路。 什么是ORM呢?上面的解释有点蒙蔽对不?其实你只需要抓住2个关键词, “映射” 和 “对象”,就能知道orm是什么干什么的了。
映射看下面的图,就是直观的例子,把右边的表结构映射成了左边的类 ?Sql语句到对象ORM可以使你不用再写原生SQL,而是像操作对象一样就可以实现对表里数据的增删改查 好棒棒,妈妈再也不用逼你写原生sql啦! 但是不要开心太早,ORM确实提高了开发效率,并且降低了数据操作与代码之间的耦合,不过有利就有弊,我们总结一下orm的优缺点。 优点:
缺点:
讲Django为什么说ORM? 哈,? 好啦,是时候该引出主角啦,因为Django的models基于架构ORM实现的。 Models模型Django 的models把数据库表结构映射成了一个个的类, 表里的每个字段就是类的属性。我们都知道数据库有很多字段类型,int,float,char等, Django的models类针对不同的字段也设置了不同的类属性。 除了普通的表字段,针对外键也有映射 OneToOneField # 1对1
好啦,接下来就用django的orm来设计一个博客表。 需求
根据需求,我们设计3张表 注意Article表和Tag表是属于多对多关系,什么是多对多?即一个文章有多个标签,一个标签又可以属于多个文章。? 比如上图的Article表中id为3的文章 ,它的标签是4,26,即投资、大文娱、社交, 你看“投资”这个标签同时还属于文章2。 这就是多对多关系 , 即many to many .? 那这种多对多的关系如何在表中存储呢?难道真的像上图中一样,在Article表中加个tags字段,关联Tag表里的多条数据,通过逗号区分? 这倒确实是个解决办法。但是也有问题,一个字段里存多条纪录的id,就没办法做查询优化了。比如不能做索引等。 所以若想实现多对多关系的高效存储+查询优化,可以在Article and Tag表之间再搞出一张表。 这样是不是就实现了多对多关联? yes,没错, django也是这么做的, django 有个专门的字段,叫ManyToManyField,就是用来实现多对多关联的,它会自动生成一个如上图一样的第3张表来存储多对多关系。 正式的表结构Create your models here.
class Account(models.Model): class Article(models.Model): class Tag(models.Model):
我们发现,每个字段其实都是一个独立的对象,一张表其实是很多类的组合。 上面好多字段里还跟了些参数,我们来看以下常用的: db_column #The name of the database column to use for this field. If this isn’t given,Django will use the field’s name.
db_index #If True,a database index will be created for this field. default #The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created. editable # django admin中用,后面讲 help_text # django admin中用,后面讲 primary_key # If True,this field is the primary key for the model. unique #If True,this field must be unique throughout the table unique_for_date #Set this to the name of a DateField or DateTimeField to require that this field be unique for the value of the date field. For example,if you have a field title that has unique_for_date="pub_date",then Django wouldn’t allow the entry of two records with the same title and pub_date. unique_for_month #Like unique_for_date,but requires the field to be unique with respect to the month. 还有几个特殊的字段属性需要单独介绍下 choices An iterable (e.g.,a list or tuple) consisting itself of iterables of exactly two items (e.g. [(A,B),(A,B) ...]) to use as choices for this field. The first element in each tuple is the actual value to be set on the model,and the second element is the human-readable name. ForeignKey.on_delete 当一条记录关联的外键纪录被删除时,django 也会根据外键关联限制的配置来决定如何处理当前这条纪录。举例,如果你有个可以为null的外键关联,并且你想在本纪录关联的数据被删除时,把当前纪录的关联字段设为null,那就配置如下 这个on_delete就是决定在关联对象被删除时,如何处理当前纪录的,常用的参数如下:
配置Django数据库连接信息Django支持多种数据库,Sqlite、Mysql、Oracle、PostgreSQL,默认的是小型文件数据库Sqlite 咱们是干大事的人,怎么也得用个Mysql呀, 改成mysql 也so easy. 不过注意,python3 连接mysql的得使用pymysql,MysqlDB模块300年没更新了,但django默认调用的还是MySQLdb,so pymysql有个功能可以让django以为是用了MySQLdb. 即在项目目录下的__init__.py中加上句代码就好 pymysql.install_as_MySQLdb()
不加的话,一会连接数据时会报错噢 。 同步数据库你在ORM定义的表结构如何同步到真实的数据库里呢? 只需2条命令。但django只能帮你自动创建表,数据库本身还是得你自己来。
好了,可以同步了,说好只需2步。 1. 生成同步文件,django自带一个专门的工具叫migrations,负责把你的orm表转成实际的表结构,它不旦可以帮自动创建表,对表结构的修改,比如增删改字段、改字段属性等也都能自动同步。只需通过下面神奇的命令。 ?不出意外的话,会显示类似以下信息 此时你会发现,你的app下的migrations目录里多了一个0001_initial.py的文件 ,这个文件就是因为你这条命令而创建的,migrations工具就会根据这个文件来创建数据库里的表。 2. 同步到数据 此时登录你的数据库,会发现创建了好多张表 show tables;
+----------------------------+
| Tables_in_luffy_dev2 |
+----------------------------+
| app01_account | #对应Account表
| app01_article | #对应Article表
| app01_article_tags | #自动创建的Article to Tag的多对多关联表
| app01_tag | #对应Tag表
| auth_group | #下面这些,都是django 自带的表,这个是自动用户系统的组
| auth_group_permissions | #自带的组与权限的多对多关联表
| auth_permission | #自带权限表
| auth_user | #用户表
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log | #现在你的无法理解
| django_content_type | #现在你的无法理解
| django_migrations | #纪录migartions工具同步纪录的表
| django_session | #现在你的无法理解
+----------------------------+
14 rows in set (0.00 sec)
好啦,表结构也有了,我们可以往里面插数据啦。 之前说好的是可以不用SQL语句的,一点不骗你。 用orm对表数据进行增删改查先进入已经连接好数据库的django python环境 >>
>>> from app01 import models
创建 创建数据简单的令人发指 查 filter 支持很多的过滤条件,我们来看下: ? contains 包含,相当于sql的like条件 SQL equivalent: Note this will match the headline 'Lennon honored today' but not 'lennon honored today'. icontains? 大小写不敏感
in In a given iterable; often a list,tuple,or queryset. SQL equivalent: You can also use a queryset to dynamically evaluate the list of values instead of providing a list of literal values: This queryset will be evaluated as subselect statement:
gt SQL equivalent: 4;
gteGreater than or equal to. ltLess than. lteLess than or equal to. startswithCase-sensitive starts-with. SQL equivalent: SQLite doesn’t support case-sensitive LIKE statements; startswith acts like istartswith for SQLite istartswithCase-insensitive starts-with. endswithCase-sensitive ends-with. iendswithCase-insensitive ends-with
range区间过渡,可对数字、日期进行过滤 SQL equivalent:
date For datetime fields,casts the value as date. Allows chaining additional field lookups. Takes a date value. yearFor date and datetime fields,an exact year match. Allows chaining additional field lookups. Takes an integer year. SQL equivalent: = '2005-01-01';
When USE_TZ is True,datetime fields are converted to the current time zone before filtering. 简单解决办法是把USE_TZ=False monthFor date and datetime fields,an exact month match. Allows chaining additional field lookups. Takes an integer 1 (January) through 12 (December). When??is? SQL equivalent: = '6';
dayFor date and datetime fields,an exact day match. Allows chaining additional field lookups. Takes an integer day. SQL equivalent: = '3';
For date and datetime fields,return the week number (1-52 or 53) according to?,i.e.,weeks start on a Monday and the first week contains the year’s first Thursday. Example: For date and datetime fields,a ‘day of the week’ match. Allows chaining additional field lookups. Takes an integer value representing the day of week from 1 (Sunday) to 7 (Saturday). Example: For datetime and time fields,an exact hour match. Allows chaining additional field lookups. Takes an integer between 0 and 23. Example: SQL equivalent: = '12';同
同时,还支持mintue,second Event.objects.filter(timestamp__second=31)
Takes either? Example: SQL equivalent: Case-sensitive regular expression match. Example: SQL equivalents: SELECT ... WHERE REGEXP_LIKE(title,'^(An?|The) +','c'); -- Oracle
SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite iregex 大小写不敏感
改删 单条修改
obj = models.Account.objects.get(username='linux') 批量删除models.User.objects.get(password='oldboy').delete() 单条删除obj = models.User.objects.get(id=3) 数据返回后的展示
Returns a? >> Blog.objects.values()
By default,results returned by a? The result above will be ordered by? Use the? To retrieve the “last” five items in a queryset,you could do this:
ORM对象操作外键关联
外键反向关联操作
多对多操作
多对多反向操作
好啦,orm的操作先点到为止,后面学项目时再带你搞复杂的。 练习题
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |