flask & Python

本人的某程序需跑在其余账户,不过又要求读取/sys/class/dmi/id/product_uuid每便重启后,/sys/class/dmi/id/product_uuid文件的权限都会东山复起。请大佬给个方案。#chattr-i/sys/class/dmi/id/product_uuid#chattr:Inappropriateioctlfordevicewhilereadingflagson/sys/class/dmi/id/product_uuid

用作二个工程师,笔者有时候忘了和煦所具备的技艺。当专业并未有根据你想要的点子提升时,却超轻便忘记您有技术去改动它。几天前,我意识到,作者曾经对自家所贩卖的书的交账管理格局以为再也忍受不了了。笔者的书实现后,小编利用了多少个例外的数字商品开拓微机,在对它们多个都感到到不满后,作者用Python和Flask,多少个小时的小时写出了小编自身的缓慢解决方案。没有错!三个时辰!今后,这几个系统帮助着自家的书本付费流程,整个经过难以置信的简便,你能够在20秒内购买图书并开始读书。

end

最后,使用两个例外的花费微电脑,发送书籍更新特别耗费时间。十分的少个能很好的支撑立异,而自己盼望有个“一键”解决方案来发送笔者的图书更新。作者就没找到一个近乎的劳动。

end

有着Flask那样的工具对消释这个标题丰硕首要。正如像作为程序员这样进步,你应有树立你的一套肃清“大旨”难点的工具集。Flask就是很好的例子,因为十万火急的拼接三个web应用是一件普通的事体。

def insert_record(constant, params)

开始的时候,作者急需调整哪些来寄放在客商和交易消息。作者决定动用SQLAlchemy,因为sandman的原故,作者相比熟练它SQLAlchemy。Flask有二个插件叫Flask-SQLAlchemy,那使得结合使用两个特别轻便。因为自个儿无需其余花哨的数据库操作,小编选取SQLite作为作者的后台数据库。

t.string :uuid, null: false

足够直观。使用UUID作为三个U索罗德L变量,搜索交易音讯。如若存在,就反省是或不是还应该有可用下载次数,然后提供所购买的文书。不然,等着您的是404八花九裂。

uuids = class_name.attribute_names.select { |name| name.end_with? _uuid }

“Flask前来施救”或是“二个100行代码的数字商品开采应用方案”

多对多关系在数额的搬迁进度中实际上有一些有一对目迷五色,在 Mongoid 中选拔has_金沙国际网址,and_belongs_to_many 会在连带的文书档案下加多二个 tag_ids 或者 post_ids 数组:

用作二个开拓者,能窥看到您有工夫作育我们和数字世界的相互影响是很好的一件事。举个例子说,笔者会忘记,即使有部分科技(science and technology卡塔尔(قطر‎无法遵照自身料想的主意去干活,小编有力量转移它。从自动化学工业机械械式的天职譬喻输入数据,到活动排序和整合治理电子邮件,开辟者们有力量去简化他们每一天的职业。

c.namespace == #{database}.#{collection_name.to_s.pluralize}

今后,支付的有个别已经消除,作者索要增多贰个后端功用,在成就支付后开始化下载。因为本身使用UUID作为主键,所以本身同一能够运用它看作U奥迪Q3L。当有人访问包蕴UUID的U昂CoraL时,作者急需检查该UUID是否含有在数据库中。假设是的话,提供图书文件同期把剩余下载(downloads_left卡塔尔次数属性收缩1次。假使不是的话,就赶回404不当。下边是本身写的代码:

透过这段代码我们就足以轻易将原始的放置关系总体进行形成征引的涉及,将置于的关联产生援引除了做那四个改换之外,无需做别的的事务,无论是数量的询问依旧模型的创造都没有要求更换代码的实现,可是记得为子模型中父模型的外键加多索引,不然会产生父模型在获得自个儿抱有的总体子模型时变成全表扫描:

好啊,未来该给自家书了

主键与 UUID

class Product(db.Model):
tablename = 'product'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
file_name = db.Column(db.String)
version = db.Column(db.String)
is_active = db.Column(db.Boolean, default=True)
price = db.Column(db.Float)

next unless post.present? tag.present?

那几个表单的action 属性指向您的站点的贰个页面,当客商达成支付后就能够被带到这里。作者在自家的书本贩卖页面增多了5个这么的按键,还也是有叁个潜伏的表单栏,包涵了被交易成品的id(product_id)(1-5时期的一个整数)

{

拍卖支付

在起始化 RelationBuilder 时,假设大家传入了 constants,那么在调用 RelationBuilder#build金沙澳门官网网址,! 时就能够重新创立在那之中的全方位关乎,不过一旦未有传到就能暗中同意加载 ActiveRecord 中颇有的子类,并去掉在那之中富含 :: 的模型,也正是 ActiveRecord 中央银行使 has_and_belongs_to_many 创造的中间类,大家会在下一节中牵线怎么样独立管理多对多涉及:

class Purchase(db.Model):
tablename = 'purchase'
uuid = db.Column(db.String, primary_key=True)
email = db.Column(db.String)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'))
product = db.relationship(Product)
downloads_left = db.Column(db.Integer, default=5)

#www.js333com, migrate data from mongodb to mysql.

技艺越大…权利越大!

update_id_columns document

你能够看的自己利用了叁个mail 对象,这些目的来自于Flask-Mail包,那么些插件让发送邮件变得自在。作者就设置它使用维生霉素ail作为服务器,然后全体东西都得以健康干活了。

if constants.present?

除此以外,作者尝试运用谷歌(GoogleState of Qatar Analytics 在全路的探望中追踪访客,包罗他们的买单进度,这一进程也很繁重。笔者时常感觉到,如若本人能够让它专业起来,并且能够在自己的书籍页面实行A/B测量检验,笔者能不小地提升销量。但是因为无法很好的寻踪,小编就没那么幸运了。

大家不独有未有享受到 UUID 带来的有个别,它还在搬迁 MySQL 的长河中推动了极大的劳动,一方面是因为 ActiveRecord 的默许主键是整数,不扶植 32 字节长度的 UUID,借使想要不改换 MongoDB 的 UUID,直接迁移到 MySQL 中动用其实也未有啥难点,只是大家要将暗中认可的整数类型的主键形成字符串类型,同一时候要运用贰个UUID 生成器来保障具有的主键都是依据时间依次增加的同一时间不会冲突。

支配那样做之后,作者创设了三个app.py 文件同期创立了之类的模子:

builder.build!

当客商点击“Buy Now”按键后,他们应该单独被供给输入他们的email地址和银行卡消息。点击“Confirm”后被带到一个只此一家别无分店的ULacrosseL去下载书籍(特地为了此次交易而变化的)。一封包括那几个U讴歌RDXL的邮件应该被发送给顾客(幸免客户须求再行下载那本书)。对他们重新下载的次数应当有个限定(5次)。交易音讯和顾客新闻应该被寄放在在数据库中,发送书籍更新应该只是二个限令的事。

reset_callbacks class_name

正如你所看到的,笔者写代码的时候有些偷懒了(因为笔者正在愤怒的编制程序……)首先,笔者有四个内联HTML,在付费不成事时重返,还大概有已购买出售成功时重临寄邮资箱。这个东西应该被放在二个全局变量,也许,越来越好的点子是身处一个独自的文书中。别的,在创造Purchase 时作者并从未开展任何的错误检查。然而事实上,唯一大概出错的地点是尝试插入重复的 uuid,不过本人并不管不顾虑,因为发生的可能率太低了(潜台词:一丝一毫)。

-T output_directory

@app.route('/test')
def test():
return """<http><body><form action="buy" method="POST">
<script
src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="pk_test_w3qNBkDR8A4jkKejBmsMdH34"
data-amount="999"
data-name="jeffknupp.com"
data-description="Writing Idiomatic Python 3 PDF ($9.99)">
</script>
<input type="hidden" name="product_id" value="2" />
</form>
</body>
</html>
"""
if name == 'main':
sys.exit(app.run(debug=True))

大家能够运用如下的代码对数据开展搬迁,这段代码从 MongoDB 中遍历有些会集Collection 中的全体数码,然后将文书档案作为参数字传送入 block,然后再各自通过 DatabaseTransformer#delete_obsolete_columns 和 DatabaseTransformer#update_rename_columns 方法删除部分原来就有的列、更新一些数据列最终将全部的 id 列都形成 uuid:

最终,小编必要自己索要加上叁个测验来让自家得以照猫画虎交易进度。上边是测量试验代码和让这么些app运转的代码:

end

昨日,当本身收到三个顾客的邮件,抱怨支付进度是如何的坚苦並且告诉笔者恐怕为此损失了过多销量后,笔者再也忍受不下去了。笔者说了算整二个谈得来的数字商品管理应用方案。作者供给产生下边那样了工艺流程:

return

在向数据库增多了5种差别版本的书籍后(小编创制了五个populate_db.py 文件,并把那一个本子作为SQLAlchemy模型来增多进数据库),小编急需调整本人究竟要什么样管理支付。幸运的是,Stripe让选拔叁个银行卡变得特别简单,并且自身也曾经有了三个他们的账户。他们的”checkout.js”方案会在你的页面上创设一个表单和按键。当点击那个开关时,叁个精练又简单的讲的浮动层会弹出来。

当成功了对文书档案的各样操作之后,该方法会直接调用 DatabaseTransformer#insert_record 将数据插入 MySQL 对应的表中;我们得以向来动用如下的代码将有些 Collection 中的全体文书档案迁移到 MySQL 中:

支出微处理器的交账难点

title: xxx,

欧耶,笔者是个程序猿

class Tag ActiveRecord::Base

往下看,看本人是何等在一夜之间完毕本人本身的数字商品开采技术方案的。

Rails.application.eager_load!

眼看,作者的使用须要七个后带给拍卖一回成功付款。小编增添了以下那些函数来成功这一指标:

# db/migrate/20170908075625_create_posts.rb

在本身起头卖书的时候,笔者总结用了二种支付服务(一种是银行卡,另一种是PayPal)。最后,作者发觉了叁个方可支撑两岸的管理情势。不过笔者对它们都不乐意。最常用的百般支付微处理器,必要顾客在出卖商的种类中创制壹个账户,况且输入他们的邮箱地址(固然邮箱并从未用)。

tag = Tag.find_by_uuid model.tag_uuid

@app.route('/buy', methods=['POST'])
def buy():
stripe_token = request.form['stripeToken']
email = request.form['stripeEmail']
product_id = request.form['product_id']
product = Product.query.get(product_id)
try:
charge = stripe.Charge.create(
amount=int(product.price * 100),
currency='usd',
card=stripe_token,
description=email)
except stripe.CardError, e:
return """<html><body><h1>Card Declined</h1><p>Your chard could not
be charged. Please check the number and/or contact your credit card
company.</p></body></html>"""
print charge
purchase = Purchase(uuid=str(uuid.uuid4()),
email=email,
product=product)
db.session.add(purchase)
db.session.commit()
message = Message(
subject='Thanks for your purchase!',
sender="jeff@jeffknupp.com",
html="""<html><body><h1>Thanks for buying Writing Idiomatic Python!</h1>
<p>If you didn't already download your copy, you can visit
<a href=" private link</a>. You'll be able to
download the file up to five times, at which point the link will
expire.""".format(purchase.uuid),
recipients=[email])
with mail.connect() as conn:
conn.send(message)
return redirect('/{}'.format(purchase.uuid))

original_association_name,

眼看,那并非那么的复杂性。最复杂的一部分是动态变化导向特定书籍版本的惟一的UCRUISERL。其余的事务都挺简单的。

t.text :content, null: false

自然,分享你的小说雷同丰硕的最重要。假使笔者做一些东西,对自己要好有用,但尚未去享受给别人,作者就能够怠慢。“分享”不止意味着”把项目放进贰个GitHub公共仓库“。你还索要让大家掌握有这些事物。从邮件列表到论坛再到个体博客,平素都不缺少让我们通晓您创制了有的事物的途径。作者老是想尽回馈社区,因为笔者从当中获得了累累事物。

DatabaseTransformer.profiling do

@app.route('/<uuid>')
def download_file(uuid):
purchase = Purchase.query.get(uuid)
if purchase:
if purchase.downloads_left <= 0:
return """<html><body><h1>No downloads left!</h1><p>You have
exceeded the allowed number of downloads for this file. Please email
jeff@jeffknupp.com with any questions.</p></body></html>"""
purchase.downloads_left -= 1
db.session.commit()
return send_from_directory(directory='files',
filename=purchase.product.file_name, as_attachment=True)
else:
abort(404)

说起底一点,测验真的很要紧,若无测量试验,未有人能够不蔓不枝在校正大气的作业代码的历程中不抛弃任何的业务逻辑,以致一旦没有测验,超多政工逻辑也许在开辟的那一天就已经错过了。

剧透:程序的尾声结出偏巧是100行代码。对于这种规模的web应用,Flask是个很好的取舍。并无需大批量的模板(cough有如Django cough),可是有好些个很好的插件作为补助。Bottle会是别的三个不错的选料,可是小编这段时间都在用Flask,所以自身就选它了。

t.timestamps null: false

事实上小编对此自个儿能这么急忙简单让那全数专门的学问起来以为震动。整个应用程序包蕴在贰个100行代码的文本中。并且它替代了本人每Smart用的这几个主要性服务,小编对那多少个服务一向都不钟爱。最后,笔者得以追踪交易,未有此外难题,那让自个儿确信本人能够进步销量。

parent.collection.find({}).each do |parent_document|

ActiveRecord::Base.descendants.map do |klass|

model.save! validate: false

next unless parent_document[child_key_name]

end

在拍卖了 MongoDB 中只有的嵌入式关系随后,大家就必要减轻一些繁杂的集合类型了,例如数组和哈希,即使大家应用 MySQL5.7 或然 PostgreSQL 的话,其实并没有须求对他们实行拍卖,因为最新版本的 MySQL 和 PostgreSQL 已经提供了对 JSON 的支撑,然则小编依然将项目中的数组和哈希都产生了科学普及的数据布局。

从文书档案到事关

constant.reset_callbacks callback

.reject { |constant| constant.to_s.include?(::) }

从涉嫌到文档

embeds_many_to_has_many(Person, Address)

end

end.compact

end

跟关系重新建立有关的代码能够在 relation_builder.rb 找到完整的用于关系迁移的代码。

end.first

STDOUT.puts #{collection_name.to_s.yellow}: skipped

reset_callbacks constant

RelationBuilder.profiling do

总结

相对来讲于从 MySQL 到 MongoDB 的动员搬迁,反向的动员搬妥协麻烦了不独有一倍,那重即使因为 MongoDB 中的超多数据类型和聚合之间的关联在 MySQL 中都并官样文章,比如嵌入式的数据布局、数组和哈希等聚焦类型、多对多关系的贯彻,超多的标题都不是唯有能通过数量上的迁徙化解的,我们需求在对数据开展搬迁早先先对有的数据构造进行重构,本文中的后半部分会介绍须求管理的数据结构和逻辑。

def change

polymorphic_associations,

delete_obsolete_columns document, obsolete_columns

validate_presence_of :title, :content

$ mongoimport db database_name collection collection_name

.map { |attr| attr.gsub _id, _uuid }

STDOUT.puts #{index}/#{collection_count} if (index % 1000).zero?

在全体的数量都被插入到 MySQL 之后,大家经过 #find_by_uuid 查询的办法将 uuid 和 post_uuid 中的关系迁移到 id 和 post_id 中,并将与 uuid 相关的字段全体刨除,那样大家能够确认保证模型之间的涉嫌不会一扫而光,而且数据行的相对地方与迁移前别无二样。

end

module RelationBuilder

t.string :title, null: false

end

STDOUT.puts

has_and_belongs_to_many :posts

module DatabaseTransformer

unless collection.present?

uuids.each do |uuid|

class PostsTag ActiveRecord::Base; end

这段时间的贰个多月时间都在做数据库的迁徙专业,作者当下在支付的系列在三皇五帝是使用 MySQL 作为主要数据库的,后来是因为有个别政工上的案由从 MySQL 迁移到了 MongoDB,使用了多少个月的时刻后,由于数据库服务特不牢固,再增加无人招呼,同时MongoDB 本人就是无 Schema 的数据库,最终变成数据库的脏数据难点非常凄惨。方今协会的分子未有比较丰硕的 Rails 开垦经验,所以如故期望利用 ActiveRecord 加上 Migration 的章程对数码开展局地强约束,有限支撑数据库中多少的法定。

在搬迁的进度中能够将 MySQL 中的全部数额以 csv 的格式导出,然后再将富有 csv 格式的多少应用 mongoimport 全体导入到 MongoDB 中:

def tag_titles

当大家希图将数据库深透迁移到 MySQL 从前,须求做一些预备专门的工作,将最终迁移所急需的干活尽量地削减,保障停机的时日不会太长,计划干活的目的就是尽大概肃清工程中复杂的数据布局。

constant = collection_name.to_s.singularize.camelcase.constantize

add_index :posts, :uuid, unique: true

end

上述代码打字与印刷出了七个 has_and_belongs_to_many 生成的类 Tag::HABTM_Posts 和 Post::HABTM_Tags,它们具有完全相近的表 posts_tags,管理多对多关系时,大家只需求在利用 DatabaseTransformer 导入表中的全体的多寡以往,再经过遍历 posts_tags 表中的数据更新多对多的关系表就足以了:

def split_categories

Mongoid 在接收时都以由此 include 将有关措施加载到近期模型中的,而 ActiveRecord 是通过三回九转 ActiveRecord::Base 的秘籍利用的,达成了对数据的预管理,大家就能够对现成模型层的代码进行退换了。

将全部的数码总体陈设到 MySQL 的表之后,模型之间还尚无其余显式的关系,大家还索要将因而 uuid 连接的模子转变到使用 id 的主意,对象时期的涉及才干通过点语法直接待上访谈,关系的创制其实特别轻便,我们获得当前类具备结尾为 _uuid 的属性,然后遍历全数的多寡行,依照 uuid 的值和 post_uuid 属性中的 “post” 部分得到到表名,最后赢得相应的涉嫌模型,在这里处我们也管理了相似多态的极度规景况:

end

具有应用 has_and_belongs_to_many 的多对多涉及都急需通过上述代码举办搬迁,这一步供给在剔除数据库中的所有uuid 字段此前产生。

document = yield document if block_given?

原稿来自Wechat大伙儿号:DBAplus社群

当大家依据 _id 的逐二回历整个文书档案,将文书档案中的数据被插入到表中时,MySQL 会为持有的数目行自动生成的依次增加的主键 id,而 post_id 在这里时都为空。