python sqlalchemy 和django orm 对比

表和表的之间关系,往往通过外键建立关系,那简单介绍下外键。

一:DB角度上的上外键含义:

主键:主键是唯一标识一条记录,不能重复,有唯一性约束,不可以为空。用来保证数据的完整性,我们常用自增id来创建主键。

外键:是另一张表的主键或者带有唯一性约束的列,外键可以重复,可以为空,主要作用:用他来和其他的表建立逻辑关系。所以当我们谈到外键的时候最少涉及到2张表。

比如:

部门表dept 和员工表emp。emp表中的Dept_id就是外键,和dept表单的主键id关联。

因为一个部门多个员工,所以员工需要在知道自己归属的部门,所以emp是子表而dept是父表。

外键一定是从表中建立的,从而和主表建立关系,从表维护二者的关系。

使用外键的条件:

  • 1、两张表必须都是InnodeDB表,并且没有临时表。
  • 注:InnodDB是数据库引擎。mysql常见的数据库引擎:innodeDBhe 和MySIAM,而MySIM不支持外键约束!!!
  • 2、建立外键关系的对应列必须有具有相似的InnoDB内部数据类型。
  • 3、建立外键关系的对应列必须建立了索引,

二:从python角度理解:

在python中通过关系映射(orm),调用底层dbapi来实现数据库的操作。通过定义类和对象,(类是表,类的对象是数据库的一行数据。)来操作数据库,通过底层的转换,最终形成sql,在相应的数据库中执行。

notice:

  1. 无论是python通过orm(sqlalchemy和django的orm)来创建表,通过定义字段使表与表建立关系,比如外键。python层面定义的外键作用到数据库中,也是形成相应的外键。
  2. 所以无论哪种的orm建立的表结构,外键都是在子表中,可以理解成外键在多对一中“多”的字段中。
  3. 在数据库中,外键是建立在子表中。建立外键的列是另一张的表的主键。所以python设置外键的表是固定的。对应的“一对多”的“多”表中建立外键。

A:django的orm:

一对多:

比如说:作者和书籍的关系,一个作者有多本书,构成一对多的关系。

modles结构:

1 class Author(models.Model):
2     username=models.CharField(max_length=32)
3 class Book(models.Model):
4     name=models.CharField(max_length=32)
5     b_author=models.ForeignKey('Author')

 

插入数据:通过访问相应的url插入数据

1 def insert(request):
2     models.Author.objects.create(username="tom")
3     return HttpResponse('ok')

1 def insert(request):
2     models.Book.objects.create(name='唐吉坷德',b_author_id=1)
3     return HttpResponse('ok')

数据库本质的插入。

查询:

1、正向查询:

通过双下划线来操作。

比如:百年孤独的作者的名字是谁?

1 def insert(request):
2     ret=models.Book.objects.filter(name="百年孤独").values("b_author__username")
3     print(ret)
4     return HttpResponse('ok')
5 <QuerySet [{'b_author__username': 'tom'}]>

反向查询:一对多也支持反向查询。方法有2个。一个是通过双下划线,一个通过tablename_set字段哎查询,查询的方式不一样,方法也不一样!!!

  • 通过tablename_set来反向查询,但是在这种查询,方法和manytomany 操作第三章表类似。

需求:查看tom都出 那些书,书的名字是什么?

1 def insert(request):
2     obj=models.Author.objects.filter(username='tom').first()
3     ret=obj.book_set.all()
4     for i in ret:
5         print(i.name)
6     return HttpResponse('ok')
1 百年孤独
2 唐吉坷德
  • 通过双下滑线反向查询:
1 def insert(request):
2     booklist=models.Author.objects.filter(username='tom').values('book__name')
3     print(booklist)
4     return HttpResponse('ok')
5 <QuerySet [{'book__name': '百年孤独'}, {'book__name': '唐吉坷德'}]>

notice:

  • 无论正向查询还是反向查询,都可以用双下划线。
  • 反向查询的时候,因为对应的是“一”,所以查询的结果需要单个对象,然后查询对应“多”的表的对象集合。而使用set的字段的时候,需要注意使用的方法都是all、filter等。

对于多对多情况,正向查询的时候,使用的的是双下划线,反向查询是用含有manytomany的字段的“表”名的隐藏的列的进行反向查询。也是利用双下划线。

表结构:一个服务器有多个用户,一个用户在存在于多个服务器中。

1 class Host(models.Model):
2     ip=models.CharField(max_length=32)
3     hostname=models.CharField(max_length=32)
4 
5 class User(models.Model):
6     username=models.CharField(max_length=32)
7     password=models.CharField(max_length=32)
8     user_host=models.ManyToManyField('Host')#注意引号的作用,如果没有引号的话,关联的表必须在当前表的前面,否则报错。

插入数据:

1 def insert(request):
2     for i in range(4):
3         models.Host.objects.create(ip='172.17.33.'+str(i),hostname=str(i)+'.com')
4     return HttpResponse('ok')

1 def insert(request):
2     for i in range(4):
3         models.User.objects.create(username='evil'+str(i),password=str(i)+'123')
4     return HttpResponse('ok')

  • 需要注意:当我们在给含有ManyToMany的表进行插值的时候,对于字段:user_host=models.ManyToManyField('Host'),不需要插值。该列只是关联第三张关系表:mod_user_user_host。实质该列在数据库并不存在该列。

第三张表(mod_user_user_host)进行插值:第三张表存储在django层面来看是对象,实际在数据库中存储的是这2张表(host、user)的主键值。所以插入值的方法也有2种。

正向插入值:

1 def insert(request):
2     res=models.User.objects.filter(id=3).first()
3     ret=models.Host.objects.filter(id__gt=2)
4     res.user_host.add(*ret)
5     return HttpResponse('ok')

 

反向插入值,反向插入值,用另一张表名_set.add()方法来操作。

1 def insert(request):
2     res=models.Host.objects.filter(id=1).first()
3     ret=models.User.objects.filter(id__lt=4)
4     res.user_set.add(*ret)
5     return HttpResponse('ok')

 

当然相应的查询方法,也可以 用_set字段或者表名进行查询,和一对多是一样的。唯一区别是:更新第三张表的时候,最好用原生sql进行更新。

B:sqlalchemy的orm

  • 对于一对多或者多对多的情况下,在sqlalchemy中使用的是relationship()来创建一个数据库中并不存在的列来构建2个表之间的关系。
  • 需要注意的:在django中建立外键,直接类的名字既可,在sqlalchemy中需要写:表的名字.主键列的名字。

表结构:比如主机和主机用户来构建多对多表结构

 1 class Host(Base):
 2     __tablename__='host'
 3     nid=Column(Integer,autoincrement=True,primary_key=True)
 4     hostname=Column(String(32))
 5     ip=Column(String(32))
 6 
 7 class system_User(Base):
 8     __tablename__='system_user'
 9     nid=Column(Integer,autoincrement=True,primary_key=True)
10     username=Column(String(32))
11     password=Column(String(32))
12 
13 class Host_to_system_User(Base):
14     __tablename__='host_to_system_user'
15     nid=Column(Integer,primary_key=True,autoincrement=True)
16     host_nid=Column(Integer,ForeignKey('host.nid'))
17     system_user_nid=Column(Integer,ForeignKey('system_user.nid'))#需要注意这个和django不一样,django直接写类名字既可。
18     host=relationship('Host',backref='ho')
19     system_user=relationship('system_User',backref='sys_u')
20 Base.metadata.create_all(engine)##执行该函数,他就会执行所有Base所有的子类。调用我们定义类并创建相应的表结构。
21 Session=sessionmaker(engine)
22 session=Session()#创建数据库连接。可以理解为django的db模块中connection。

 

插入数据:2张表正常插入值和django一样,不需要关注第三张表,当需要建立关系的时候,直接给第三张表插入相应的id值既可。

 1 Session=sessionmaker(engine)
 2 session=Session()#创建数据库连接。可以理解为django的db模块中connection。
 3 host_obj=Host(hostname='c1.com',ip='172.17.22.12')
 4 host_obj_1=Host(hostname='c2.com',ip='172.17.22.13')
 5 host_obj_2=Host(hostname='c3.com',ip='172.17.22.14')
 6 session.add_all(
 7         [
 8             host_obj,
 9             host_obj_1,
10             host_obj_2
11         ]
12 )
13 system_user_obj=system_User(username='evil',password='123')
14 system_user_obj_1=system_User(username='tom',password='123')
15 system_user_obj_2=system_User(username='jack',password='123')
16 session.add_all(
17         (
18             system_user_obj,
19             system_user_obj_1,
20             system_user_obj_2
21         )
22 )
23 #
24 host_to_system_user_obj=Host_to_system_User(host_nid=1,system_user_nid=1)
25 host_to_system_user_obj_1=Host_to_system_User(host_nid=1,system_user_nid=2)
26 host_to_system_user_obj_2=Host_to_system_User(host_nid=1,system_user_nid=3)
27 host_to_system_user_obj_3=Host_to_system_User(host_nid=2,system_user_nid=1)
28 host_to_system_user_obj_7=Host_to_system_User(host_nid=2,system_user_nid=2)
29 host_to_system_user_obj_4=Host_to_system_User(host_nid=2,system_user_nid=3)
30 host_to_system_user_obj_5=Host_to_system_User(host_nid=3,system_user_nid=1)
31 host_to_system_user_obj_6=Host_to_system_User(host_nid=3,system_user_nid=2)
32 session.add_all(
33     [
34         host_to_system_user_obj,
35         host_to_system_user_obj_1,
36         host_to_system_user_obj_2,
37         host_to_system_user_obj_3,
38         host_to_system_user_obj_4,
39         host_to_system_user_obj_5,
40         host_to_system_user_obj_6,
41         host_to_system_user_obj_7
42     ]
43 )
44 session.commit()

 

 1 mysql> select * from  host;
 2 +-----+----------+--------------+
 3 | nid | hostname | ip           |
 4 +-----+----------+--------------+
 5 |   1 | c1.com   | 172.17.22.12 |
 6 |   2 | c2.com   | 172.17.22.13 |
 7 |   3 | c3.com   | 172.17.22.14 |
 8 +-----+----------+--------------+
 9 3 rows in set (0.00 sec)
10 
11 mysql> select * from  system_user;
12 +-----+----------+----------+
13 | nid | username | password |
14 +-----+----------+----------+
15 |   1 | evil     | 123      |
16 |   2 | tom      | 123      |
17 |   3 | jack     | 123      |
18 +-----+----------+----------+
19 3 rows in set (0.00 sec)
20 
21 mysql> select * from host_to_system_user;
22 +-----+----------+-----------------+
23 | nid | host_nid | system_user_nid |
24 +-----+----------+-----------------+
25 |   1 |        1 |               1 |
26 |   2 |        1 |               2 |
27 |   3 |        1 |               3 |
28 |   4 |        2 |               1 |
29 |   5 |        2 |               3 |
30 |   6 |        3 |               1 |
31 |   7 |        3 |               2 |
32 |   8 |        2 |               2 |
33 +-----+----------+-----------------+
34 8 rows in set (0.00 sec)

 

查询:

需求:用户evil 都在哪些服务器上?

分析:首先通过system_user查到evil的对象,通过该对象获取sys_u的列,这个列是第三张表的对象的集合,通过循环该列获取每列的我们建立的host关系列来获取对应的host表的属性值。也就是说先反向查询在正向查询。

1 ret=session.query(system_User).filter(system_User.username=='evil').first()
2 for i in ret.sys_u:
3     print(i.host.ip)

 

1 172.17.22.12
2 172.17.22.13
3 172.17.22.14

 

django orm和sqlalchemy的orm的对比:

  • 在django中orm中插入和查询的时候,使用是类中定义数据库的列的名字,而在sqlalchemy中使用的调用数据库的字段是对象的属性字段。

django:

modle:

1 class Person(models.Model):
2     username=models.CharField(max_length=32)
3 
4 class Fav(models.Model):
5     name=models.CharField(max_length=32)
6     per_fav=models.ForeignKey('Person')

查询语句:

比如查询名字为evil的爱好都有哪些:

1 def insert(request):
2     ret=models.Fav.objects.filter(per_fav__username='evil').values('name')
3     print(ret)
4     return HttpResponse('ok')

其中查询的字段并没有对象.字段属性。而sqlalchemy在调用表的字段的字段的时候,需要使用类.字段(其中字段属于类的静态字段。)

sqlalchemy:

 1 from sqlalchemy.ext.declarative import declarative_base
 2 from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index#导入列数据类型字段。
 3 from sqlalchemy.orm import sessionmaker, relationship#导入会话函数、
 4 from sqlalchemy import create_engine
 5 engine = create_engine("mysql+pymysql://root:@192.168.31.222:3306/django", max_overflow=15)#创建数据库引擎,通过连接池获取数据库的连接。数据库连接池数量为:15,默认值是5.
 6 #创建sqlorm基类。(为声明的类定义基类。)
 7 Base = declarative_base()
 8 class User(Base):
 9     __tablename__='user'
10     nid=Column(Integer,primary_key=True,autoincrement=True)
11     username=Column(String(32))
12 
13     def __repr__(self):
14         temp='%s-%s'%(self.nid,self.username)
15         return temp
16 Base.metadata.create_all(engine)##执行该函数,他就会执行所有Base所有的子类。调用我们定义类并创建相应的表结构。

插入数据:

 1 Session=sessionmaker(engine)
 2 session=Session()#创建数据库连接。可以理解为django的db模块中connection。
 3 user_obj=User(username='evil')#创建类的对象。
 4 user_obj1=User(username='tom')
 5 user_obj2=User(username='jack')
 6 session.add_all(
 7         (
 8             user_obj,
 9             user_obj1,
10             user_obj2
11         )
12 )
13 session.commit()#提交数据库事务。

 

1 mysql> select *from user;
2 +-----+----------+
3 | nid | username |
4 +-----+----------+
5 |   1 | evil     |
6 |   2 | tom      |
7 |   3 | jack     |
8 +-----+----------+
9 3 rows in set (0.00 sec)

查询数据库:

1 Session=sessionmaker(engine)
2 session=Session()#创建数据库连接。可以理解为django的db模块中connection。
3 ret=session.query(User).filter(User.nid>1).all()
4 print(ret)
5 [2-tom, 3-jack]

对比:

  • 数据库连接:django在创建项目的时候在setting配置文件中需要配置数据库的连接串,默认使用数据库是sqlite。
1 DATABASES = {
2     'default': {
3         'ENGINE': 'django.db.backends.sqlite3',
4         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
5     }
6 }
  • sqlalchemy 需要导入相应的模块,然后建立相应的连接引擎和数据库的连接池。每次执行数据库操作的时候都需要创建连接对象。而django默认帮我们做数据库连接。
1 from sqlalchemy import create_engine
2 engine = create_engine("mysql+pymysql://root:@192.168.31.222:3306/django", max_overflow=15)#创建数据库引擎,通过连接池获取数据库的连接。 
  • django在创建数据库的时候,创建表的类的时候需要继承(models.Model)而sqlalchemy需要继承一个基类:Base = declarative_base()
  • 在django如果不指定主键的时候,django默认会创建一个名为:id的自增列。而sqlalchemy需要手动指定自增列和主键。
  • 默认在django中表明是类名的小写,而在sqlalchemy中必须要指定__tablename__字段,指定数据库的表的名字否则报如下错误信息
1 sqlalchemy.exc.InvalidRequestError: Class <class '__main__.User'> does not have a __table__ or __tablename__ specified and does not inherit from an existing table-mapped class.

django:

1 from django.db import models
2 
3 # Create your models here.
4 class Person(models.Model):
5     username=models.CharField(max_length=32)

 sqlalchemy:

 1 from sqlalchemy.ext.declarative import declarative_base
 2 from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index  # 导入列数据类型字段。
 3 from sqlalchemy.orm import sessionmaker, relationship  # 导入会话函数、
 4 from sqlalchemy import create_engine
 5 
 6 engine = create_engine("mysql+pymysql://root:@192.168.147.129:3306/sqlalchemy",
 7                        max_overflow=15)  # 创建数据库引擎,通过连接池获取数据库的连接。数据库连接池数量为:15,默认值是5.
 8 # 创建sqlorm基类。(为声明的类定义基类。)
 9 Base = declarative_base()
10 
11 class   User(Base):
12     __tablename__='user'
13     nid=Column(Integer,primary_key=True,autoincrement=True)
14     name=Column(String(32))
15     def __repr__(self):
16         return self.name
  • django 默认情况不需要指定表名,而sqlalchemy需要指定表名否则报错。
  • 2者在查询返回的结果都是对象的列表(django是Queryset对象,而sqlalchemy返回的是相应的类对象),django可以用__unicode__方法 输出对象的时候我们可以自定义输出的我们自定义的字段(django版本Django 1.10中是__str__方法),而sqlalchemy是__repr__方法来输出对象的自定义字段。

sqlalchemy:

1 class User(Base):
2     __tablename__='user'
3     nid=Column(Integer,primary_key=True,autoincrement=True)
4     username=Column(String(32))
5 Session=sessionmaker(engine)
6 session=Session()#创建数据库连接。可以理解为django的db模块中connection。
7 ret=session.query(User).filter(User.nid>1).all()
8 print(ret)
9 [<__main__.User object at 0x03708210>, <__main__.User object at 0x03708250>]

 django:

1 from django.db import models
2 
3 # Create your models here.
4 class Person(models.Model):
5     username=models.CharField(max_length=32)
6 
7 class Fav(models.Model):
8     name=models.CharField(max_length=32)
9     per_fav=models.ForeignKey('Person')
1 def insert(request):
2     ret=models.Fav.objects.filter(per_fav__username='evil').all()
3     print(ret)
4     return HttpResponse('ok')
1 <QuerySet [<Fav: Fav object>, <Fav: Fav object>]>

 sqlalchemy:

1 class User(Base):
2     __tablename__='user'
3     nid=Column(Integer,primary_key=True,autoincrement=True)
4     username=Column(String(32))
5 
6     def __repr__(self):
7         temp='%s-%s'%(self.nid,self.username)
8         return temp
9  [2-tom, 3-jack]

 django:

 1 from django.db import models
 2 
 3 # Create your models here.
 4 class Person(models.Model):
 5     username=models.CharField(max_length=32)
 6     def __str__(self):
 7         temp='%s-%s'%(self.id,self.username)
 8         return temp
 9 
10 class Fav(models.Model):
11     name=models.CharField(max_length=32)
12     per_fav=models.ForeignKey('Person')
13     def __str__(self):
14         temp='%s-%s'%(self.id,self.name)
15         return temp

输出函数:

 1 from django.shortcuts import render,HttpResponse
 2 from mod  import models
 3 # Create your views here.
 4 def insert(request):
 5     ret=models.Fav.objects.filter(per_fav__username='evil').all()
 6     for i in ret:
 7         print(i)
 8     return HttpResponse('ok')
 9 1-bak
10 2-foot
  •  在sqlalchemy中对数据库进行增删改的时候,最后需要提交事务(session.commit()),数据库才能保存我们的数据修改,在低版本的django中也需要save()进行提交事务在版本:Django 1.10中不需要提交事务。
 1 User_obj=User(name='evil')
 2 User_obj_1=User(name='tom')
 3 User_obj_2=User(name='jack')
 4 
 5 Session=sessionmaker(engine)
 6 session=Session()
 7 session.add_all(
 8     [
 9         User_obj,
10         User_obj_1,
11         User_obj_2
12     ]
13 )
14 session.commit()

 

1 mysql> select * from  user;
2 +-----+------+
3 | nid | name |
4 +-----+------+
5 |   1 | evil |
6 |   2 | tom  |
7 |   3 | jack |
8 +-----+------+
9 3 rows in set (0.00 sec)
  • 插入数据:在一对多的情况下,django可以有两种方式进行数据的插入,包括:django层面,对外键列插入关联表的对象,在数据库层面:实际数据库中存储的是:另一个列的主键id值。可以直接插入数字。

表结构:

1 class Author(models.Model):
2     username=models.CharField(max_length=32)
3 class Book(models.Model):
4     name=models.CharField(max_length=32)
5     b_author=models.ForeignKey('Author')

给b_author插入值,默认情况下,book表(注意是小写)中的b_author列在数据库中的列为:b_author_id.

所以我们在插入b_author列插入author表的对象,也可以直接插入author主键列里的id值。插入对象:

1 from django.shortcuts import render,HttpResponse
2 from mod import models
3 # Create your views here.
4 def insert(request):
5     author_obj=models.Author.objects.filter(id=1).first()
6     models.Book.objects.create(b_author=author_obj,name="罗兵逊漂流记")
7     return HttpResponse('ok')

 

插入id值:

1 from django.shortcuts import render,HttpResponse
2 from mod import models
3 # Create your views here.
4 def insert(request):
5     models.Book.objects.create(b_author_id=2,name="陈二狗的妖孽人生")
6     return HttpResponse('ok')

需要注意的是:需要使用实际数据库存在的列(b_author_id)而不是django定义字段的列名字:b_author。

  • 在sqlalchemy中,插入的时候可以直接入相应类的对象(add()),或者可迭代对象集合(addall(元组、或者列表)),存在foreign key 列需要特别注意: 插入该列的值不是对象,而是关联表的主键nid值,不是对象!!!区别于django 插入外键的时候可以是对象或者id值。而且sqlalchemy定义的列名字就是数据库存储的名字。区别于django中在数据库层次的实际存储的列名字是django定义列的名字加上_id.

表结构:一个作者有多本书。book表示子表,相对author表为父表。

 1 class Author(Base):
 2     __tablename__='author'
 3     username=Column(String(32))
 4     nid=Column(Integer,primary_key=True,autoincrement=True)
 5     def __repr__(self):
 6         temp='%s--%s'%(self.nid,self.username)
 7         return temp
 8 
 9 class Book(Base):
10     __tablename__ = 'book'
11     nid = Column(Integer, primary_key=True, autoincrement=True)
12     name = Column(String(32))
13     b_a=Column(Integer,ForeignKey('author.nid'))
14     book=relationship('Author',backref='auth')
15 
16     def __repr__(self):
17         temp = '%s-%s' % (self.nid, self.name)
18         return temp
19 Base.metadata.create_all(engine)##执行该函数,他就会执行所有Base所有的子类。调用我们定义类并创建相应的表结构。

 插入值:

 1 author1=Author(username='evil')
 2 author2=Author(username='tom')
 3 author3=Author(username='jack')
 4 
 5 Session=sessionmaker(bind=engine)
 6 session=Session()
 7 session.add_all(
 8     [
 9         author1,
10         author2,
11         author3
12     ]
13 )
14 session.commit()
1 mysql> select * from author;
2 +----------+-----+
3 | username | nid |
4 +----------+-----+
5 | evil     |   1 |
6 | tom      |   2 |
7 | jack     |   3 |
8 +----------+-----+
9 3 rows in set (0.00 sec)

插入语句:注意外键的列插入的不是对象,而是相应的关联表的主键的值。即主表的主键nid值。

 1 book1=Book(name='百年孤独',b_a=3)
 2 book2=Book(name='陈二狗的妖孽人生',b_a=3)
 3 book3=Book(name='海贼王',b_a=3)
 4 
 5 session.add_all(
 6     (
 7         book1,
 8         book2,
 9         book3
10     )
11 )
12 session.commit()
 1 mysql> select * from book;
 2 +-----+--------------------------+------+
 3 | nid | name                     | b_a  |
 4 +-----+--------------------------+------+
 5 |   2 | 百年孤独                 |    2 |
 6 |   3 | 陈二狗的妖孽人生         |    2 |
 7 |   4 | 海贼王                   |    2 |
 8 |   5 | 百年孤独                 |    1 |
 9 |   6 | 陈二狗的妖孽人生         |    1 |
10 |   7 | 海贼王                   |    1 |
11 |   8 | 百年孤独                 |    3 |
12 |   9 | 陈二狗的妖孽人生         |    3 |
13 |  10 | 海贼王                   |    3 |
14 +-----+--------------------------+------+
15 9 rows in set (0.00 sec)
  • 出现的问题: 编码问题,如果我们在sqlalchemy中不指定编码的时候,底层dbapi采用的编码:latin-1进行编码,如果你插入的数据含有中文的话,由于latin-1在解码的时候,不支持中文会报错:

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 38-41: ordinal not in range(256)

解决方法:在数据连接引擎处指定编码,让sql语句中的中文部分按指定的编码进行解码。使用dbname?charset=utf8来指定相应的编码。

http://firefish.blog.51cto.com/298258/112794/

1 engine = create_engine("mysql+pymysql://root:@192.168.147.129:3306/sqlalchemy?charset=utf8",
2                        max_overflow=15)  # 创建数据库引擎,通过连接池获取数据库的连接。数据库连接池数量为:15,默认值是5.

所以以后再写引擎的时候,需要注意:直接写上面的连接串。

在mysql中修改编码的方法:在/etc/my.cnf 中添加入下语句,如果不添加client字段的话,在数据库中中文字段显示是?问号。但是程序查询的时候,还会正常显示中文。

1 [mysqld]
2 default-storage-engine=INNODB
3 default-character-set=utf8
4 [client]
5 default-character-set=utf8

因为有的版本mysql不支持参数:default-character-set=utf8 需要使用:character_set_server=utf8。

  •  建立外键的区别:django 中在一对多的情况下,使用的foreign key 。 在多对多,不创建第三张表的时候,使用ManyToMany字段。如果手动创建第三张表的时候使用foreign key来构建关系。sqlalchemy中,一对多、多对多的情况下,

都是用foreign key来构建关系。而且在多对多的情况下,需要手动构建表结构关系,创建第三张表,

  • 对外键列的插入方法的不同:在django中对于外键列插入值,可以是插入关联表的对象或者关联表的对应的主键列即id列2种方法,但是在sqlalchemy对于外键列只能插入父表中的定义的主键列的值比如:nid值,而不是对象。
  • 对于查询建立关系的区别:在django中,默认给咱们创建相应的查询的虚拟列比如一对多,反向查询:tablename_set  和tablename2种虚拟关系列。前者不能使用双下划线,后者可以使用双下划线。在sqlalchemy中需要我们手动创建一个不存在数据库的虚拟机列,使用(本表和关联表的虚拟关系列)=relationship('classname',backref='另一张表的虚拟关系列')进行查询。正向查询用:用等号的左边的列,反向查询的时候,用等号的右边的backref定义的虚拟关系列。

sqlalchemy:

表结构:

 1 class Author(Base):
 2     __tablename__='author'
 3     username=Column(String(32))
 4     nid=Column(Integer,primary_key=True,autoincrement=True)
 5     def __repr__(self):
 6         temp='%s--%s'%(self.nid,self.username)
 7         return temp
 8 
 9 class Book(Base):
10     __tablename__ = 'book'
11     nid = Column(Integer, primary_key=True, autoincrement=True)
12     name = Column(String(100))
13     b_a=Column(Integer,ForeignKey('author.nid'))
14     book=relationship('Author',backref='auth')
15     def __repr__(self):
16         temp = '%s-%s' % (self.nid, self.name)
17         return temp 

反向查询:使用子表中定义的列:book=relationship('Author',backref='auth') 建立的虚拟关系列:auth需要注意的是auth是另一个表的对象的集合。

需求场景:作者为:evil,都出那些书籍?

1 Session=sessionmaker(bind=engine)
2 session=Session()
3 res=session.query(Author).filter(Author.username=='evil').first()
4 for i in res.auth:
5     print(i.name)
6 百年孤独
7 陈二狗的妖孽人生
8 海贼王

正向查询:

需求场景:book表中nid=2的书作者是谁?

1 Session=sessionmaker(bind=engine)
2 session=Session()
3 ret=session.query(Book).filter(Book.nid==2).first()
4 print(ret.book.username)
5 
6 tom
  •  在django中对于大于、小于、等于、包含、不包含等使用的双下滑线:id__lt=2...    在sqlalchemy中直接使用  > < ==等。
  • 在django和sqlalchemy中如果查询条件为并的时候,都是用逗号。
1 Session=sessionmaker(bind=engine)
2 session=Session()
3 ret=session.query(Book).filter(Book.nid.in_((2,3,7)) ).all()
4 for i in ret:
5     print(i.name)
6 百年孤独
7 陈二狗的妖孽人生
8 海贼王

 

posted @ 2016-10-20 15:43  evil_liu  阅读(4262)  评论(1编辑  收藏  举报