它将django模型转换为sqlalchemy orm/expression对象。
d2a的Python项目详细描述
要求
- Python:2.7.15或更高版本,3.4或更高版本。
- 使用2.7.15、3.6进行测试
- django:1.9或更高版本。
- 用1.11、2.0、2.1进行测试
- sqlalchemy:0.9或更高版本。
- 用1.2 测试
安装
$ pip install d2a
用法
自动加载
只需将d2a添加到settings.INSTALLED_APPS。
INSTALLED_APPS=['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',# top or here'd2a',# example apps'books','sales',]
警告
把它放在你能做的应用之前。 因为它希望在另一个apps.py之前注册炼金术模型。
然后,所有应用程序中的模型都将作为模块导入。
>>>frombooksimportmodels_sqla>>>models_sqla.# tab completionmodels_sqla.Author(models_sqla.BookCategory(models_sqla.CategoryRelation(models_sqla.transfer(models_sqla.Book(models_sqla.Category(models_sqla.models>>>models_sqla.Book<class'd2a.book'>>>>models_sqla.Book.# tab completionmodels_sqla.Book.authormodels_sqla.Book.contentmodels_sqla.Book.metadatamodels_sqla.Book.tagsmodels_sqla.Book.author_idmodels_sqla.Book.descriptionmodels_sqla.Book.mro(models_sqla.Book.titlemodels_sqla.Book.categorymodels_sqla.Book.idmodels_sqla.Book.price# SQL Expression schema>>>models_sqla.Book.__table__Table('book',MetaData(bind=None),Column('id',UUID(),table=<book>,primary_key=True,nullable=False,default=ColumnDefault(<functionuuid4at0x7f3cebe7e598>)),Column('price',JSON(astext_type=Text()),table=<book>,nullable=False),Column('title',VARCHAR(length=255),table=<book>,nullable=False),Column('description',TEXT(),table=<book>),Column('author_id',INTEGER(),ForeignKey('author.id'),table=<book>),Column('content',BYTEA(),table=<book>,nullable=False),Column('tags',ARRAY(VARCHAR()),table=<book>,nullable=False),schema=None)
此外,它还可以根据m2m字段提取隐式声明的模型。 (在这种情况下,图书类别)
注意
您可以将配置设置为settings.py。
示例:
# This variable can be omitted.D2A_CONFIG={'AUTOLOAD':{# optional# module name: It can be used different module name from `models_sqla`.'module':'modelsa',# optional, default: 'models_sqla'# waiting seconds during autoloading'seconds':5,# default: 1# transfer function's args after 'exports' arg.'option':{# optional'db_type':'postgresql',# default: 'default''back_type':'backref',# default: 'backref''as_table':True,# default: False'name_formatter':str.upper,# default: get_camelcase}},# converting rules for customized fields'ALIASES':{# optional# Evaluates ExtendedImageField as ImageFieldExtendedImageField:models.ImageField,},}
每个模型模块
如果要手动创建模块,请在应用程序中创建models_sqla.py。
按如下方式书写:
fromd2aimporttransferfrom.importmodelstransfer(models,globals())<> > >模型Sq.Laq.Py < /c> >,将省略自动模块创建。
如果您手动创建每个模型, 无需将d2a设置为settings.INSTALLED_APPS。
示例:
- project_postgresql/books/models_sqla.py
- 您可以省略指定数据库类型,然后它会自动检测来自settings.DATABASES['default']的数据库类型。
- 现在允许postgresql,mysql和oracle, 其他类型将转换为default类型: sqlalchemy/types.py
每个型号
如果只想转换一个模型,应该使用declare函数。
>>>fromd2aimportdeclare>>>fromsales.modelsimportSales>>>sales=declare(Sales)>>>sales<class'd2a.sales'>>>>sales.__table__Table('sales',MetaData(bind=None),Column('id',BIGINT(),table=<sales>,primary_key=True,nullable=False),Column('book_id',UUID(),ForeignKey('book.id'),table=<sales>,nullable=False),Column('sold',TIMESTAMP(),table=<sales>,nullable=False),Column('reservation',INTERVAL(),table=<sales>),Column('source',INET(),table=<sales>),schema=None)>>>sales.sales.booksales.idsales.mro(sales.soldsales.book_idsales.metadatasales.reservationsales.source
自定义字段
如果您使用的是自定义字段(不是内置的), 您可以使用alias或alias\u dict方法将该字段注册为另一个字段。
fromdjango.db.modelsimportImageFieldclassExtendedImageField(ImageField):"""something customizing"""fromd2aimportaliasalias(ExtendedImageField,ImageField)# oralias_dict({ExtendedImageField:ImageField,})
查询快捷方式
orm
orm模式有一个名为make_session的函数。
>>>fromd2aimportmake_session>>>frombooks.models_sqlaimportAuthor>>>withmake_session()assession:...# it commits and flushes automatically when the scope exits....a=Author()...a.name='righ'...a.age=30...session.add(a)...>>>withmake_session()assession:...# when the session was rolled back or causes some exception in the context,...# it won't register records in the session....a=Author()...a.name='teruhiko'...a.age=85...session.add(a)...session.rollback()...>>>withmake_session()assession:...session.query(Author.name,Author.age).all()...[('righ',30)]
它接收以下参数:
engine: | engine object or database-type (string) (default: None). When it is omitted, it guesses database type and gets an engine automatically. |
---|---|
autoflush: | It is the same as sessionmaker (default: True) |
autocommit: | It is the same as sessionmaker (default: False) |
expire_on_commit: | |
It is the same as sessionmaker (default: True) | |
info: | It is the same as sessionmaker (default: None) |
所有参数都可以省略。
表达式
有两个功能。
query_expression: | |
---|---|
To retrieve SELECT results, and returns a list containing record. | |
execute_expression: | |
To execute INSERT, DELETE, UPDATE statements, and returns num of records having been affected. |
>>>fromsqlalchemyimport(...select,...insert,...)>>>fromd2aimportquery_expression,execute_expression# if you try on `project_mysql` demo, you should write ``from books.modelsa import Author``>>>frombooks.models_sqlaimportAuthor>>>AuthorTable=Author.__table__>>>records=[...{'name':'a','age':10},...{'name':'b','age':30},...{'name':'c','age':20},...]>>># insert>>>stmt=insert(AuthorTable).values(records)>>>execute_expression(stmt)3>>># select>>>stmt=select([...AuthorTable.c.id,...AuthorTable.c.name,...AuthorTable.c.age,...]).select_from(AuthorTable).order_by(AuthorTable.c.age)>>>query_expression(stmt)[OrderedDict([('id',12),('name','a'),('age',10)]),OrderedDict([('id',14),('name','c'),('age',20)]),OrderedDict([('id',13),('name','b'),('age',30)])]>>># record as tuple>>>query_expression(stmt,as_col_dict=False)[(12,'a',10),(14,'c',20),(13,'b',30)]>>>query_expression(stmt,as_col_dict=False,debug={'printer':print,'show_explain':True,'sql_format':True})====================================================================================================SELECTauthor.id,author.name,author.ageFROMauthorORDERBYauthor.age====================================================================================================Sort(cost=16.39..16.74rows=140width=522)(actualtime=0.027..0.028rows=18loops=1)SortKey:ageSortMethod:quicksortMemory:25kB->SeqScanonauthor(cost=0.00..11.40rows=140width=522)(actualtime=0.007..0.009rows=18loops=1)Planningtime:0.072msExecutiontime:0.047ms[(12,'a',10),(14,'c',20),(13,'b',30)]
注意
我添加了query_expression()的参数以查看调试信息。
将选项指定为dict type,如下所示:
query_expression(stmt,debug={# all options can be skipped.'show_sql':True,# if showing the sql query or not.'show_explain':False,# if showing explain for the sql query or not.'sql_format':False,# if formatting the sql query or not.'sql_reindent':True,# if setting indent the sql query or not.'sql_keyword_case':'upper',# A rule converting reserved words.'explain_prefix':dependsonthedatabasetype.unlessyouspecifyit,anappropriateprefixwillbeautomaticallyused.'printer':logger.debug,# printing method, if you use python3, then try `print` function.'delimiter':'='*100,# characters dividing debug informations.'database':'default'# django database})
默认值是{}(空dict表示禁用调试。)
警告
支持的自动检测数据库类型如下:
- PostgreSQL
- mysql
- 甲骨文
演示
启动环境
$ git clone git@github.com:walkframe/d2a.git
$ cd d2a
$ docker-compose up
准备
$ docker exec -it d2a_app_1 /bin/bash # python -m venv venv # only first time # source venv/bin/activate (venv)# cd project_postgresql/ # (or mysql) (venv) project_postgresql # ./manage.py migrate
执行
(venv) project_postgresql # ./manage.py shell
>>>frombooksimportmodels_sqla>>>book=models_sqla.Book()>>>author=models_sqla.Author()>>>book.author=author>>>author.books[<d2a.bookobjectat0x7f3cec539358>]# And do something you want do ;)
历史记录
2.1.0: |
| ||||||
---|---|---|---|---|---|---|---|
2.0.0: |
| ||||||
1.1.x: |
| ||||||
1.0.2: |
| ||||||
1.0.1: |
| ||||||
1.0.0: |
| ||||||
0.0.6: |
| ||||||
0.0.5: |
| ||||||
0.0.4: |
| ||||||
0.0.3: |
| ||||||
0.0.2: |
| ||||||
0.0.1: | 第一版(2017-12-27) |