HexoでMermaidを使ってダイアグラムを描く

 
カテゴリー SSG   タグ

HexoのMermaidプラグイン

hexo-filter-mermaid-diagramsのインストール

hexo-filter-mermaid-diagramsのインストール。

1
npm install hexo-filter-mermaid-diagrams --save

Tranquilpeakの設定

themes/tranquilpeak/_config.ymlにmermaidの設定を追加。

1
2
3
4
5
6
# Mermaid
mermaid:
enable: true
version: "7.1.2"
# Available themes: default | dark | forest | neutral
theme: default

Mermaidの読み込み

themes/tranquilpeak/layout/_partial/script.ejsに以下を追加。

1
2
3
4
5
6
7
8
<% if (theme.mermaid.enable) { %>
<script src='https://unpkg.com/mermaid@<%= theme.mermaid.version %>/dist/mermaid.min.js'></script>
<script>
if (window.mermaid) {
mermaid.initialize({theme: 'forest'});
}
</script>
<% } %>

ダイアグラムを描く

書き方

コードブロックでmermaidのコードであることを示して記述する。
コードブロックで書くことがサンプルで表現されていないので注意。

フローチャート

1
2
3
4
5
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;

Sequence diagram

1
2
3
4
5
6
7
8
9
10
11
sequenceDiagram
participant Alice
participant Bob
Alice->>John: Hello John, how are you?
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts <br/>prevail...
John-->>Alice: Great!
John->>Bob: How about you?
Bob-->>John: Jolly good!
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>John: Hello John, how are you?
    loop Healthcheck
        John->>John: Fight against hypochondria
    end
    Note right of John: Rational thoughts 
prevail... John-->>Alice: Great! John->>Bob: How about you? Bob-->>John: Jolly good!

Gantt diagram

1
2
3
4
5
6
7
8
9
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram to mermaid

section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
gantt
dateFormat  YYYY-MM-DD
title Adding GANTT diagram to mermaid

section A section
Completed task            :done,    des1, 2014-01-06,2014-01-08
Active task               :active,  des2, 2014-01-09, 3d
Future task               :         des3, after des2, 5d
Future task2               :         des4, after des3, 5d

Class diagram

1
2
3
4
5
6
7
8
9
10
11
12
13
14
classDiagram
Class01 <|-- AveryLongClass : Cool
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
classDiagram
Class01 <|-- averylongclass : cool class03 *-- class04 class05 o-- class06 class07 .. class08 class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label

Git graph

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
gitGraph:
options
{
"nodeSpacing": 150,
"nodeRadius": 10
}
end
commit
branch newbranch
checkout newbranch
commit
commit
checkout master
commit
commit
merge newbranch
gitGraph:
options
{
    "nodeSpacing": 150,
    "nodeRadius": 10
}
end
commit
branch newbranch
checkout newbranch
commit
commit
checkout master
commit
commit
merge newbranch

コメント・シェア

HexoのGoogleChartプラグイン

hexo-tag-googlechartsのインストール

1
npm install hexo-tag-googlecharts -- save

GoogleChartを読み込む

themes/tranquilpeak/layout/_partial/head.ejs<script type="text/javascript" src="//www.google.com/jsapi"></script>を読み込むように追記する。

1
2
3
    <!-- Google Chart -->
<script type="text/javascript" src="//www.google.com/jsapi"></script>
</head>

チャートを描く

書き方

1
2
3
4
5
6
7
8
9
{% googlecharts ChartType [width [height]] %}
Title for the Graph
{ "customOptions": true }
'Column1', 'Column2', 'Column3'
1000, 28, 5
5000, 71, 19
10000, 143, 37
20000, 282, 68
{% endgooglecharts %}
  • ChartTypeにはチャート名を記載
  • オプションはJSON形式で渡す
  • データはCSV形式で記述

Pie Chart

1
2
3
4
5
6
7
8
9
10
11
{% googlecharts PieChart 100% %}
Pie Chart
{}
'Task', 'Hours per Day'
'Work', 11
'Eat', 2
'Commute', 2
'Watch TV', 2
'Sleep', 7
{% endgooglecharts %}

Donut Charts

1
2
3
4
5
6
7
8
9
10
{% googlecharts PieChart 100% %}
Donut Charts
{"pieHole": 0.4}
'タスク', '時間'
'仕事', 11
'食事', 2
'通勤', 2
'テレビ', 2
'睡眠', 7
{% endgooglecharts %}

Table Charts

1
2
3
4
5
6
7
8
9
{% googlecharts Table 100% 100% %}
Table Charts
{"showRowNumber": true}
'Name', 'Salary', 'Full Time Employee'
'Mike', {v: 10000, f: '$10,000'}, true
'Jim', {v:8000, f: '$8,000'}, false
'Alice', {v: 12500, f: '$12,500'}, true
'Bob', {v: 7000, f: '$7,000'}, true
{% endgooglecharts %}

Bar Charts

1
2
3
4
5
6
7
8
9
{% googlecharts BarChart 100% %}
Bar Charts
{}
'Element', 'Density', { role: 'style' }
'Copper', 8.94, '#b87333'
'Silver', 10.49, 'silver'
'Gold', 19.30, 'gold'
'Platinum', 21.45, 'color: #e5e4e2'
{% endgooglecharts %}

Goe Charts

1
2
3
4
5
6
7
8
9
10
11
{% googlecharts GeoChart 640 480 %}
GeoCharts
{}
'Country', 'Popularity'
'Germany', 200
'United States', 300
'Brazil', 400
'Canada', 500
'France', 600
'RU', 700
{% endgooglecharts %}

Bubble Charts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% googlecharts BubbleChart 640 480 %}
Bubble Charts
{"hAxis": {"title": "Life Expectancy"}, "vAxis": {"title": "Fertility Rate"}, "bubble": {"textStyle": {"fontSize": 11}}}
'ID', 'Life Expectancy', 'Fertility Rate', 'Region', 'Population'
'CAN', 80.66, 1.67, 'North America', 33739900
'DEU', 79.84, 1.36, 'Europe', 81902307
'DNK', 78.6, 1.84, 'Europe', 5523095
'EGY', 72.73, 2.78, 'Middle East', 79716203
'GBR', 80.05, 2, 'Europe', 61801570
'IRN', 72.49, 1.7, 'Middle East', 73137148
'IRQ', 68.09, 4.77, 'Middle East', 31090763
'ISR', 81.55, 2.96, 'Middle East', 7485600
'RUS', 68.6, 1.54, 'Europe', 141850000
'USA', 78.09, 2.05, 'North America', 307007000
{% endgooglecharts %}

コメント・シェア

HexoのTranquilpeakをみやすくカスタマイズ

 
カテゴリー SSG   タグ

フォントを変更する

Webフォントを読み込む

themes/tranquilpeak/layout/_partial/head.ejs<link href="https://fonts.googleapis.com/earlyaccess/notosansjapanese.css" rel="stylesheet">を読み込むように追記する。

1
2
3
    <!-- Web Fonts -->
<link href="https://fonts.googleapis.com/earlyaccess/notosansjapanese.css" rel="stylesheet">
</head>

フォントを使用する

themes/tranquilpeak/source/_css/utils/_variables.scssをカスタマイズする。
Noto Sans Japaneseフォントを読み込み、codeとhighlight以外を置き換える。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Font families
$open-sans: 'Open Sans';
$open-sans-sans-serif: 'Open Sans', sans-serif;
$merriweather-serif: 'Merriweather', serif;
$monospace: Menlo, Consolas, monospace;
$noto-sans-japanese: 'Noto Sans Japanese';

//$font-family-base: $open-sans-sans-serif;
$font-family-base: $noto-sans-japanese;

$font-families: (
//// base
//'headings': $open-sans-sans-serif,
//// components
//'code': $monospace,
//'caption': $merriweather-serif,
//'image-gallery': $open-sans,
//'post-header-cover': $merriweather-serif,
//'post-meta': $open-sans-sans-serif,
//'post-content': $merriweather-serif,
//'post-excerpt-link': $open-sans-sans-serif,
//'highlight': $monospace,
//// layout
//'sidebar': $open-sans-sans-serif
// base
'headings': $noto-sans-japanese,
// components
'code': $monospace,
'caption': $noto-sans-japanese,
'image-gallery': $noto-sans-japanese,
'post-header-cover': $noto-sans-japanese,
'post-meta': $noto-sans-japanese,
'post-content': $noto-sans-japanese,
'post-excerpt-link': $noto-sans-japanese,
'highlight': $monospace,
// layout
'sidebar': $noto-sans-japanese
);

ヘッダーのカスタマイズ

themes/tranquilpeak/layout/_partial/post/meta.ejsをカスタマイズして、見やすくする。

  • 記事投稿日だけでなく記事の更新日も表示する
  • 各メタ情報のアイコンを表示する
  • カテゴリーだけでなくタグもヘッダーに表示する
  • カテゴリーもタグと同じ表示形式にする
  • フォントをtext-smallからtext-mediumにして
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<div class="<%= (classes ? classes.join(' ') : '') %>">
<!-- 記事投稿日 -->
<i class="fas fa-file-alt"></i>
<time datetime="<%= post.date.format() %>">
<span class="text-color-light text-medium">
<% if (post.lang) { %>
<%= post.date.locale(post.lang).format(__('date_format')) %>
<% } else { %>
<%= post.date.locale(page.lang).format(__('date_format')) %>
<% } %>
</span>
</time>
&nbsp;
<!-- 記事更新日 -->
<% if (post.updated) { %>
<i class="fas fa-redo-alt"></i>
<time datetime="<%= post.updated.format() %>">
<span class="text-color-light text-medium">
<% if (post.lang) { %>
<%= post.updated.locale(post.lang).format(__('date_format')) %>
<% } else { %>
<%= post.updated.locale(page.lang).format(__('date_format')) %>
<% } %>
</span>
</time>
<% } %>
<br>
<!-- カテゴリー -->
<% if ((post.categories) && (post.categories.length > 0)) { %>
<i class="far fa-folder-open"></i>
<span class="text-color-light text-medium"><%= __('post.categorized_in') %> </span>
<%- partial('category', {categories: post.categories})%>
<% } %>
&nbsp;
<!-- タグ -->
<% if ((post.tags) && (post.tags.length > 0)) { %>
<i class="far fa-folder-open"></i>
<span class="text-color-light text-medium"><%= __('post.tagged_in') %> </span>
<%- partial('tag', {tags: post.tags})%>
<% } %>
</div>

フッターのカスタマイズ

themes/tranquilpeak/layout/_partial/post.ejsをカスタマイズして、フッターからタグを削除。

  • タグをフッターに表示しない
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    <div id="post-footer" class="post-footer main-content-wrap">
<!--
<% if ((post.tags) && (post.tags.length > 0)) { %>
<div class="post-footer-tags">
<span class="text-color-light text-small"><%= __('post.tagged_in') %></span><br/>
<%- partial('post/tag', {tags: post.tags})%>
</div>
<% } %>
-->
<% if (post.actions === undefined || post.actions) { %>
<%- partial('post/actions', {postContent: postContent}) %>
<% } %>
<% if (post.comments) { %>
<% if (theme.disqus_shortname) { %>
<%- partial('post/disqus') %>
<% } else if (theme.gitment.enable) { %>
<%- partial('post/gitment') %>
<% } else if (theme.gitalk.enable) { %>
<%- partial('post/gitalk') %>
<% } %>
<% } %>
</div>
</article>

ベフォーアフター

元々発生していたGoogleAnalyticsでのエラー

GoogleAnalytics Error width=640

ヘッダーおよびフォントの変化

ビフォー。アルファベットと日本語のバランスが良くない。

Hexo Tranquilpeak width=640

アフター。統一感があって読みやすい。カテゴリーとタグも視認しやすくなったが、ゴチャついてる感じも。

Hexo Tranquilpeak width=640

フッターの変化

ビフォー。記事が長いとアクセスしにくいタグ。

Hexo Tranquilpeak width=640

アフター。すっきり。

Hexo Tranquilpeak width=640

コメント・シェア

パスワードマネージャー

主要なパスワードマネージャー

比較

項目 1Password LastPass Dashlane Bitwarden
ブラウザ拡張
モバイルアプリ
多要素認証
オープンソース × × ×
無料プラン × ×
有料プラン(年間) 36USD 36USD 40USD 10USD

Bitwardenのコスパがすごくいい。

Bitwarden

特徴

  • パスワードマネージャーの機能としては必要十分
  • 無料プランで十分実用的
  • OpenSource(GitHub)
  • Bitwardenクラウドを利用できるが、パスワードマネージャーサーバを構築することも可能

End-to-End Encryption

end-to-end AES-256 bit encryption, salted hashing, and PBKDF2 SHA-256.

個人情報やパスワードはエンドエンド間で暗号化。暗号化アルゴリズムはAES256。ハッシュはPBKDF2。PBKDF2は安全なハッシュ方式でSHA-256をベースにソルトやストレッチ(複数回ハッシュ化を繰り返して解析耐性を上げる)。

Cross-Platform Applications

クロスプラットフォーム対応。主要なものは対応している。

  • Desktop(Windows, macOS, Linux)
  • Web Browser(GoogleChrome, Safari, Mozilla Firefox, Vivaldi, Opera, Brave, Microsoft Edge, Tor Browser)
  • Mobile(Apple, Google)
  • Command Line(Windows, macOS, Linux
  • Web(Access Web Vault)

BitWartdenアカウントの作成

Create Your Free Accountからアカウント作成

Bitwarden width=640

Bitwarden width=640

保管庫にアカウントデータが保存される。

Bitwarden width=640

Bitwarden width=640

パスワード生成ツールによってポリシーに従ったランダムパスワードを付与できる

Bitwarden width=640

2段階認証で多要素認証の設定が可能。

Bitwarden width=640

Chromenに保存したID/パスワードのエクスポート

Chromeに保存されたID/パスワードをエクスポートする。設定->自動入力->パスワードから。

Bitwarden width=640

Bitwarden width=640

エクスポートにはWindowsの認証が必要。

Bitwarden width=320

Chromenに保存したID/パスワードのインポート

データをインポートから、ChromeのCSVを選択して、エクスポートしたデータをインポート。

Bitwarden width=640

Bitwarden width=640

Bitwarden width=640

保管庫にインポートされる。

Bitwarden width=640

BitwardenのChromeアドオン

Bitwarden無料パスワードマネージャーを追加。

Bitwarden Chrome width=640

Bitwarden Chrome width=320

Bitwarden Chrome width=640

アドオンにログインすれば、保管庫のID/パスワードを自動入力できるようになる。

Bitwarden Chrome width=320

Bitwarden Chrome width=320

Bitwarden Chrome width=320

コメント・シェア

動かない

コード0x8004de40
インターネットにはつながっていますか?のようなものを除き主要な対策は3つ。

対策1: TLSが有効であることを確認する

  1. inetcpl.cplを実行
  2. 詳細設定でTLS1.0、TLS1.1、TLS1.2にチェックが入っていることを確認

対策2: Windows Socket (Winsock)カタログをリセットする

  1. cmdを管理者で実行
  2. 起動したコマンドプロンプトでnetsh winsock reset catalogを実行

対策3: OneDriveをリセットする

大量にファイルがあると、時間がかかるので注意。

  1. %localappdata%\\Microsoft\\OneDrive\\onedrive.exe /resetを実行
  2. %localappdata%\\Microsoft\\OneDrive\\onedrive.exeで再起動

それでも動かない

これら主要なワークアラウンドでこの時は結局解決しなかった。
しかし、溜まっていたWindowsUpdateを適用したらなぜか解消……。なにそれ。

コメント・シェア

OneDriveの個人用Vaultとは

Office365を利用していると1TBのストレージと制限なしの個人用Vaultが使える。

個人用Vault、表記によってはPersonal Vaultになっている。使用しているプランによって使えるファイル数制限がある。
個人用Vaultは普段ロックされ、多要素認証を行うことで保護したフォルダーにアクセスすることができる。利用しない場合は20分(モバイルアプリでは3分)で自動ロックされる。

項目 Microsoft 365 Personal OneDrive Standalone 100GB OneDrive Basic 5 GB
合計ストレージ 1 TB 100 GB 5 GB
個人用Vault 制限なし 3ファイル 3ファイル

個人用Vaultを使う

OneDriveのフォルダー内にある個人用Vaultのアイコンからセットアップ開始

OneDriveVaultwidth=320

OneDriveVaultwidth=320

OneDriveVaultwidth=320

個人用Vaultアイコンから再度実行すると、本人確認を促される。

OneDriveVaultwidth=320

OneDriveVaultwidth=320

OneDriveVaultwidth=320

本人確認後、フォルダーを読み書きできるようになる。

OneDriveVaultwidth=320

個人用Vaultフォルダーのロック

手動でロックすることもできる。

OneDriveVaultwidth=480

ロックするとフォルダーへのアクセスはエラーに。

OneDriveVaultwidth=480

同期もできなくなっている。

OneDriveVaultwidth=320

ロックを解除するとOneDriveの設定画面でも確認できる。ここからロックすることもできる。

OneDriveVaultwidth=320

多要素認証を変更する

メールではなくGoogleAuthenticatorのようなアプリを利用するように変更することができる。

  1. Microsoft アカウントにアクセス

OneDriveのアカウントでサインイン

OneDriveVaultwidth=640

OneDriveVaultwidth=640

OneDriveVaultwidth=640

セキュリティ情報を更新する。

OneDriveVaultwidth=640

OneDriveVaultwidth=640

OneDriveVaultwidth=640

OneDriveVaultwidth=640

OneDriveVaultwidth=640

認証アプリでのコード入力を追加する。身元を証明する方法のサインインまたは確認の新しい方法を追加から追加する。

OneDriveVaultwidth=640

アプリを使う。

OneDriveVaultwidth=640

Microsoft Authenticatorは使わないのでスキップ。

OneDriveVaultwidth=640

自分のAuthenticatorアプリでQRコードを読み込み設定。

OneDriveVaultwidth=640

認証アプリからコードを入力するが追加されている。

OneDriveVaultwidth=640

個人用Vaultにアクセスしようとすると、今度は認証アプリでコード入力が求められる。

OneDriveVaultwidth=320

自動ロックの時間を設定する

OneDriveのアカウント設定で設定できる。標準は20分。

OneDriveVaultwidth=480

コメント・シェア

Django REST frameworkチュートリアル

公式のQuick Startからチュートリアルへ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$ mkdir tutorial
$ cd tutorial
$ django-admin startproject tutorial .
$ cd tutorial
$ django-admin startapp quickstart
$ pwd
/work/tutorial/tutorial
$ cd ..
$ find .
.
./manage.py
./tutorial
./tutorial/__init__.py
./tutorial/asgi.py
./tutorial/quickstart
./tutorial/quickstart/__init__.py
./tutorial/quickstart/admin.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/migrations
./tutorial/quickstart/migrations/__init__.py
./tutorial/quickstart/models.py
./tutorial/quickstart/tests.py
./tutorial/quickstart/views.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py
$ ./manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
$ ./manage.py createsuperuser --email admin@example.com --username admin
Password: ********
Password (again): ********
Superuser created successfully.

Serializers

Serializertutorial/quickstart/serializers.py)を定義。
SerializerはデータをPythonデータ型に変換し、JSONなどのコンテンツタイプにレンダリングする処理を担う。
既定のクラスを継承して実装する。ここでは主キーフィールドの変わりにurlフィールドを使用するHyperlinkedModelSerializerを使用している。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.contrib.auth.models import User, Group
from rest_framework import serializers


class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'groups']


class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ['url', 'name']

Views

Viewtutorial/quickstart/views.py)を定義。
ViewSetsでモデルのCRUD操作を暗黙的に実装している。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer


class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer


class GroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Group.objects.all()
serializer_class = GroupSerializer

URLs

urltutorial/urls.py)を定義。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

Pagination

settingstutorial/settings.py)をカスタマイズ。

  • SECRET_KEYを環境変数で定義する
  • INSTALL_APPSでrest_frameworkを追加する
  • Pagenation(次のページ)を有効化する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ['SECRET_KEY']

…略…

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
]

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}

アクセス

Viewとしてusersgroupsが定義されている

1
2
3
4
5
$ curl -H 'Accept: application/json; indent=4' -u admin:adminadmin http://127.0.0.1:8000/
{
"users": "http://127.0.0.1:8000/users/",
"groups": "http://127.0.0.1:8000/groups/"
}

Django REST framework quickstart width=640

Paginationを設定したので、応答にnextpreviousが追加されている。アイテム数が少ないので、値はnull。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ curl -H 'Accept: application/json; indent=4' -u admin:adminadmin http://127.0.0.1:8000/users/
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"url": "http://127.0.0.1:8000/users/1/",
"username": "admin",
"email": "admin@example.com",
"groups": []
}
]
}
$ curl -H 'Accept: application/json; indent=4' -u admin:adminadmin http://127.0.0.1:8000/groups/
{
"count": 0,
"next": null,
"previous": null,
"results": []
}

Django REST framework quickstart width=640

Django REST framework quickstart width=640

コメント・シェア

DjangoのSECRET_KEYをGitの管理対象外にする

 
カテゴリー Python   タグ

DjangoのSECRET_KEY

A secret key for a particular Django installation. This is used to provide cryptographic signing, and should be set to a unique, unpredictable value.

django-admin startproject automatically adds a randomly-generated SECRET_KEY to each new project.

SECRET_KEYは暗号署名のために一意で予測不能な値にする必要がある。
django-admin startprojectで自動的にsetting.pySECRET_KEYにランダムな値が追加される。

The secret key is used for:

  • All sessions if you are using any other session backend than django.contrib.sessions.backends.cache, or are using the default get_session_auth_hash().
  • All messages if you are using CookieStorage or FallbackStorage.
  • All PasswordResetView tokens.
  • Any usage of cryptographic signing, unless a different key is provided.

If you rotate your secret key, all of the above will be invalidated. Secret keys are not used for passwords of users and key rotation will not affect them.

  • Sessions
    • django.contrib.sessions.backends.cache以外のセッションバックエンドを使用する場合
    • get_session_auth_hash()を使用する場合
  • messages
    • CookieStorageかFallbackStorageを使用する場合
  • PasswordResetView Tokens
  • Cryptographic signing
    • 異なる鍵が提供されない場合

setting.pyからSECRET_KEYの値を外だしする

GitリポジトリにSECRET_KEYをPushしないように、setting.pyに埋め込まれたSECRET_KEYを環境変数にして管理する。

1
2
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ['SECRET_KEY']

.envファイルで環境変数を管理している場合は以下のように設定。

1
SECRET_KEY=e=+g9j8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX@k8wj0&

コメント・シェア

Django REST framework

 
カテゴリー Python   タグ

django REST framework

  • The Web browsable API is a huge usability win for your developers.
  • Authentication policies including packages for OAuth1a and OAuth2.
  • Serialization that supports both ORM and non-ORM data sources.
  • Customizable all the way down - just use regular function-based views if you don’t need the more powerful features.
  • Extensive documentation, and great community support.
  • Used and trusted by internationally recognised companies including Mozilla, Red Hat, Heroku, and Eventbrite.
  • Webブラウジング可能なAPIによるユーザビリティ
  • OAuth1aとOuth2のための認証ポリシーを含む
  • ORMとnon-ORMの各データソースのシリアライズをサポート
  • 端から端までカスタマイズ可能
  • 広範囲のドキュメントとコミュニティサポート
  • さまざまな国際的企業で利用されている

Django REST framework width=640

BLACK LIVES MATTERやってる(2020/6/18)

Requirements

REST framework requires the following:

Python (3.5, 3.6, 3.7, 3.8)
Django (1.11, 2.0, 2.1, 2.2, 3.0)
We highly recommend and only officially support the latest patch release of each Python and Django series.

The following packages are optional:

coreapi (1.32.0+) - Schema generation support.
Markdown (3.0.0+) - Markdown support for the browsable API.
Pygments (2.4.0+) - Add syntax highlighting to Markdown processing.
django-filter (1.0.1+) - Filtering support.
django-guardian (1.1.1+) - Object level permissions support.

これを元にrequirement.txtを作成。

1
djangorestframework

Django REST frameworkのインストール

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ pip install -r requirements.txt
Collecting djangorestframework
Downloading djangorestframework-3.11.0-py3-none-any.whl (911 kB)
|████████████████████████████████| 911 kB 3.2 MB/s
Collecting django>=1.11
Downloading Django-3.0.7-py3-none-any.whl (7.5 MB)
|████████████████████████████████| 7.5 MB 10.5 MB/s
Collecting sqlparse>=0.2.2
Downloading sqlparse-0.3.1-py2.py3-none-any.whl (40 kB)
|████████████████████████████████| 40 kB 7.7 MB/s
Collecting asgiref~=3.2
Downloading asgiref-3.2.9-py3-none-any.whl (19 kB)
Requirement already satisfied: pytz in /usr/local/lib/python3.8/site-packages (from django>=1.11->djangorestframework->-r requirements.txt (line 1)) (2019.3)
Installing collected packages: sqlparse, asgiref, django, djangorestframework
Successfully installed asgiref-3.2.9 django-3.0.7 djangorestframework-3.11.0 sqlparse-0.3.1

Exampleで基本的な動作を見る

プロジェクト作成

  1. django-adminコマンドでexampleプロジェクトを作成
  2. manage.py migrateを実行
  3. manage.py createsuperuserでrootアカウント作成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
$ django-admin startproject example .
$ tree .
.
├── README.md
├── docker-compose.yml
├── example
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── requirements.txt

1 directory, 9 files

$ ./manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
$ ./manage.py createsuperuser
Username (leave blank to use 'root'):
Email address:
Password: ********
Password (again): ********
Superuser created successfully.

settings.pyのカスタマイズ

INSTALLED_APPSrest_frameworkを追加し、REST_FRAMEWORKで基本設定を行う。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
]

REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}

url.pyのカスタマイズ

Example用のAPIをカスタマイズ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from django.urls import path, include
from django.contrib.auth.models import User
from rest_framework import serializers, viewsets, routers

# Serializers define the API representation.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'is_staff']


# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer


# Routers provide a way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)


# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

APIのテスト

1
2
3
4
5
6
7
8
9
10
11
$ ./manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
June 17, 2020 - 15:50:19
Django version 3.0.7, using settings 'example.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[17/Jun/2020 15:50:42] "GET / HTTP/1.1" 200 47
[17/Jun/2020 15:50:49] "GET /users/ HTTP/1.1" 200 138

作成済のrootアカウントを閲覧できるか確認する。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ curl -H 'Accept: application/json; indent=4' -u root:rootroot http://127.0.0.1:8000/
{
"users": "http://127.0.0.1:8000/users/"
}
$ curl -H 'Accept: application/json; indent=4' -u root:rootroot http://127.0.0.1:8000/users/
[
{
"url": "http://127.0.0.1:8000/users/1/",
"username": "root",
"email": "",
"is_staff": true
}
]

ユーザを追加する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ curl -X POST -d username=new -d email=new@example.com -d is_staff=false -H 'Accept: application/json; indent=4' -u root:rootroot http://127.0.0.1:8000/users/
{
"url": "http://127.0.0.1:8000/users/2/",
"username": "new",
"email": "new@example.com",
"is_staff": false
}
$ curl -H 'Accept: application/json; indent=4' -u root:rootroot http://127.0.0.1:8000/users/
[
{
"url": "http://127.0.0.1:8000/users/1/",
"username": "root",
"email": "",
"is_staff": true
},
{
"url": "http://127.0.0.1:8000/users/2/",
"username": "new",
"email": "new@example.com",
"is_staff": false
}
]

runserverは127.0.0.1で待ち受けるので、コンテナ外からアクセスできるように0.0.0.0で待ち受ける。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ ./manage.py runserver 0.0.0.0:8000
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
June 17, 2020 - 16:12:22
Django version 3.0.7, using settings 'example.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
[17/Jun/2020 16:12:38] "GET / HTTP/1.1" 200 5322
[17/Jun/2020 16:12:38] "GET /static/rest_framework/css/bootstrap-tweaks.css HTTP/1.1" 200 3385
[17/Jun/2020 16:12:38] "GET /static/rest_framework/js/csrf.js HTTP/1.1" 200 1719
[17/Jun/2020 16:12:38] "GET /static/rest_framework/css/prettify.css HTTP/1.1" 200 817
[17/Jun/2020 16:12:38] "GET /static/rest_framework/js/prettify-min.js HTTP/1.1" 200 13632
[17/Jun/2020 16:12:38] "GET /static/rest_framework/css/bootstrap.min.css HTTP/1.1" 200 121457
[17/Jun/2020 16:12:38] "GET /static/rest_framework/css/default.css HTTP/1.1" 200 1131
[17/Jun/2020 16:12:38] "GET /static/rest_framework/js/bootstrap.min.js HTTP/1.1" 200 39680
[17/Jun/2020 16:12:38] "GET /static/rest_framework/js/ajax-form.js HTTP/1.1" 200 3597
[17/Jun/2020 16:12:38] "GET /static/rest_framework/js/default.js HTTP/1.1" 200 1268
[17/Jun/2020 16:12:38] "GET /static/rest_framework/js/jquery-3.4.1.min.js HTTP/1.1" 200 88145
[17/Jun/2020 16:12:39] "GET / HTTP/1.1" 200 5322
[17/Jun/2020 16:12:39] "GET /static/rest_framework/img/grid.png HTTP/1.1" 200 1458
Not Found: /favicon.ico
[17/Jun/2020 16:12:39] "GET /favicon.ico HTTP/1.1" 404 3137
[17/Jun/2020 16:13:02] "GET /users/ HTTP/1.1" 200 5886
[17/Jun/2020 16:13:03] "GET /static/rest_framework/css/bootstrap-tweaks.css HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/css/default.css HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/css/bootstrap.min.css HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/css/prettify.css HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/js/jquery-3.4.1.min.js HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/js/csrf.js HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/js/ajax-form.js HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/js/default.js HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/js/prettify-min.js HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/js/bootstrap.min.js HTTP/1.1" 304 0
[17/Jun/2020 16:13:03] "GET /static/rest_framework/img/grid.png HTTP/1.1" 304 0

Django REST framework example width=640

Django REST framework example width=640

管理画面

from django.contrib import adminでインポートし、urlpatternsにpath('admin/', admin.site.urls),を追加する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from django.contrib import admin
#from django.urls import path

#urlpatterns = [
# path('admin/', admin.site.urls),
#]

from django.urls import path, include
from django.contrib.auth.models import User
from rest_framework import serializers, viewsets, routers

…中略…

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

http://localhost:8000/admin/から管理機能にアクセスできる。

Django REST framework example width=640

Django REST framework example width=640

コメント・シェア

Sleepが安定しない…勝手に復帰してしまう

 
カテゴリー Windows   タグ

スリープが安定しない

PCをスリープさせて眠ろうとしたら……起動
再度スリープさせても……起動

解除しているデバイスは何か

管理者モードでコマンドプロンプトを起動して、powercfg -lastwakeで確認することができる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
C:\Windows\system32>powercfg -lastwake
スリープ状態の解除履歴カウント - 1
スリープ状態の解除履歴 [0]
スリープ状態の解除元カウント - 1
スリープ状態の解除元 [0]
種類: デバイス
インスタンス パス: USB\VID_XXXX&PID_XXXX\7&XXXXXXXXXXXXXXX
フレンドリ名:
説明: USB Composite Device
製造元: (標準 USB ホスト コントローラー)

C:\Windows\system32>powercfg -devicequery wake_armed
HID 準拠マウス
HID キーボード デバイス
HID キーボード デバイス (001)

イベントビューアーで確認する

Windowsログ -> システムでソースがPower-Troubleshooterのものを確認。

1
2
3
4
5
6
システムは低電力状態から再開しました。

スリープ時間: ‎2020‎-‎06‎-‎16T16:27:38.675253100Z
スリープ解除時間: ‎2020‎-‎06‎-‎16T16:28:02.205399800Z

スリープ状態の解除元: デバイス -USB Composite Device
1
2
3
4
5
6
システムは低電力状態から再開しました。

スリープ時間: ‎2020‎-‎06‎-‎16T16:39:26.214154100Z
スリープ解除時間: ‎2020‎-‎06‎-‎16T16:39:57.242369700Z

スリープ状態の解除元: デバイス -USB Composite Device

マウスは操作していないがUSB Composite Deviceによって30秒ぐらいでスリープ解除されている。

正常にスリープして復帰した場合は以下の様にスリープ時間~解除時間までは長い。

1
2
3
4
5
6
システムは低電力状態から再開しました。

スリープ時間: ‎2020‎-‎06‎-‎16T16:41:13.952273900Z
スリープ解除時間: ‎2020‎-‎06‎-‎16T22:51:34.244904400Z

スリープ状態の解除元: デバイス -USB Composite Device

スリープを邪魔しているものは

そもそもうまくスリープ後にすぐに復帰してしまう状態なので、何かが邪魔をしてスリープしないわけではない。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
C:\Windows\system32>powercfg -requests
DISPLAY:
なし。

SYSTEM:
なし。

AWAYMODE:
なし。

実行:
[SERVICE] \Device\HarddiskVolume3\Windows\System32\svchost.exe (UsoSvc)
Universal Orchestrator

PERFBOOST:
なし。

ACTIVELOCKSCREEN:
なし。

Universal OrchestratorでWindowsUpdateのためにスリープ解除する事例は多いが、今回は違う。

解決方法1: スリープ解除タイマーを無効化する

WindowsUpdateのためにスリープ解除する事例の対策でよくある、スリープ解除タイマーの無効化。
電源オプションの詳細設定でスリープ -> スリープ解除タイマーの許可 -> 設定: 無効にする。

Disable sleep awake width=480

なぜかこれで解消してしまった。

解決方法2: マウスのスリープ解除を無効化する

デバイスマネージャーでマウスとほかのポインティングデバイス -> HID準拠マウスのプロパティで設定する。
このデバイスで、コンピューターのスタンバイ状態を解除できるようにするのチェックを外す。

Disable sleep awake width=480

こちらが本命だったが、これを設定してもマウスを動かすとスリープ解除してしまう……

コメント・シェア

nullpo

めも


募集中


Japan