直线与空间坐标系XY轴上的数字怎么理解?轴成84°与Y轴成82°与Z轴成10°,这样的直线存在吗?

&figure&&img src=&https://pic2.zhimg.com/v2-3c221b5c58e0bd0dec93d85eed7a78bd_b.jpg& data-rawwidth=&1024& data-rawheight=&768& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&https://pic2.zhimg.com/v2-3c221b5c58e0bd0dec93d85eed7a78bd_r.jpg&&&/figure&&p&此专栏我会不定期分享一些 Django 最前沿的文章,内容偏重技巧、经验的归纳总结,来源暂时有:&/p&&ol&&li&&a href=&https://link.zhihu.com/?target=https%3A//medium.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Medium&/a&&/li&&li&&a href=&https://link.zhihu.com/?target=https%3A//twitter.com/tmpboo& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Twitter&/a& 知名博主&/li&&/ol&&p&如果大家感兴趣,请一定点个关注,给我一些动力,毕竟翻译整理是需要时间的,谢谢大家&/p&&p&--&/p&&blockquote&原文地址:&a href=&https://link.zhihu.com/?target=https%3A//medium.com/%40hakibenita/9-django-tips-for-working-with-databases-beba787ed7d3& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&9 Django Tips for Working with Databases&/a&&br&原文作者:&a href=&https://link.zhihu.com/?target=https%3A//medium.com/%40hakibenita%3Fsource%3Dpost_header_lockup& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Haki Benita&/a&&br&译者:&a href=&https://www.zhihu.com/people/tmpbook& class=&internal&&临书&/a&&br&校对:&a href=&https://www.zhihu.com/people/tmpbook& class=&internal&&临书&/a&&br&推荐程度:?????&/blockquote&&p&对开发人员来说,ORM 确实非常实用,但是将数据库的访问抽象出来本身是有成本的,那些愿意在数据库中探索的开发人员,经常会发现修改 ORM 的默认行为可以带来性能的提升。&/p&&p&&b&在本文中,我将分享在 Django 中使用数据库的 9 个技巧&/b&&/p&&hr&&h2&1. 过滤器聚合(Aggregation with Filter)&/h2&&p&在 Django 2.0 之前,如果我们想要得到诸如用户总数和活跃用户总数之类的东西,我们不得不求助于&a href=&https://link.zhihu.com/?target=https%3A//docs.djangoproject.com/en/2.0/ref/models/conditional-expressions/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&条件表达式&/a&:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&django.contrib.auth.models&/span& &span class=&kn&&import&/span& &span class=&n&&User&/span&
&span class=&kn&&from&/span& &span class=&nn&&django.db.models&/span& &span class=&kn&&import&/span& &span class=&p&&(&/span&
&span class=&n&&Count&/span&&span class=&p&&,&/span&
&span class=&n&&Sum&/span&&span class=&p&&,&/span&
&span class=&n&&Case&/span&&span class=&p&&,&/span&
&span class=&n&&When&/span&&span class=&p&&,&/span&
&span class=&n&&Value&/span&&span class=&p&&,&/span&
&span class=&n&&IntegerField&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&span class=&n&&User&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&aggregate&/span&&span class=&p&&(&/span&
&span class=&n&&total_users&/span&&span class=&o&&=&/span&&span class=&n&&Count&/span&&span class=&p&&(&/span&&span class=&s1&&'id'&/span&&span class=&p&&),&/span&
&span class=&n&&total_active_users&/span&&span class=&o&&=&/span&&span class=&n&&Sum&/span&&span class=&p&&(&/span&&span class=&n&&Case&/span&&span class=&p&&(&/span&
&span class=&n&&When&/span&&span class=&p&&(&/span&&span class=&n&&is_active&/span&&span class=&o&&=&/span&&span class=&bp&&True&/span&&span class=&p&&,&/span& &span class=&n&&then&/span&&span class=&o&&=&/span&&span class=&n&&Value&/span&&span class=&p&&(&/span&&span class=&mi&&1&/span&&span class=&p&&)),&/span&
&span class=&n&&default&/span&&span class=&o&&=&/span&&span class=&n&&Value&/span&&span class=&p&&(&/span&&span class=&mi&&0&/span&&span class=&p&&),&/span&
&span class=&n&&output_field&/span&&span class=&o&&=&/span&&span class=&n&&IntegerField&/span&&span class=&p&&(),&/span&
&span class=&p&&)),&/span&
&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&在 Django 2.0 中,添加了&a href=&https://link.zhihu.com/?target=https%3A//docs.djangoproject.com/en/2.0/ref/models/querysets/%23id6& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&聚合函数的过滤器参数&/a&,使其更容易:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&django.contrib.auth.models&/span& &span class=&kn&&import&/span& &span class=&n&&User&/span&
&span class=&kn&&from&/span& &span class=&nn&&django.db.models&/span& &span class=&kn&&import&/span& &span class=&n&&Count&/span&&span class=&p&&,&/span& &span class=&n&&F&/span&
&span class=&n&&User&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&aggregate&/span&&span class=&p&&(&/span&
&span class=&n&&total_users&/span&&span class=&o&&=&/span&&span class=&n&&Count&/span&&span class=&p&&(&/span&&span class=&s1&&'id'&/span&&span class=&p&&),&/span&
&span class=&n&&total_active_users&/span&&span class=&o&&=&/span&&span class=&n&&Count&/span&&span class=&p&&(&/span&&span class=&s1&&'id'&/span&&span class=&p&&,&/span& &span class=&nb&&filter&/span&&span class=&o&&=&/span&&span class=&n&&F&/span&&span class=&p&&(&/span&&span class=&s1&&'is_active'&/span&&span class=&p&&)),&/span&
&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&很棒,又短又可口&/p&&p&如果你正在使用 PostgreSQL,这两个查询将如下所示:&/p&&div class=&highlight&&&pre&&code class=&language-sql&&&span&&/span&&span class=&k&&SELECT&/span&
&span class=&k&&COUNT&/span&&span class=&p&&(&/span&&span class=&n&&id&/span&&span class=&p&&)&/span& &span class=&k&&AS&/span& &span class=&n&&total_users&/span&&span class=&p&&,&/span&
&span class=&k&&SUM&/span&&span class=&p&&(&/span&&span class=&k&&CASE&/span& &span class=&k&&WHEN&/span& &span class=&n&&is_active&/span& &span class=&k&&THEN&/span& &span class=&mi&&1&/span& &span class=&k&&ELSE&/span& &span class=&mi&&0&/span& &span class=&k&&END&/span&&span class=&p&&)&/span& &span class=&k&&AS&/span& &span class=&n&&total_active_users&/span&
&span class=&k&&FROM&/span&
&span class=&n&&auth_users&/span&&span class=&p&&;&/span&
&span class=&k&&SELECT&/span&
&span class=&k&&COUNT&/span&&span class=&p&&(&/span&&span class=&n&&id&/span&&span class=&p&&)&/span& &span class=&k&&AS&/span& &span class=&n&&total_users&/span&&span class=&p&&,&/span&
&span class=&k&&COUNT&/span&&span class=&p&&(&/span&&span class=&n&&id&/span&&span class=&p&&)&/span& &span class=&n&&FILTER&/span& &span class=&p&&(&/span&&span class=&k&&WHERE&/span& &span class=&n&&is_active&/span&&span class=&p&&)&/span& &span class=&k&&AS&/span& &span class=&n&&total_active_users&/span&
&span class=&k&&FROM&/span&
&span class=&n&&auth_users&/span&&span class=&p&&;&/span&
&/code&&/pre&&/div&&p&第二个查询使用了 &code&WHERE&/code& 过滤子句。&/p&&hr&&h2&2. 查询集的结果变为具名元组(QuerySet results as namedtuples)&/h2&&p&我是一个 namedtuples 的粉丝,同时也是 Django 2.0 的 ORM 的粉丝。&/p&&p&在 Django 2.0 中,&code&values_list&/code& 方法的参数中添加了一个叫做 &code&named&/code& 的属性。将 &code&named&/code& 设置为 &code&True&/code& 会将 QuerySet 作为 namedtuples 列表返回:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&o&&&&/span& &span class=&n&&user&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&values_list&/span&&span class=&p&&(&/span&
&span class=&s1&&'first_name'&/span&&span class=&p&&,&/span&
&span class=&s1&&'last_name'&/span&&span class=&p&&,&/span&
&span class=&p&&)[&/span&&span class=&mi&&0&/span&&span class=&p&&]&/span&
&span class=&p&&(&/span&&span class=&err&&‘&/span&&span class=&n&&Haki&/span&&span class=&err&&’&/span&&span class=&p&&,&/span& &span class=&err&&‘&/span&&span class=&n&&Benita&/span&&span class=&err&&’&/span&&span class=&p&&)&/span&
&span class=&o&&&&/span& &span class=&n&&user_names&/span& &span class=&o&&=&/span& &span class=&n&&User&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&values_list&/span&&span class=&p&&(&/span&
&span class=&s1&&'first_name'&/span&&span class=&p&&,&/span&
&span class=&s1&&'last_name'&/span&&span class=&p&&,&/span&
&span class=&n&&named&/span&&span class=&o&&=&/span&&span class=&bp&&True&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&span class=&o&&&&/span& &span class=&n&&user_names&/span&&span class=&p&&[&/span&&span class=&mi&&0&/span&&span class=&p&&]&/span&
&span class=&n&&Row&/span&&span class=&p&&(&/span&&span class=&n&&first_name&/span&&span class=&o&&=&/span&&span class=&s1&&'Haki'&/span&&span class=&p&&,&/span& &span class=&n&&last_name&/span&&span class=&o&&=&/span&&span class=&s1&&'Benita'&/span&&span class=&p&&)&/span&
&span class=&o&&&&/span& &span class=&n&&user_names&/span&&span class=&p&&[&/span&&span class=&mi&&0&/span&&span class=&p&&]&/span&&span class=&o&&.&/span&&span class=&n&&first_name&/span&
&span class=&s1&&'Haki'&/span&
&span class=&o&&&&/span& &span class=&n&&user_names&/span&&span class=&p&&[&/span&&span class=&mi&&0&/span&&span class=&p&&]&/span&&span class=&o&&.&/span&&span class=&n&&last_name&/span&
&span class=&s1&&'Benita'&/span&
&/code&&/pre&&/div&&hr&&h2&3. 自定义函数(Custom functions)&/h2&&p&Django 2.0 的 ORM 功能非常强大,而且特性丰富,但还是不能与所有数据库的特性同步。不过幸运的是,ORM让我们用自定义函数来扩展它。&/p&&p&假设我们有一个记录报告的持续时间字段,我们希望找到所有报告的平均持续时间:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&django.db.models&/span& &span class=&kn&&import&/span& &span class=&n&&Avg&/span&
&span class=&n&&Report&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&aggregate&/span&&span class=&p&&(&/span&&span class=&n&&avg_duration&/span&&span class=&o&&=&/span&&span class=&n&&Avg&/span&&span class=&p&&(&/span&&span class=&err&&‘&/span&&span class=&n&&duration&/span&&span class=&err&&’&/span&&span class=&p&&))&/span&
&span class=&o&&&&/span& &span class=&p&&{&/span&&span class=&s1&&'avg_duration'&/span&&span class=&p&&:&/span& &span class=&n&&datetime&/span&&span class=&o&&.&/span&&span class=&n&&timedelta&/span&&span class=&p&&(&/span&&span class=&mi&&0&/span&&span class=&p&&,&/span& &span class=&mi&&0&/span&&span class=&p&&,&/span& &span class=&mi&&55432&/span&&span class=&p&&)}&/span&
&/code&&/pre&&/div&&p&那很棒,但是如果只有均值,信息量有点少。我们再算出标准偏差吧:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&django.db.models&/span& &span class=&kn&&import&/span& &span class=&n&&Avg&/span&&span class=&p&&,&/span& &span class=&n&&StdDev&/span&
&span class=&n&&Report&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&aggregate&/span&&span class=&p&&(&/span&
&span class=&n&&avg_duration&/span&&span class=&o&&=&/span&&span class=&n&&Avg&/span&&span class=&p&&(&/span&&span class=&s1&&'duration'&/span&&span class=&p&&),&/span&
&span class=&n&&std_duration&/span&&span class=&o&&=&/span&&span class=&n&&StdDev&/span&&span class=&p&&(&/span&&span class=&s1&&'duration'&/span&&span class=&p&&),&/span&
&span class=&p&&)&/span&
&span class=&n&&ProgrammingError&/span&&span class=&p&&:&/span& &span class=&n&&function&/span& &span class=&n&&stddev_pop&/span&&span class=&p&&(&/span&&span class=&n&&interval&/span&&span class=&p&&)&/span& &span class=&n&&does&/span& &span class=&ow&&not&/span& &span class=&n&&exist&/span&
&span class=&n&&LINE&/span& &span class=&mi&&1&/span&&span class=&p&&:&/span& &span class=&n&&SELECT&/span& &span class=&n&&STDDEV_POP&/span&&span class=&p&&(&/span&&span class=&s2&&&report&&/span&&span class=&o&&.&/span&&span class=&s2&&&duration&&/span&&span class=&p&&)&/span& &span class=&n&&AS&/span& &span class=&s2&&&std_dura...&/span&
&span class=&o&&^&/span&
&span class=&n&&HINT&/span&&span class=&p&&:&/span&
&span class=&n&&No&/span& &span class=&n&&function&/span& &span class=&n&&matches&/span& &span class=&n&&the&/span& &span class=&n&&given&/span& &span class=&n&&name&/span& &span class=&ow&&and&/span& &span class=&n&&argument&/span& &span class=&n&&types&/span&&span class=&o&&.&/span&
&span class=&n&&You&/span& &span class=&n&&might&/span& &span class=&n&&need&/span& &span class=&n&&to&/span& &span class=&n&&add&/span& &span class=&n&&explicit&/span& &span class=&nb&&type&/span& &span class=&n&&casts&/span&&span class=&o&&.&/span&
&/code&&/pre&&/div&&p&呃... PostgreSQL 不支持间隔类型字段的求标准偏差操作,我们需要将时间间隔转换为数字,然后才能对它应用 &code&STDDEV_POP&/code& 操作。&/p&&p&一个选择是从时间间隔中提取:&/p&&div class=&highlight&&&pre&&code class=&language-sql&&&span&&/span&&span class=&k&&SELECT&/span&
&span class=&k&&AVG&/span&&span class=&p&&(&/span&&span class=&n&&duration&/span&&span class=&p&&),&/span&
&span class=&n&&STDDEV_POP&/span&&span class=&p&&(&/span&&span class=&k&&EXTRACT&/span&&span class=&p&&(&/span&&span class=&n&&EPOCH&/span& &span class=&k&&FROM&/span& &span class=&n&&duration&/span&&span class=&p&&))&/span&
&span class=&k&&FROM&/span&
&span class=&n&&report&/span&&span class=&p&&;&/span&
&span class=&k&&avg&/span&
&span class=&o&&|&/span&
&span class=&n&&stddev_pop&/span&
&span class=&c1&&----------------+------------------&/span&
&span class=&mi&&00&/span&&span class=&p&&:&/span&&span class=&mi&&00&/span&&span class=&p&&:&/span&&span class=&mi&&00&/span&&span class=&p&&.&/span&&span class=&mi&&55432&/span& &span class=&o&&|&/span& &span class=&mi&&1&/span&&span class=&p&&.&/span&&span class=&mi&&49&/span&
&span class=&p&&(&/span&&span class=&mi&&1&/span& &span class=&k&&row&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&那么我们如何在 Django 中实现呢?你猜到了 -- 一个自定义函数:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&c1&&# common/db.py&/span&
&span class=&kn&&from&/span& &span class=&nn&&django.db.models&/span& &span class=&kn&&import&/span& &span class=&n&&Func&/span&
&span class=&k&&class&/span& &span class=&nc&&Epoch&/span&&span class=&p&&(&/span&&span class=&n&&Func&/span&&span class=&p&&):&/span&
&span class=&n&&function&/span& &span class=&o&&=&/span& &span class=&s1&&'EXTRACT'&/span&
&span class=&n&&template&/span& &span class=&o&&=&/span& &span class=&s2&&&&/span&&span class=&si&&%(function)s&/span&&span class=&s2&&('epoch' from &/span&&span class=&si&&%(expressions)s&/span&&span class=&s2&&)&&/span&
&/code&&/pre&&/div&&p&我们的新函数这样使用:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&django.db.models&/span& &span class=&kn&&import&/span& &span class=&n&&Avg&/span&&span class=&p&&,&/span& &span class=&n&&StdDev&/span&&span class=&p&&,&/span& &span class=&n&&F&/span&
&span class=&kn&&from&/span& &span class=&nn&&common.db&/span& &span class=&kn&&import&/span& &span class=&n&&Epoch&/span&
&span class=&n&&Report&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&aggregate&/span&&span class=&p&&(&/span&
&span class=&n&&avg_duration&/span&&span class=&o&&=&/span&&span class=&n&&Avg&/span&&span class=&p&&(&/span&&span class=&s1&&'duration'&/span&&span class=&p&&),&/span&
&span class=&n&&std_duration&/span&&span class=&o&&=&/span&&span class=&n&&StdDev&/span&&span class=&p&&(&/span&&span class=&n&&Epoch&/span&&span class=&p&&(&/span&&span class=&n&&F&/span&&span class=&p&&(&/span&&span class=&s1&&'duration'&/span&&span class=&p&&))),&/span&
&span class=&p&&)&/span&
&span class=&p&&{&/span&&span class=&s1&&'avg_duration'&/span&&span class=&p&&:&/span& &span class=&n&&datetime&/span&&span class=&o&&.&/span&&span class=&n&&timedelta&/span&&span class=&p&&(&/span&&span class=&mi&&0&/span&&span class=&p&&,&/span& &span class=&mi&&0&/span&&span class=&p&&,&/span& &span class=&mi&&55432&/span&&span class=&p&&),&/span&
&span class=&s1&&'std_duration'&/span&&span class=&p&&:&/span& &span class=&mf&&1.49&/span&&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&*注意在 Epoch 调用中使用 F 表达式。&/p&&hr&&h2&4. 声明超时(Statement Timeout)&/h2&&p&这可能是我给的最简单的也是最重要的提示。我们是人类,我们都会犯错。我们不可能考虑到每一个边缘情况,所以我们必须设定边界。&/p&&p&与其他非阻塞应用程序服务器(如 Tornado,asyncio 甚至 Node)不同,Django 通常使用同步工作进程。这意味着,当用户执行长时间运行的操作时,工作进程会被阻塞,完成之前,其他人无法使用它。&/p&&p&应该没有人真正在生产中只用一个工作进程来运行 Django,但是我们仍然希望确保一个查询不会浪费太多资源太久。&/p&&p&在大多数 Django 应用程序中,大部分时间都花在等待数据库查询上了。所以,在 SQL 查询上设置超时是一个很好的开始。&/p&&p&我喜欢像这样在我的 &code&wsgi.py&/code& 文件中设置一个全局超时:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&c1&&# wsgi.py&/span&
&span class=&kn&&from&/span& &span class=&nn&&django.db.backends.signals&/span& &span class=&kn&&import&/span& &span class=&n&&connection_created&/span&
&span class=&kn&&from&/span& &span class=&nn&&django.dispatch&/span& &span class=&kn&&import&/span& &span class=&n&&receiver&/span&
&span class=&nd&&@receiver&/span&&span class=&p&&(&/span&&span class=&n&&connection_created&/span&&span class=&p&&)&/span&
&span class=&k&&def&/span& &span class=&nf&&setup_postgres&/span&&span class=&p&&(&/span&&span class=&n&&connection&/span&&span class=&p&&,&/span& &span class=&o&&**&/span&&span class=&n&&kwargs&/span&&span class=&p&&):&/span&
&span class=&k&&if&/span& &span class=&n&&connection&/span&&span class=&o&&.&/span&&span class=&n&&vendor&/span& &span class=&o&&!=&/span& &span class=&s1&&'postgresql'&/span&&span class=&p&&:&/span&
&span class=&k&&return&/span&
&span class=&c1&&# Timeout statements after 30 seconds.&/span&
&span class=&k&&with&/span& &span class=&n&&connection&/span&&span class=&o&&.&/span&&span class=&n&&cursor&/span&&span class=&p&&()&/span& &span class=&k&&as&/span& &span class=&n&&cursor&/span&&span class=&p&&:&/span&
&span class=&n&&cursor&/span&&span class=&o&&.&/span&&span class=&n&&execute&/span&&span class=&p&&(&/span&&span class=&s2&&&&&&/span&
&span class=&s2&&
SET statement_timeout TO 30000;&/span&
&span class=&s2&&
&&&&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&&b&为什么是 wsgi.py?&/b& 因为这样它只会影响工作进程,不会影响进程外的分析查询,cron 任务等。&/p&&p&希望您使用的是持久的数据库连接,这样每次请求都不会再有连接开销。&/p&&p&超时也可以配置到用户粒度:&/p&&div class=&highlight&&&pre&&code class=&language-psql&&&span&&/span&&span class=&gp&&postgresql=#&/span&&span class=&o&&&&/span& &span class=&k&&alter&/span& &span class=&k&&user&/span& &span class=&n&&app_user&/span& &span class=&k&&set&/span& &span class=&n&&statement_timeout&/span& &span class=&k&&TO&/span& &span class=&mf&&30000&/span&&span class=&p&&;&/span&
&span class=&go&&ALTER ROLE&/span&
&/code&&/pre&&/div&&p&题外话:我们花了很多时间在其他常见的地方,比如网络。因此,请确保在调用远程服务时始终设置超时时间:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&import&/span& &span class=&nn&&requests&/span&
&span class=&n&&response&/span& &span class=&o&&=&/span& &span class=&n&&requests&/span&&span class=&o&&.&/span&&span class=&n&&get&/span&&span class=&p&&(&/span&
&span class=&s1&&'https://api.slow-as-hell.com'&/span&&span class=&p&&,&/span&
&span class=&n&&timeout&/span&&span class=&o&&=&/span&&span class=&mi&&3000&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&/code&&/pre&&/div&&hr&&h2&5. 限制(Limit)&/h2&&p&这与设置边界的最后一点有些相关。有时我们的客户的一些行为是不可预知的&/p&&p&比如,同一用户打开另一个选项卡并在第一次尝试「卡住」时再试一次并不罕见。&/p&&p&&br&&/p&&p&&b&这就是为什么要限制&/b&&/p&&p&&br&&/p&&p&我们限制某一个查询的返回不超过 100 行数据:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&c1&&# bad example&/span&
&span class=&n&&data&/span& &span class=&o&&=&/span& &span class=&nb&&list&/span&&span class=&p&&(&/span&&span class=&n&&Sale&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&all&/span&&span class=&p&&())[:&/span&&span class=&mi&&100&/span&&span class=&p&&]&/span&
&/code&&/pre&&/div&&p&这很糟糕,因为虽然只返回 100 行数据,但是其实你已经把所有的行都取出来放进了内存。&/p&&p&我们再试试:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&n&&data&/span& &span class=&o&&=&/span& &span class=&n&&Sale&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&all&/span&&span class=&p&&()[:&/span&&span class=&mi&&100&/span&&span class=&p&&]&/span&
&/code&&/pre&&/div&&p&这个好多了,Django 会在 SQL 中使用 limit 子句来获取 100 行数据。&/p&&p&我们增加了限制,但我们仍然有一个问题 -- 用户想要所有的数据,但我们只给了他们 100 个,用户现在认为只有 100 个数据了。&/p&&p&并非盲目的返回前 100 行,我们先确认一下,如果超过 100 行(通常是过滤以后),我们会抛出一个异常:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&n&&LIMIT&/span& &span class=&o&&=&/span& &span class=&mi&&100&/span&
&span class=&k&&if&/span& &span class=&n&&Sales&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&count&/span&&span class=&p&&()&/span& &span class=&o&&&&/span& &span class=&n&&LIMIT&/span&&span class=&p&&:&/span&
&span class=&k&&raise&/span& &span class=&n&&ExceededLimit&/span&&span class=&p&&(&/span&&span class=&n&&LIMIT&/span&&span class=&p&&)&/span&
&span class=&k&&return&/span& &span class=&n&&Sale&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&all&/span&&span class=&p&&()[:&/span&&span class=&n&&LIMIT&/span&&span class=&p&&]&/span&
&/code&&/pre&&/div&&p&挺有用,但是我们增加了一个新的查询&/p&&p&能不能做的更好呢?我们可以这样:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&n&&LIMIT&/span& &span class=&o&&=&/span& &span class=&mi&&100&/span&
&span class=&n&&data&/span& &span class=&o&&=&/span& &span class=&n&&Sale&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&&span class=&o&&.&/span&&span class=&n&&all&/span&&span class=&p&&()[:(&/span&&span class=&n&&LIMIT&/span& &span class=&o&&+&/span& &span class=&mi&&1&/span&&span class=&p&&)]&/span&
&span class=&k&&if&/span& &span class=&nb&&len&/span&&span class=&p&&(&/span&&span class=&n&&data&/span&&span class=&p&&)&/span& &span class=&o&&&&/span& &span class=&n&&LIMIT&/span&&span class=&p&&:&/span&
&span class=&k&&raise&/span& &span class=&n&&ExceededLimit&/span&&span class=&p&&(&/span&&span class=&n&&LIMIT&/span&&span class=&p&&)&/span&
&span class=&k&&return&/span& &span class=&n&&data&/span&
&/code&&/pre&&/div&&p&我们不取 100 行,我们取 100 + 1 = 101 行,如果 101 行存在,那么我们知道超过了 100 行:&/p&&p&&b&记住 LIMIT + 1 窍门,有时候它会非常方便&/b&&/p&&hr&&h2&6. 事务与锁的控制&/h2&&p&这个比较难。&/p&&p&由于数据库中的锁机制,我们开始在半夜发现事务超时错误。&/p&&p&(看来这个作者之前经常被半夜叫醒
)&/p&&p&在我们的代码中操作事务的常见模式如下所示:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&django.db&/span& &span class=&kn&&import&/span& &span class=&n&&transaction&/span& &span class=&k&&as&/span& &span class=&n&&db_transaction&/span&
&span class=&o&&...&/span&
&span class=&k&&with&/span& &span class=&n&&db_transaction&/span&&span class=&o&&.&/span&&span class=&n&&atomic&/span&&span class=&p&&():&/span&
&span class=&n&&transaction&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&
&span class=&n&&Transaction&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&
&span class=&o&&.&/span&&span class=&n&&select_related&/span&&span class=&p&&(&/span&
&span class=&s1&&'user'&/span&&span class=&p&&,&/span&
&span class=&s1&&'product'&/span&&span class=&p&&,&/span&
&span class=&s1&&'product__category'&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&span class=&o&&.&/span&&span class=&n&&select_for_update&/span&&span class=&p&&()&/span&
&span class=&o&&.&/span&&span class=&n&&get&/span&&span class=&p&&(&/span&&span class=&n&&uid&/span&&span class=&o&&=&/span&&span class=&n&&uid&/span&&span class=&p&&)&/span&
&span class=&p&&)&/span&
&span class=&o&&...&/span&
&/code&&/pre&&/div&&p&事务操作通常会涉及用户和产品的一些属性,所以我们经常使用 &code&select_related&/code& 来强制 join 并保存一些查询。&/p&&p&更新交易还会涉及获得一个锁来确保它不被别人获得。&/p&&p&现在,你看到问题了吗?没有?我也没有。(作者好萌)&/p&&p&我们有一些晚上运行的 ETL 进程,主要是在产品和用户表上做维护。这些 ETL 操作会更新字段然后插入表,这样它们也会获得了表的锁。&/p&&p&那么问题是什么?当 &code&select_for_update&/code& 与 &code&select_related&/code& 一起使用时,Django 将尝试获取查询中所有表的锁。&/p&&p&我们用来获取事务的代码尝试获取事务表、用户、产品、类别表的锁。一旦 ETL 在午夜锁定了后三个表,交易就开始失败。&/p&&p&一旦我们对问题有了更好的理解,我们就开始寻找只锁定必要表(事务表)的方法。(又)幸运的是,&code&select_for_update&/code& 的一个新选项在 Django 2.0 中可用:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&django.db&/span& &span class=&kn&&import&/span& &span class=&n&&transaction&/span& &span class=&k&&as&/span& &span class=&n&&db_transaction&/span&
&span class=&o&&...&/span&
&span class=&k&&with&/span& &span class=&n&&db_transaction&/span&&span class=&o&&.&/span&&span class=&n&&atomic&/span&&span class=&p&&():&/span&
&span class=&n&&transaction&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&
&span class=&n&&Transaction&/span&&span class=&o&&.&/span&&span class=&n&&objects&/span&
&span class=&o&&.&/span&&span class=&n&&select_related&/span&&span class=&p&&(&/span&
&span class=&s1&&'user'&/span&&span class=&p&&,&/span&
&span class=&s1&&'product'&/span&&span class=&p&&,&/span&
&span class=&s1&&'product__category'&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&span class=&o&&.&/span&&span class=&n&&select_for_update&/span&&span class=&p&&(&/span&
&span class=&n&&of&/span&&span class=&o&&=&/span&&span class=&p&&(&/span&&span class=&s1&&'self'&/span&&span class=&p&&,)&/span&
&span class=&p&&)&/span&
&span class=&o&&.&/span&&span class=&n&&get&/span&&span class=&p&&(&/span&&span class=&n&&uid&/span&&span class=&o&&=&/span&&span class=&n&&uid&/span&&span class=&p&&)&/span&
&span class=&p&&)&/span&
&span class=&o&&...&/span&
&/code&&/pre&&/div&&p&这个 &code&of&/code& 选项被添加到 &code&select_for_update&/code& ,使用 &code&of&/code& 可以指明我们要锁定的表,&code&self&/code& 是一个特殊的关键字,表示我们要锁定我们正在处理的模型,即事务表。&/p&&p&目前,该功能仅适用于 PostgreSQL 和 Oracle。&/p&&hr&&h2&7. 外键索引(FK Indexes)&/h2&&p&创建模型时,Django 会在所有外键上创建一个 B-Tree 索引,它的开销可能相当大,而且有时候并不很必要。&/p&&p&典型的例子是 M2M(多对多)关系的直通模型:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&k&&class&/span& &span class=&nc&&Membership&/span&&span class=&p&&(&/span&&span class=&n&&Model&/span&&span class=&p&&):&/span&
&span class=&n&&group&/span& &span class=&o&&=&/span& &span class=&n&&ForeignKey&/span&&span class=&p&&(&/span&&span class=&n&&Group&/span&&span class=&p&&)&/span&
&span class=&n&&user&/span& &span class=&o&&=&/span& &span class=&n&&ForeignKey&/span&&span class=&p&&(&/span&&span class=&n&&User&/span&&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&在上面的模型中,Django 将会隐式的创建两个索引:一个用于用户,一个用于组。&/p&&p&M2M 模型中的另一个常见模式是在两个字段一起作为一个唯一约束。在这种情况下,意味着一个用户只能是同一个组的成员,还是那个模型:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&k&&class&/span& &span class=&nc&&Membership&/span&&span class=&p&&(&/span&&span class=&n&&Model&/span&&span class=&p&&):&/span&
&span class=&n&&group&/span& &span class=&o&&=&/span& &span class=&n&&ForeignKey&/span&&span class=&p&&(&/span&&span class=&n&&Group&/span&&span class=&p&&)&/span&
&span class=&n&&user&/span& &span class=&o&&=&/span& &span class=&n&&ForeignKey&/span&&span class=&p&&(&/span&&span class=&n&&User&/span&&span class=&p&&)&/span&
&span class=&k&&class&/span& &span class=&nc&&Meta&/span&&span class=&p&&:&/span&
&span class=&n&&unique_together&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&
&span class=&s1&&'group'&/span&&span class=&p&&,&/span&
&span class=&s1&&'user'&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&这个 &code&unique_together&/code& 也会创建两个索引,所以我们得到了&b&两&/b&个字段&b&三&/b&个索引的模型
&/p&&p&根据我们用这个模型的职能,我们可以忽略 FK 索引,只保留唯一约束索引:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&k&&class&/span& &span class=&nc&&Membership&/span&&span class=&p&&(&/span&&span class=&n&&Model&/span&&span class=&p&&):&/span&
&span class=&n&&group&/span& &span class=&o&&=&/span& &span class=&n&&ForeignKey&/span&&span class=&p&&(&/span&&span class=&n&&Group&/span&&span class=&p&&,&/span& &span class=&n&&db_index&/span&&span class=&o&&=&/span&&span class=&bp&&False&/span&&span class=&p&&)&/span&
&span class=&n&&user&/span& &span class=&o&&=&/span& &span class=&n&&ForeignKey&/span&&span class=&p&&(&/span&&span class=&n&&User&/span&&span class=&p&&,&/span& &span class=&n&&db_index&/span&&span class=&o&&=&/span&&span class=&bp&&False&/span&&span class=&p&&)&/span&
&span class=&k&&class&/span& &span class=&nc&&Meta&/span&&span class=&p&&:&/span&
&span class=&n&&unique_together&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&
&span class=&s1&&'group'&/span&&span class=&p&&,&/span&
&span class=&s1&&'user'&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&删除冗余的索引将会是插入和查询更快,而且我们的数据库更轻量。&/p&&hr&&h2&8. 组合索引中列的顺序(Order of columns in composite index)&/h2&&p&具有多个列的索引称为组合索引。 在 B-Tree 组合索引中,第一列使用树结构进行索引。从第一层的树叶为第二层创建一棵新树,以此类推。&/p&&p&索引中列的顺序非常重要。&/p&&p&在上面的例子中,我们首先会得到一个组(group)的树,另一个树是所有它的用户(user)。&/p&&p&B-Tree 组合索引的经验法则是使二级索引尽可能小。换句话说,高基数(更明确的值)的列应该是在第一位的。&/p&&p&在我们的例子中,假设组少于用户(一般),所以把用户列放在第一位会使组的二级索引变小。&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&k&&class&/span& &span class=&nc&&Membership&/span&&span class=&p&&(&/span&&span class=&n&&Model&/span&&span class=&p&&):&/span&
&span class=&n&&group&/span& &span class=&o&&=&/span& &span class=&n&&ForeignKey&/span&&span class=&p&&(&/span&&span class=&n&&Group&/span&&span class=&p&&,&/span& &span class=&n&&db_index&/span&&span class=&o&&=&/span&&span class=&bp&&False&/span&&span class=&p&&)&/span&
&span class=&n&&user&/span& &span class=&o&&=&/span& &span class=&n&&ForeignKey&/span&&span class=&p&&(&/span&&span class=&n&&User&/span&&span class=&p&&,&/span& &span class=&n&&db_index&/span&&span class=&o&&=&/span&&span class=&bp&&False&/span&&span class=&p&&)&/span&
&span class=&k&&class&/span& &span class=&nc&&Meta&/span&&span class=&p&&:&/span&
&span class=&n&&unique_together&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&
&span class=&s1&&'user'&/span&&span class=&p&&,&/span&
&span class=&s1&&'group'&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&*注意元组里面的字段名顺序&/p&&p&这只是一个经验法则,最终的索引应该针对特定的场景进行优化。这里的要点是要知道隐式索引和组合索引中列顺序的重要性。(临书:惹不起惹不起)&/p&&hr&&h2&9. 块范围索引(BRIN indexes)&/h2&&p&B-Tree 索引的结构像一棵树。查找单个值的成本是随机访问表的树的高度 + 1。这使得 B-Tree 索引非常适合独特的约束和(一些)范围查询。&/p&&p&B-Tree索引的缺点是它的大小 -- B-Tree 索引可能会变大。&/p&&p&没有其他选择了吗?并不是,数据库为特定用例提供其他类型的索引也蛮多的。&/p&&p&从 Django 1.11 开始,有一个新的 Meta 选项用于在模型上创建索引。这给了我们探索其他类型索引的机会。&/p&&p&PostgreSQL 有一个非常有用的索引类型 BRIN(块范围索引)。在某些情况下,BRIN 索引可以比 B-Tree 索引更高效。&/p&&p&我们看看官网文档怎么说的:&/p&&p&BRIN 设计用于处理非常大的表格,其中某些列与表格内的物理位置有一些自然的相关性。&/p&&p&要理解这个陈述,了解 BRIN 索引如何工作是很重要的。顾名思义,BRIN 索引会在表格中的一系列相邻块上创建一个小型索引。该索引非常小,只能说明某个值是否在范围内,或者是否在索引块范围内。&/p&&p&我们来做一个 BRIN 索引如何帮助我们的简单例子。&/p&&p&假设我们在一列中有这些值,每一个都是一个块:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&1, 2, 3, 4, 5, 6, 7, 8, 9
&/code&&/pre&&/div&&p&我们为每三个相邻的块创建一个范围:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&[1,2,3], [4,5,6], [7,8,9]
&/code&&/pre&&/div&&p&对于每个范围,我们将保存范围内的最小值和最大值:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&[1–3], [4–6], [7–9]
&/code&&/pre&&/div&&p&我们尝试通过此索引搜索 5:&/p&&ul&&li&&code&[1–3]&/code& —
绝对没在这里&/li&&li&&code&[4–6] &/code&— 可能在这里&/li&&li&&code&[7–9]&/code& — 绝对没在这里&/li&&/ul&&p&使用索引,我们限制了我们搜索的范围在 [4-6] 范围。&/p&&p&再举一个例子,这次列中的值不会被很好地排序:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&[2–9], [1–7], [3–8]
&/code&&/pre&&/div&&p&再试着查找 5:&/p&&ul&&li&&code&[2–9]&/code& — 可能在这里&/li&&li&&code&[1–7] &/code&— 可能在这里&/li&&li&&code&[3–8] &/code&— 可能在这里&/li&&/ul&&p&索引是无用的 -- 它不仅没有限制搜索,实际上我们不得不搜索更多,因为我们同时提取了索引和整个表。&/p&&p&回到文档:&/p&&blockquote&...列与表格内的物理位置有一些自然的相关性&/blockquote&&p&这是 BRIN 索引的关键。为了充分利用它,列中的值必须大致排序或聚集在磁盘上。&/p&&p&现在回到 Django,我们有哪些常被索引的字段,最有可能在磁盘上自然排序?没错,就是 &code&auto_now_add&/code&。(这个很常用,没用到的小伙伴可以了解下) &/p&&p&Django 模型中一个非常常见的模式是:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&k&&class&/span& &span class=&nc&&SomeModel&/span&&span class=&p&&(&/span&&span class=&n&&Model&/span&&span class=&p&&):&/span&
&span class=&n&&created&/span& &span class=&o&&=&/span& &span class=&n&&DatetimeField&/span&&span class=&p&&(&/span&
&span class=&n&&auto_now_add&/span&&span class=&o&&=&/span&&span class=&bp&&True&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&当使用 &code&auto_now_add&/code& 时,Django 将自动使用当前时间填充该行的时间。创建的字段通常也是查询的绝佳候选字段,所以它通常被插入索引。&/p&&p&让我们在创建时添加一个 BRIN 索引:&/p&&div class=&highlight&&&pre&&code class=&language-python&&&span&&/span&&span class=&kn&&from&/span& &span class=&nn&&django.contrib.postgres.indexes&/span& &span class=&kn&&import&/span& &span class=&n&&BrinIndex&/span&
&span class=&k&&class&/span& &span class=&nc&&SomeModel&/span&&span class=&p&&(&/span&&span class=&n&&Model&/span&&span class=&p&&):&/span&
&span class=&n&&created&/span& &span class=&o&&=&/span& &span class=&n&&DatetimeField&/span&&span class=&p&&(&/span&
&span class=&n&&auto_now_add&/span&&span class=&o&&=&/span&&span class=&bp&&True&/span&&span class=&p&&,&/span&
&span class=&p&&)&/span&
&span class=&k&&class&/span& &span class=&nc&&Meta&/span&&span class=&p&&:&/span&
&span class=&n&&indexes&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&
&span class=&n&&BrinIndex&/span&&span class=&p&&(&/span&&span class=&n&&fields&/span&&span class=&o&&=&/span&&span class=&p&&[&/span&&span class=&s1&&'created'&/span&&span class=&p&&]),&/span&
&span class=&p&&)&/span&
&/code&&/pre&&/div&&p&为了了解大小的差异,我创建了一个约 2M 行的表,并在磁盘上自然排序了日期字段:&/p&&ul&&li&B-Tree 索引:37 &b&MB&/b&&/li&&li&BRIN 索引:49 &b&KB&/b&&/li&&/ul&&p&没错,你没看错。&/p&&p&创建索引时要考虑的要比索引的大小要多得多。但是现在,通过 Django 1.11 支持索引,我们可以轻松地将新类型的索引整合到我们的应用程序中,使它们更轻,更快。&/p&&p&--&/p&&p&&b&全文完,随意转载,转载请注明出处:&/b&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&Django 与数据库交互,你需要知道的 9 个点&/a&&/p&&p&&br&&/p&&p&觉得文章怎么样?我个人觉得是非常赞的!&/p&&p&如果大家觉得此类文章对你很有用,请务必点个关注,谢谢啦&/p&
此专栏我会不定期分享一些 Django 最前沿的文章,内容偏重技巧、经验的归纳总结,来源暂时有: 知名博主如果大家感兴趣,请一定点个关注,给我一些动力,毕竟翻译整理是需要时间的,谢谢大家--原文地址:
&figure&&img src=&https://pic1.zhimg.com/v2-31f9e290f82207cddd5b2_b.jpg& data-rawwidth=&1200& data-rawheight=&499& class=&origin_image zh-lightbox-thumb& width=&1200& data-original=&https://pic1.zhimg.com/v2-31f9e290f82207cddd5b2_r.jpg&&&/figure&&p&&strong&1.拿到一个待检测的站,你觉得应该先做什么?&/strong&&/p&&ul&&li&&p&收集信息&br&whois、网站源IP、旁站、C段网站、服务器系统版本、容器版本、程序版本、数据库类型、二级域名、防火墙、维护者信息另说...&/p&&/li&&/ul&&p&&strong&2.mysql的网站注入,5.0以上和5.0以下有什么区别?&/strong&&/p&&ul&&li&&p&5.0以下没有information_schema这个系统表,无法列表名等,只能暴力跑表名。&/p&&/li&&li&&p&5.0以下是多用户单操作,5.0以上是多用户多操做。&/p&&/li&&/ul&&p&&strong&3.在渗透过程中,收集目标站注册人邮箱对我们有什么价值?&/strong&&/p&&ul&&li&&p&丢社工库里看看有没有泄露密码,然后尝试用泄露的密码进行登录后台。&/p&&/li&&li&&p&用邮箱做关键词进行丢进搜索引擎。&/p&&/li&&li&&p&利用搜索到的关联信息找出其他邮进而得到常用社交账号。&/p&&/li&&li&&p&社工找出社交账号,里面或许会找出管理员设置密码的习惯 。&/p&&/li&&li&&p&利用已有信息生成专用字典。&/p&&/li&&li&&p&观察管理员常逛哪些非大众性网站,拿下它,你会得到更多好东西。&/p&&/li&&/ul&&p&&strong&4.判断出网站的CMS对渗透有什么意义?&/strong&&/p&&ul&&li&&p&查找网上已曝光的程序漏洞。&/p&&/li&&li&&p&如果开源,还能下载相对应的源码进行代码审计。&/p&&/li&&/ul&&p&&strong&5.一个成熟并且相对安全的CMS,渗透时扫目录的意义?&/strong&&/p&&ul&&li&&p&敏感文件、二级目录扫描&/p&&/li&&li&&p&站长的误操作比如:网站备份的压缩文件、说明.txt、二级目录可能存放着其他站点&/p&&/li&&/ul&&p&&strong&6.常见的网站服务器容器。&/strong&&/p&&ul&&li&&p&IIS、Apache、nginx、Lighttpd、Tomcat&/p&&/li&&/ul&&p&&strong&7.mysql注入点,用工具对目标站直接写入一句话,需要哪些条件?&/strong&&/p&&ul&&li&&p&root权限以及网站的绝对路径。&/p&&/li&&/ul&&p&&strong&8.目前已知哪些版本的容器有解析漏洞,具体举例。&/strong&&/p&&ul&&li&&p&&strong&IIS 6.0&/strong&&br&/xx.asp/xx.jpg &xx.asp&是文件夹名&/p&&/li&&li&&p&&strong&IIS 7.0/7.5&/strong&&br&默认Fast-CGI开启,直接在url中图片地址后面输入/1.php,会把正常图片当成php解析&/p&&/li&&li&&p&&strong&Nginx&/strong&&br&版本小于等于0.8.37,利用方法和IIS 7.0/7.5一样,Fast-CGI关闭情况下也可利用。&br&空字节代码 xxx.jpg%00.php&/p&&/li&&li&&p&&strong&Apache&/strong&&br&上传的文件命名为:test.php.x1.x2.x3,Apache是从右往左判断后缀&/p&&/li&&li&&p&&strong&lighttpd&/strong&&br&xx.jpg/xx.php,不全,请小伙伴们在评论处不吝补充,谢谢!&/p&&/li&&/ul&&p&&strong&9.如何手工快速判断目标站是windows还是linux服务器?&/strong&&/p&&ul&&li&&p&linux大小写敏感,windows大小写不敏感。&/p&&/li&&/ul&&p&&strong&10.为何一个mysql数据库的站,只有一个80端口开放?&/strong&&/p&&ul&&li&&p&更改了端口,没有扫描出来。&/p&&/li&&li&&p&站库分离。&/p&&/li&&li&&p&3306端口不对外开放&/p&&/li&&/ul&&p&&strong&11.3389无法连接的几种情况。&/strong&&/p&&ul&&li&&p&没开放3389 端口&/p&&/li&&li&&p&端口被修改&/p&&/li&&li&&p&防护拦截&/p&&/li&&li&&p&处于内网(需进行端口转发)&/p&&/li&&/ul&&p&&strong&12.如何突破注入时字符被转义?&/strong&&/p&&ul&&li&&p&宽字符注入&/p&&/li&&li&&p&hex编码绕过&/p&&/li&&/ul&&p&&strong&13.在某后台新闻编辑界面看到编辑器,应该先做什么?&/strong&&/p&&ul&&li&&p&查看编辑器的名称版本,然后搜索公开的漏洞。&/p&&/li&&/ul&&p&&strong&14.拿到一个webshell发现网站根目录下有.htaccess文件,我们能做什么?&/strong&&/p&&ul&&li&&p&能做的事情很多,用隐藏网马来举例子:&br&插入&br&&FilesMatch &xxx.jpg&& SetHandler application/x-httpd-php &/FilesMatch&&br&.jpg文件会被解析成.php文件。&/p&&/li&&li&&p&具体其他的事情,不好详说,建议大家自己去搜索语句来玩玩。&/p&&/li&&/ul&&p&&strong&15.注入漏洞只能查账号密码?&/strong&&/p&&ul&&li&&p&只要权限广,拖库脱到老。&/p&&/li&&/ul&&p&&strong&16.安全狗会追踪变量,从而发现出是一句话木马吗?&/strong&&/p&&ul&&li&&p&是根据特征码,所以很好绕过了,只要思路宽,绕狗绕到欢,但这应该不会是一成不变的。&/p&&/li&&/ul&&p&&strong&17.access 扫出后缀为asp的数据库文件,访问乱码。如何实现到本地利用。&/strong&&/p&&ul&&li&&p&迅雷下载,直接改后缀为.mdb。&/p&&/li&&/ul&&p&&strong&18.提权时选择可读写目录,为何尽量不用带空格的目录?&/strong&&/p&&ul&&li&&p&因为exp执行多半需要空格界定参数&/p&&/li&&/ul&&p&&strong&19.某服务器有站点A,B 为何在A的后台添加test用户,访问B的后台。发现也添加上了test用户?&/strong&&/p&&ul&&li&&p&同数据库。&/p&&/li&&/ul&&p&&strong&20.注入时可以不使用and 或or 或xor,直接order by 开始注入吗?&/strong&&/p&&ul&&li&&p&and/or/xor,前面的1=1、1=2步骤只是为了判断是否为注入点,如果已经确定是注入点那就可以省那步骤去。&/p&&/li&&/ul&&p&&strong&21:某个防注入系统,在注入时会提示:&/strong&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span& 系统检测到你有非法注入的行为。
已记录您的ip xx.xx.xx.xx
提交页面:test.asp?id=15
提交内容:and 1=1
&/code&&/pre&&/div&&p&&strong&如何利用这个防注入系统拿shell?&/strong&&/p&&ul&&li&&p&在URL里面直接提交一句话,这样网站就把你的一句话也记录进数据库文件了 这个时候可以尝试寻找网站的配置文件 直接上菜刀链接。具体文章参见:&a href=&https://link.zhihu.com/?target=http%3A//ytxiao.lofter.com/post/40583a_ab36540& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&一句话木马在防注入中的重生-= 奇闻录-笑 =&/a&。&/p&&/li&&/ul&&p&&strong&22.上传大马后访问乱码时,有哪些解决办法?&/strong&&/p&&ul&&li&&p&浏览器中改编码。&/p&&/li&&/ul&&p&&strong&23.审查上传点的元素有什么意义?&/strong&&/p&&ul&&li&&p&有些站点的上传文件类型的限制是在前端实现的,这时只要增加上传类型就能突破限制了。&/p&&/li&&/ul&&p&&strong&24.目标站禁止注册用户,找回密码处随便输入用户名提示:“此用户不存在”,你觉得这里怎样利用?&/strong&&/p&&ul&&li&&p&先爆破用户名,再利用被爆破出来的用户名爆破密码。&/p&&/li&&li&&p&其实有些站点,在登陆处也会这样提示&/p&&/li&&li&&p&所有和数据库有交互的地方都有可能有注入。&/p&&/li&&/ul&&p&&strong&25.目标站发现某txt的下载地址为&a href=&https://link.zhihu.com/?target=http%3A//www.test.com/down/down.php%3Ffile%3D/upwdown/1.txt& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Client Validation&/a&,你有什么思路?&/strong&&/p&&ul&&li&&p&这就是传说中的下载漏洞!在file=后面尝试输入index.php下载他的首页文件,然后在首页文件里继续查找其他网站的配置文件,可以找出网站的数据库密码和数据库的地址。&/p&&/li&&/ul&&p&&strong&26.甲给你一个目标站,并且告诉你根目录下存在/abc/目录,并且此目录下存在编辑器和admin目录。请问你的想法是?&/strong&&/p&&ul&&li&&p&直接在网站二级目录/abc/下扫描敏感文件及目录。&/p&&/li&&/ul&&p&&strong&27.在有shell的情况下,如何使用xss实现对目标站的长久控制?&/strong&&/p&&ul&&li&&p&后台登录处加一段记录登录账号密码的js,并且判断是否登录成功,如果登录成功,就把账号密码记录到一个生僻的路径的文件中或者直接发到自己的网站文件中。(此方法适合有价值并且需要深入控制权限的网络)。&/p&&/li&&li&&p&在登录后才可以访问的文件中插入XSS脚本。&/p&&/li&&/ul&&p&&strong&28.后台修改管理员密码处,原密码显示为*。你觉得该怎样实现读出这个用户的密码?&/strong&&/p&&ul&&li&&p&审查元素 把密码处的password属性改成text就明文显示了&/p&&/li&&/ul&&p&&strong&29.目标站无防护,上传图片可以正常访问,上传脚本格式访问则403.什么原因?&/strong&&/p&&ul&&li&&p&原因很多,有可能web服务器配置把上传目录写死了不执行相应脚本,尝试改后缀名绕过&/p&&/li&&/ul&&p&&strong&30.审查元素得知网站所使用的防护软件,你觉得怎样做到的?&/strong&&/p&&ul&&li&&p&在敏感操作被拦截,通过界面信息无法具体判断是什么防护的时候,F12看HTML体部 比如护卫神就可以在名称那看到&hws&内容&hws&。&/p&&/li&&/ul&&p&&strong&31.在win2003服务器中建立一个 .zhongzi文件夹用意何为?&/strong&&/p&&ul&&li&&p&隐藏文件夹,为了不让管理员发现你传上去的工具。&/p&&/li&&/ul&&br&&p&&strong&32、sql注入有以下两个&/strong&&strong&测试&/strong&&strong&选项,选一个并且阐述不选另一个的理由:&/strong&&/p&&p&&br&A. demo.jsp?id=2+1
B. demo.jsp?id=2-1 &br&选B,在 URL 编码中 + 代表空格,可能会造成混淆&/p&&br&&p&&strong&33、以下链接存在 sql 注入漏洞,对于这个变形注入,你有什么思路? &/strong&&/p&&p&&br&demo.do?DATA=AjAxNg== &br&DATA有可能经过了 base64 编码再传入服务器,所以我们也要对参数进行 base64 编码才能正确完成测试&/p&&br&&p&&strong&34、发现 demo.jsp?uid=110 注入点,你有哪几种思路获取 webshell,哪种是优选? &/strong&&/p&&p&&br&有写入权限的,构造联合查询语句使用using INTO OUTFILE,可以将查询的输出重定向到系统的文件中,这样去写入 WebShell &br&使用 sqlmap –os-shell 原理和上面一种相同,来直接获得一个 Shell,这样效率更高 &br&通过构造联合查询语句得到网站管理员的账户和密码,然后扫后台登录后台,再在后台通过改包上传等方法上传 Shell&/p&&br&&p&&strong&35、CSRF 和 XSS 和 XXE 有什么区别,以及修复方式? &/strong&&/p&&p&&br&XSS是跨站脚本攻击,用户提交的数据中可以构造代码来执行,从而实现窃取用户信息等攻击。修复方式:对字符实体进行转义、使用HTTP Only来禁止JavaScript读取Cookie值、输入时校验、浏览器与Web应用端采用相同的字符编码。 &/p&&p&&br&CSRF是跨站请求伪造攻击,XSS是实现CSRF的诸多手段中的一种,是由于没有在关键操作执行时进行是否由用户自愿发起的确认。修复方式:筛选出需要防范CSRF的页面然后嵌入Token、再次输入密码、检验Referer &br&XXE是XML外部实体注入攻击,XML中可以通过调用实体来请求本地或者远程内容,和远程文件保护类似,会引发相关安全问题,例如敏感文件读取。修复方式:XML解析库在调用时严格禁止对外部实体的解析。&/p&&br&&p&&strong&36、CSRF、SSRF和重放攻击有什么区别?&/strong&&/p&&p&&br&CSRF是跨站请求伪造攻击,由客户端发起 &br&SSRF是服务器端请求伪造,由服务器发起 &br&重放攻击是将截获的数据包进行重放,达到身份认证等目的&/p&&br&&p&&strong&37、说出至少三种业务逻辑漏洞,以及修复方式?&/strong&&/p&&p&&br&密码找回漏洞中存在密码允许暴力破解、存在通用型找回凭证、可以跳过验证步骤、找回凭证可以拦包获取等方式来通过厂商提供的密码找回功能来得到密码 &br&身份认证漏洞中最常见的是会话固定攻击和 Cookie 仿冒,只要得到 Session 或 Cookie 即可伪造用户身份 &br&验证码漏洞中存在验证码允许暴力破解、验证码可以通过 Javascript 或者改包的方法来进行绕过&/p&&br&&p&&strong&38、圈出下面会话中可能存在问题的项,并标注可能会存在的问题?&/strong&&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&get /ecskins/demo.jsp?uid=&keyword=”hello world”
HTTP/1.1Host:*******.com:82User-Agent:Mozilla/
5.0 Firefox/40Accept:text/css,*/*;q=0.1
Accept-Language:zh-CN;q=0.8;en-US;q=0.5,q=0.3
Referer:http://*******.com/eciop/orderForCC/
cgtListForCC.htm?zone=&v=145902
Cookie:myguid=c372c3dc273d;
uniqueserid=session_OGRMIFIYJHAH5_HZRQOZAMHJ;
st_uid=N90PLYHLZGJXI-NX01VPUF46W;
status=True
Connection:keep-alive
&/code&&/pre&&/div&&ul&&li&&p&11&/p&&/li&&/ul&&p&&strong&
39、找一类你最擅长的漏洞,谈下绕过漏洞修复后的方案?&/strong&&/p&&p&&strong&40、你常用的渗透工具有哪些,最常用的是哪个?&/strong&&/p&&p&&strong&41、描述一个你深入研究过的 CVE 或 POC。&/strong&&/p&&p&&strong&42、谈谈你经常关注的安全平台?&/strong&&/p&
1.拿到一个待检测的站,你觉得应该先做什么?收集信息 whois、网站源IP、旁站、C段网站、服务器系统版本、容器版本、程序版本、数据库类型、二级域名、防火墙、维护者信息另说...2.mysql的网站注入,5.0以上和5.0以下有什么区别?5.0以下没有information_sc…
&figure&&img src=&https://pic2.zhimg.com/v2-ef57eb26f8decc9e602f379bbe149099_b.jpg& data-rawwidth=&750& data-rawheight=&340& class=&origin_image zh-lightbox-thumb& width=&750& data-original=&https://pic2.zhimg.com/v2-ef57eb26f8decc9e602f379bbe149099_r.jpg&&&/figure&&p&&a href=&https://link.zhihu.com/?target=https%3A//github.com/chenjiandongx/pyecharts& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&pyecharts&/a& 是一个用于生成 &a href=&https://link.zhihu.com/?target=https%3A//github.com/ecomfe/echarts& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Echarts&/a& 图表的类库。实际上就是 Echarts 和 Python 的对接。 Echarts 是百度开源的一个数据可视化 JS 库。主要用于数据可视化。&/p&&h2&安装&/h2&&p&pyecharts 兼容 Python2 和 Python3。目前版本为 0.1.6&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&pip install pyecharts
&/code&&/pre&&/div&&h2&入门&/h2&&p&首先开始来绘制你的第一个图表&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Bar
bar = Bar(&我的第一个图表&, &这里是副标题&)
bar.add(&服装&, [&衬衫&, &羊毛衫&, &雪纺衫&, &裤子&, &高跟鞋&, &袜子&], [5, 20, 36, 10, 75, 90])
bar.show_config()
bar.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-2a0993eabea281b1ed54_b.jpg& data-rawwidth=&824& data-rawheight=&390& class=&origin_image zh-lightbox-thumb& width=&824& data-original=&https://pic1.zhimg.com/v2-2a0993eabea281b1ed54_r.jpg&&&/figure&&p&&br&&/p&&p&&b&Tip:&/b& 可以按右边的下载按钮将图片下载到本地&/p&&ul&&li&add()&br&主要方法,用于添加图表的数据和设置各种配置项&/li&&li&show_config()&br&打印输出图表的所有配置项&/li&&li&render()&br&默认将会在根目录下生成一个 render.html 的文件,支持 path 参数,设置文件保存位置,如 render(r&e:\my_first_chart.html&),文件用浏览器打开。&br&默认的编码类型为 UTF-8,在 Python3 中是没什么问题的,Python3 对中文的支持好很多。但是在 Python2 中,编码的处理是个很头疼的问题,暂时没能找到完美的解决方法,目前只能通过文本编辑器自己进行二次编码,我用的是 Visual Studio Code,先通过 Gbk 编码重新打开,然后再用 UTF-8 重新保存,这样用浏览器打开的话就不会出现中文乱码问题了。&/li&&/ul&&p&基本上所有的图表类型都是这样绘制的:&/p&&ol&&li&chart_name = Type() 初始化具体类型图表。&/li&&li&add() 添加数据及配置项。&/li&&li&render() 生成 .html 文件&/li&&/ol&&p&&br&&/p&&h2&图表类型&/h2&&p&由于篇幅原因,这里只给出了每种图表类型的示例(代码 + 生成图表),目的是为了引起读者的兴趣。详细参数的介绍请参考项目 &a href=&https://link.zhihu.com/?target=https%3A//github.com/chenjiandongx/pyecharts/blob/master/README.md& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&README.md&/a& 文档&/p&&h2&Bar(柱状图/条形图)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Bar
attr = [&衬衫&, &羊毛衫&, &雪纺衫&, &裤子&, &高跟鞋&, &袜子&]
v1 = [5, 20, 36, 10, 75, 90]
v2 = [10, 25, 8, 60, 20, 80]
bar = Bar(&柱状图数据堆叠示例&)
bar.add(&商家A&, attr, v1, is_stack=True)
bar.add(&商家B&, attr, v2, is_stack=True)
bar.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-84cdc6d13632_b.jpg& data-rawwidth=&844& data-rawheight=&408& data-thumbnail=&https://pic1.zhimg.com/v2-84cdc6d13632_b.jpg& class=&origin_image zh-lightbox-thumb& width=&844& data-original=&https://pic1.zhimg.com/v2-84cdc6d13632_r.jpg&&&/figure&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Bar
bar = Bar(&标记线和标记点示例&)
bar.add(&商家A&, attr, v1, mark_point=[&average&])
bar.add(&商家B&, attr, v2, mark_line=[&min&, &max&])
bar.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-fad5ba1c77_b.jpg& data-rawwidth=&818& data-rawheight=&410& data-thumbnail=&https://pic3.zhimg.com/v2-fad5ba1c77_b.jpg& class=&origin_image zh-lightbox-thumb& width=&818& data-original=&https://pic3.zhimg.com/v2-fad5ba1c77_r.jpg&&&/figure&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Bar
bar = Bar(&x 轴和 y 轴交换&)
bar.add(&商家A&, attr, v1)
bar.add(&商家B&, attr, v2, is_convert=True)
bar.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-caf2cf2363_b.jpg& data-rawwidth=&836& data-rawheight=&391& class=&origin_image zh-lightbox-thumb& width=&836& data-original=&https://pic2.zhimg.com/v2-caf2cf2363_r.jpg&&&/figure&&p&&br&&/p&&h2&EffectScatter(带有涟漪特效动画的散点图)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import EffectScatter
v1 = [10, 20, 30, 40, 50, 60]
v2 = [25, 20, 15, 10, 60, 33]
es = EffectScatter(&动态散点图示例&)
es.add(&effectScatter&, v1, v2)
es.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-6dbffcad2ba59e81ffa5d8_b.jpg& data-rawwidth=&830& data-rawheight=&408& data-thumbnail=&https://pic2.zhimg.com/v2-6dbffcad2ba59e81ffa5d8_b.jpg& class=&origin_image zh-lightbox-thumb& width=&830& data-original=&https://pic2.zhimg.com/v2-6dbffcad2ba59e81ffa5d8_r.jpg&&&/figure&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&es = EffectScatter(&动态散点图各种图形示例&)
es.add(&&, [10], [10], symbol_size=20, effect_scale=3.5, effect_period=3, symbol=&pin&)
es.add(&&, [20], [20], symbol_size=12, effect_scale=4.5, effect_period=4,symbol=&rect&)
es.add(&&, [30], [30], symbol_size=30, effect_scale=5.5, effect_period=5,symbol=&roundRect&)
es.add(&&, [40], [40], symbol_size=10, effect_scale=6.5, effect_brushtype='fill',symbol=&diamond&)
es.add(&&, [50], [50], symbol_size=16, effect_scale=5.5, effect_period=3,symbol=&arrow&)
es.add(&&, [60], [60], symbol_size=6, effect_scale=2.5, effect_period=3,symbol=&triangle&)
es.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-5fa770abecb5b71aebbe_b.jpg& data-rawwidth=&828& data-rawheight=&406& data-thumbnail=&https://pic2.zhimg.com/v2-5fa770abecb5b71aebbe_b.jpg& class=&origin_image zh-lightbox-thumb& width=&828& data-original=&https://pic2.zhimg.com/v2-5fa770abecb5b71aebbe_r.jpg&&&/figure&&h2&Funnel(漏斗图)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Funnel
attr = [&衬衫&, &羊毛衫&, &雪纺衫&, &裤子&, &高跟鞋&, &袜子&]
value = [20, 40, 60, 80, 100, 120]
funnel = Funnel(&漏斗图示例&)
funnel.add(&商品&, attr, value, is_label_show=True, label_pos=&inside&, label_text_color=&#fff&)
funnel.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-f1c17050cbe4e2cdf350c_b.jpg& data-rawwidth=&816& data-rawheight=&376& data-thumbnail=&https://pic2.zhimg.com/v2-f1c17050cbe4e2cdf350c_b.jpg& class=&origin_image zh-lightbox-thumb& width=&816& data-original=&https://pic2.zhimg.com/v2-f1c17050cbe4e2cdf350c_r.jpg&&&/figure&&p&&br&&/p&&h2&Gauge(仪表盘)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Gauge
gauge = Gauge(&仪表盘示例&)
gauge.add(&业务指标&, &完成率&, 66.66)
gauge.show_config()
gauge.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-d549a80507cc05ecb1fc38_b.jpg& data-rawwidth=&819& data-rawheight=&390& class=&origin_image zh-lightbox-thumb& width=&819& data-original=&https://pic2.zhimg.com/v2-d549a80507cc05ecb1fc38_r.jpg&&&/figure&&p&&br&&/p&&h2&Geo(地理坐标系)&/h2&&p&Scatter 类型&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Geo
(&海门&, 9),(&鄂尔多斯&, 12),(&招远&, 12),(&舟山&, 12),(&齐齐哈尔&, 14),(&盐城&, 15),
(&赤峰&, 16),(&青岛&, 18),(&乳山&, 18),(&金昌&, 19),(&泉州&, 21),(&莱西&, 21),
(&日照&, 21),(&胶南&, 22),(&南通&, 23),(&拉萨&, 24),(&云浮&, 24),(&梅州&, 25)...]
geo = Geo(&全国主要城市空气质量&, &data from pm2.5&, title_color=&#fff&, title_pos=&center&,
width=1200, height=600, background_color='#404a59')
attr, value = geo.cast(data)
geo.add(&&, attr, value, visual_range=[0, 200], visual_text_color=&#fff&, symbol_size=15, is_visualmap=True)
geo.show_config()
geo.render()
&/code&&/pre&&/div&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ba0357a8bdd_b.jpg& data-rawwidth=&1124& data-rawheight=&596& data-thumbnail=&https://pic3.zhimg.com/v2-ba0357a8bdd_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1124& data-original=&https://pic3.zhimg.com/v2-ba0357a8bdd_r.jpg&&&/figure&&p&&br&&/p&&p&HeatMap 类型&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&geo = Geo(&全国主要城市空气质量&, &data from pm2.5&, title_color=&#fff&, title_pos=&center&, width=1200, height=600,
background_color='#404a59')
attr, value = geo.cast(data)
geo.add(&&, attr, value, type=&heatmap&, is_visualmap=True, visual_range=[0, 300], visual_text_color='#fff')
geo.show_config()
geo.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-eea3bc9fe1_b.jpg& data-rawwidth=&1496& data-rawheight=&744& data-thumbnail=&https://pic2.zhimg.com/v2-eea3bc9fe1_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1496& data-original=&https://pic2.zhimg.com/v2-eea3bc9fe1_r.jpg&&&/figure&&p&&br&&/p&&p&EffectScatter 类型&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Geo
data = [(&海门&, 9), (&鄂尔多斯&, 12), (&招远&, 12), (&舟山&, 12), (&齐齐哈尔&, 14), (&盐城&, 15)]
geo = Geo(&全国主要城市空气质量&, &data from pm2.5&, title_color=&#fff&, title_pos=&center&,
width=1200, height=600, background_color='#404a59')
attr, value = geo.cast(data)
geo.add(&&, attr, value, type=&effectScatter&, is_random=True, effect_scale=5)
geo.show_config()
geo.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-df12e2bd517ced995c4a1ef_b.jpg& data-rawwidth=&808& data-rawheight=&566& data-thumbnail=&https://pic3.zhimg.com/v2-df12e2bd517ced995c4a1ef_b.jpg& class=&origin_image zh-lightbox-thumb& width=&808& data-original=&https://pic3.zhimg.com/v2-df12e2bd517ced995c4a1ef_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&h2&Graph(关系图)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Graph
nodes = [{&name&: &结点1&, &symbolSize&: 10},
{&name&: &结点2&, &symbolSize&: 20},
{&name&: &结点3&, &symbolSize&: 30},
{&name&: &结点4&, &symbolSize&: 40},
{&name&: &结点5&, &symbolSize&: 50},
{&name&: &结点6&, &symbolSize&: 40},
{&name&: &结点7&, &symbolSize&: 30},
{&name&: &结点8&, &symbolSize&: 20}]
links = []
for i in nodes:
for j in nodes:
links.append({&source&: i.get('name'), &target&: j.get('name')})
graph = Graph(&关系图-环形布局示例&)
graph.add(&&, nodes, links, is_label_show=True, repulsion=8000, layout='circular', label_text_color=None)
graph.show_config()
graph.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-70d3cc34c8174a53dda0_b.jpg& data-rawwidth=&828& data-rawheight=&418& class=&origin_image zh-lightbox-thumb& width=&828& data-original=&https://pic4.zhimg.com/v2-70d3cc34c8174a53dda0_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Graph
import json
with open(&..\json\weibo.json&, &r&, encoding=&utf-8&) as f:
j = json.load(f)
nodes, links, categories, cont, mid, userl = j
graph = Graph(&微博转发关系图&, width=1200, height=600)
graph.add(&&, nodes, links, categories, label_pos=&right&, repulsion=50, is_legend_show=False,
line_curve=0.2, label_text_color=None)
graph.show_config()
graph.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ca9d9ce4d27d_b.jpg& data-rawwidth=&1221& data-rawheight=&594& class=&origin_image zh-lightbox-thumb& width=&1221& data-original=&https://pic1.zhimg.com/v2-ca9d9ce4d27d_r.jpg&&&/figure&&p&&br&&/p&&h2&HeatMap(热力图)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&import random
from pyecharts import HeatMap
x_axis = [&12a&, &1a&, &2a&, &3a&, &4a&, &5a&, &6a&, &7a&, &8a&, &9a&, &10a&, &11a&,
&12p&, &1p&, &2p&, &3p&, &4p&, &5p&, &6p&, &7p&, &8p&, &9p&, &10p&, &11p&]
y_aixs = [&Saturday&, &Friday&, &Thursday&, &Wednesday&, &Tuesday&, &Monday&, &Sunday&]
data = [[i, j, random.randint(0, 50)] for i in range(24) for j in range(7)]
heatmap = HeatMap()
heatmap.add(&热力图直角坐标系&, x_axis, y_aixs, data, is_visualmap=True,
visual_text_color=&#000&, visual_orient='horizontal')
heatmap.show_config()
heatmap.render()
&/code&&/pre&&/div&&figure&&img src=&https://pic4.zhimg.com/v2-c775a724d2725392edae8_b.jpg& data-rawwidth=&1026& data-rawheight=&528& data-thumbnail=&https://pic4.zhimg.com/v2-c775a724d2725392edae8_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1026& data-original=&https://pic4.zhimg.com/v2-c775a724d2725392edae8_r.jpg&&&/figure&&p&&br&&/p&&h2&Kline(K线图)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Kline
v1 = [[20.26, 62.94], [.3, 08.38],
[46.5, 45.92], [58.98, 63.8],
[82.48, 83.76], [85.42, 91.82],
[19.02, 21.15], [28.15, 40.38],
[.13, 37.42], [34.48, 41.73],
[18.53, 33.89], [32.4, 43.03],
[21.56, 44.8], [82.91, 27.07],
[97.18, 97.94], [25.95, 78.82],
[14.16, 30.88], [25.82, 38.78],
[93.34, 40.71], [13.22, 24.63],
[65.59, 66.16], [59.51, 69.65],
[73.4, 33.54], [26.31, 28.14],
[47.18, 51.44], [24.29, 52.02],
[18.61, 33.67], [10.59, 20.96],
[86.6, 33.29], [63.97, 86.33],
[70.28, 76.22]]
kline = Kline(&K 线图示例&)
kline.add(&日K&, [&2017/7/{}&.format(i + 1) for i in range(31)], v1)
kline.show_config()
kline.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ae1a866aa9d4cef6b999029d_b.jpg& data-rawwidth=&1028& data-rawheight=&506& class=&origin_image zh-lightbox-thumb& width=&1028& data-original=&https://pic3.zhimg.com/v2-ae1a866aa9d4cef6b999029d_r.jpg&&&/figure&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&kline = Kline(&K 线图示例&)
kline.add(&日K&, [&2017/7/{}&.format(i + 1) for i in range(31)], v1, mark_point=[&max&], is_datazoom_show=True)
kline.show_config()
kline.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-a97ba60e703c288a11add_b.jpg& data-rawwidth=&1062& data-rawheight=&538& data-thumbnail=&https://pic3.zhimg.com/v2-a97ba60e703c288a11add_b.jpg& class=&origin_image zh-lightbox-thumb& width=&1062& data-original=&https://pic3.zhimg.com/v2-a97ba60e703c288a11add_r.jpg&&&/figure&&h2&Line(折线/面积图)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Line
attr = [&衬衫&, &羊毛衫&, &雪纺衫&, &裤子&, &高跟鞋&, &袜子&]
v1 = [5, 20, 36, 10, 10, 100]
v2 = [55, 60, 16, 20, 15, 80]
line = Line(&折线图示例&)
line.add(&商家A&, attr, v1, mark_point=[&average&])
line.add(&商家B&, attr, v2, is_smooth=True, mark_line=[&max&, &average&])
line.show_config()
line.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-cbbcff48dd4_b.jpg& data-rawwidth=&846& data-rawheight=&424& data-thumbnail=&https://pic3.zhimg.com/v2-cbbcff48dd4_b.jpg& class=&origin_image zh-lightbox-thumb& width=&846& data-original=&https://pic3.zhimg.com/v2-cbbcff48dd4_r.jpg&&&/figure&&p&标记点其他配置&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&line = Line(&折线图示例&)
line.add(&商家A&, attr, v1, mark_point=[&average&, &max&, &min&],
mark_point_symbol='diamond', mark_point_textcolor='#40ff27')
line.add(&商家B&, attr, v2, mark_point=[&average&, &max&, &min&],
mark_point_symbol='arrow', mark_point_symbolsize=40)
line.show_config()
line.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-78f2cba79582aca44bf704_b.jpg& data-rawwidth=&1024& data-rawheight=&498& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&https://pic4.zhimg.com/v2-78f2cba79582aca44bf704_r.jpg&&&/figure&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&line = Line(&折线图-阶梯图示例&)
line.add(&商家A&, attr, v1, is_step=True, is_label_show=True)
line.show_config()
line.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-ff88aedd554e78beac89708_b.jpg& data-rawwidth=&816& data-rawheight=&403& class=&origin_image zh-lightbox-thumb& width=&816& data-original=&https://pic2.zhimg.com/v2-ff88aedd554e78beac89708_r.jpg&&&/figure&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&line = Line(&折线图-面积图示例&)
line.add(&商家A&, attr, v1, is_fill=True, line_opacity=0.2, area_opacity=0.4, symbol=None)
line.add(&商家B&, attr, v2, is_fill=True, area_color='#000', area_opacity=0.3, is_smooth=True)
line.show_config()
line.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-d01b6e3cd31cc0c31e5ae9_b.jpg& data-rawwidth=&826& data-rawheight=&407& class=&origin_image zh-lightbox-thumb& width=&826& data-original=&https://pic2.zhimg.com/v2-d01b6e3cd31cc0c31e5ae9_r.jpg&&&/figure&&p&&br&&/p&&h2&Liquid(水球图)&/h2&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Liquid
liquid = Liquid(&水球图示例&)
liquid.add(&Liquid&, [0.6])
liquid.show_config()
liquid.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-4a82d0cc3347fcd422d447_b.jpg& data-rawwidth=&692& data-rawheight=&394& data-thumbnail=&https://pic4.zhimg.com/v2-4a82d0cc3347fcd422d447_b.jpg& class=&origin_image zh-lightbox-thumb& width=&692& data-original=&https://pic4.zhimg.com/v2-4a82d0cc3347fcd422d447_r.jpg&&&/figure&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Liquid
liquid = Liquid(&水球图示例&)
liquid.add(&Liquid&, [0.6, 0.5, 0.4, 0.3], is_liquid_outline_show=False)
liquid.show_config()
liquid.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-a11dbacacc6e743aff2632d_b.jpg& data-rawwidth=&696& data-rawheight=&366& data-thumbnail=&https://pic3.zhimg.com/v2-a11dbacacc6e743aff2632d_b.jpg& class=&origin_image zh-lightbox-thumb& width=&696& data-original=&https://pic3.zhimg.com/v2-a11dbacacc6e743aff2632d_r.jpg&&&/figure&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&from pyecharts import Liquid
liquid = Liquid(&水球图示例&)
liquid.add(&Liquid&, [0.6, 0.5, 0.4, 0.3], is_liquid_animation=False, shape='diamond')
liquid.show_config()
liquid.render()
&/code&&/pre&&/div&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-ea1f938b5dbd5f}

我要回帖

更多关于 Y=X2与直线Y=2X+3 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信