nikkie-ftnextの日記

イベントレポートや読書メモを発信

Django Girls Tutorial ExtensionsをDjango2系で動かす(Part 2/3) セキュリティ編

はじめに

いつも心は虹色に! nikkieです。
Django Girls Tutorial ExtensionsのDjango2系動作確認の第2弾です。
第1弾はこちら:Django Girls Tutorial ExtensionsをDjango2系で動かす(Part 1/3) #モグモグDjango - nikkie-ftnextの日記
先日の #モグモグDjango で確認したことをブログにまとめました。

背景

Django Girls Tutorial Extensionsでは、Django Girls Tutorialで作ったブログアプリに機能追加していきます。
ExtensionsのコードはDjango 1系で書かれており、Django Girls Tutorialの翻訳メンバーの間では「Django 2系に書き換えたいね」という話が出ていました。

Django 2系に書き換える対象は、3ページあります。

今回はセキュリティのチュートリアルを進める中で気づいたことを書きます。

ブログアプリで何が問題か

Django Girls Tutorialの中で、ログインしているユーザだけに投稿作成ボタンや編集ボタンが見えるようにしました。
参照:Djangoフォーム · Django Girls Tutorial の「セキュリティ」

これは新しい投稿の作成を完全に保護するものではありませんが、それは良い第一歩です。 私たちは拡張レッスンでより多くのセキュリティをカバーします。

確かに画面上にボタンが見えなくなったのですが、URLを推測すると記事が作れてしまうという問題があります。1
ログインしていないユーザでhttp://127.0.0.1:8000/post/new/にアクセスすると、記事の作成画面が表示されます。
f:id:nikkie-ftnext:20181110200323p:plain

セキュリティ対応

ログインが求められるように修正

URLを推測されても記事が作成できないようにする対応はそれほど大変ではありませんでした。
ビューの関数に@login_requiredを設定すると、ログインが求められるように変更できます。

blog/views.py

from django.contrib.auth.decorators import login_required # 追加
from django.shortcuts import redirect
# 省略

@login_required # 追加
def post_new(request):
    # 省略
    
@login_required # 追加
def post_edit(request, pk):
    # 省略

@login_required # 追加
def post_draft_list(request):
    # 省略

@login_required # 追加
def post_publish(request, pk):
    # 省略

@login_required # 追加
def post_remove(request, pk):
    # 省略

この時点ではログイン画面のテンプレートが用意されていないため、ログインしていないユーザで、http://127.0.0.1:8000/post/new/(記事作成のURL)にアクセスするとエラーとなります。
f:id:nikkie-ftnext:20181110200403p:plain
ですが、誰でも記事が作れる状態ではひとまず修正されました。

ログイン画面を用意する

ログイン画面用のURLの設定は、プロジェクト側で(mysite/urls.pyで)行います。

# 省略
from django.contrib.auth import views # 追加

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/login/', views.login, name='login'), # 追加
    path('', include('blog.urls')),
]

ログイン画面のテンプレートを追加しましょう。 blog/templatesの下にregistrationというフォルダを作り、login.htmlを置きます。
ログイン機能はDjangoに用意されたものを使うために、命名規則を守る必要があると理解しました。

blog/templates/registration/login.html

{% extends "blog/base.html" %}

{% block content %}
  {% if form.errors %}
    <p>Your username and password didn't match. Please try again.</p>
  {% endif %}

  <form method="POST" action="{% url 'login' %}">
    {% csrf_token %}
    <table>
      <tr>
        <td>{{ form.username.label_tag }}</td>
        <td>{{ form.username }}</td>
      </tr>
      <tr>
        <td>{{ form.password.label_tag }}</td>
        <td>{{ form.password }}</td>
      </tr>
    </table>

    <input type="submit" value="login">
    <input type="hidden" name="next" value="{{ next }}">
  </form>
{% endblock %}

テンプレートで使われているform.username.label_tagは、HTMLのlabel要素を作る関数だそうです。
https://docs.djangoproject.com/en/2.0/topics/forms/#rendering-fields-manually

ログインしていないユーザで、http://127.0.0.1:8000/post/new/(記事作成のURL)にアクセスすると、以下のようなログイン画面が表示されます!
(ただし、画像はログイン画面に直接アクセスしたときのものです。)
f:id:nikkie-ftnext:20181110200336p:plain

ログイン画面周りでは、あと少しだけコードを修正する必要があります。
ログイン画面のURL(http://127.0.0.1:8000/accounts/login/)を直接叩いてログインした場合、ログインしたあとにページが見つからずにエラーとなります。
f:id:nikkie-ftnext:20181124162627p:plain

この対応はmysite/settings.pyで行います。
末尾に以下の1行を追加しました。

LOGIN_REDIRECT_URL = '/'

この設定により、ログイン画面のURLを直接叩いた場合、ログインに成功後、記事一覧(http://127.0.0.1:8000/)が表示されます。

ログイン・ログアウトのためのリンクを追加

ログイン機能を使うためのリンクを追加します。

blog/templates/blog/base.html

    {% if user.is_authenticated %}
      <a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
      <a href="{% url 'post_draft_list' %}" class="top-menu"><span class="glyphicon glyphicon-edit"></span></a>
    {% else %} <!-- 追加 -->
      <a href="{% url 'login' %}" class="top-menu"><span class="glyphicon glyphicon-lock"></span></a> <!-- 追加 -->
    {% endif %}

ログインしていない場合、ヘッダーにログイン画面に遷移するリンク(鍵のアイコン)が表示されます。 f:id:nikkie-ftnext:20181110200452p:plain

ログアウトの機能も実装します。

mysite/urls.py

# 省略

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/login/', views.login, name='login'),
    path('accounts/logout/', views.logout, name='logout', kwargs={'next_page': '/'}), # 追加
    path('', include('blog.urls')),
]

blog/templates/blog/base.html

    {% if user.is_authenticated %}
      <a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
      <a href="{% url 'post_draft_list' %}" class="top-menu"><span class="glyphicon glyphicon-edit"></span></a>
      <p class="top-menu">Hello {{ user.username }} <small>(<a href="{% url 'logout' %}">Log out</a>)</small></p> <!-- 追加 -->
    {% else %}
      <a href="{% url 'login' %}" class="top-menu"><span class="glyphicon glyphicon-lock"></span></a>
    {% endif %}

ログインユーザの情報とログアウトのリンクがヘッダーに表示されるようになりました。
f:id:nikkie-ftnext:20181110195444p:plain

書き換えなくてもDjango2.0.9で動きました

ここまででDjango2系向けに書き換えたのは、urlpatternsのurl関数です(path関数にしました)。 Django2系でもurl関数は使えるので、Extensionsのコードのままでも動きました。
参考:Django 1.11 と 2.0 の違い (「現場で使える 基礎 Django」本の補講その1) - akiyoko blog

django.conf.urls.url() を使った書き方は、Django 2.0 でもそのまま使えるように互換性が保たれていますし、(後略)

mysite/urls.py

from django.conf.urls import url # 追加
from django.contrib import admin
from django.urls import path, include

from django.contrib.auth import views # 追加


urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^accounts/login/$', views.login, name='login'), # 追加
    url(r'^accounts/logout/$', views.logout, name='logout', kwargs={'next_page': '/'}), # 追加
    path('', include('blog.urls')),
]

mysite/urls.pyをDjango2系向けにアップデート

この記事を書く中で記述の食い違いに気づきました。

  • 原文(Django 1系):django.contrib.auth.views.login
  • セキュリティのバートで参照されているドキュメント2の書き方:django.contrib.auth.login

結論を言うと、mysite/urls.pyを以下のように書き換えた方がよいことがわかりました。

# 省略
urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/login/', views.LoginView.as_view(), name='login'), # 変更
    path('accounts/logout/', views.LogoutView.as_view(next_page='/'), name='logout'), # 変更
    path('', include('blog.urls')),
]

これはDjango 2系で動く書き方です。
LoginView()を使う書き換えをしないと、Django 2.1.xで動かないと考えています。3
django.contrib.auth.views.loginを使った書き方は、Django 2.0.xまでで動く書き方で、2.1.xでは動かないという認識です)

LogoutView.as_view()では、引数にログアウト後に表示されるページ(記事一覧)のURLを渡しています。4
mysite/settings.pyにLOGOUT_REDIRECT_URL = '/'を指定することでも同じ動きが実現できましたが、Django Adminからログアウトした場合も記事一覧に遷移するという副作用がありました。

なお、django.contrib.auth.loginを使う書き方はビュー向けであるようで、importしてからpath('accounts/login/', login, name='login')のように使うとエラーとなりました。(TypeError: login() missing 1 required positional argument: 'user'

終わりに

Extensionsでログイン機能を触ったことで、Djangoでアプリケーションが作れそうな気がしてきました。

そして、残るはコメント機能。
Django2系の動作確認最終回でまたお会いしましょう。
最後までお読みいただき、ありがとうございました。

脚注


  1. PythonAnywhereで公開されているDjango Girls Tutorialのブログアプリは第三者が記事を作れる状態なので、なるべくExtensionsのセキュリティのパートまで進めていただくのを個人的には推奨します。

  2. ドキュメントのURLのうち、Djangoのバージョンだけ2.0に変えて参照しました:https://docs.djangoproject.com/en/2.0/topics/auth/default/#how-to-log-a-user-out

  3. django.contrib.auth.views.loginのソースを見たところ、'The login() view is superseded by the class-based LoginView().'RemovedInDjango21Warning)と記載されていました。Django 2.1.xではLoginView()を使う書き方に置き換わるようです。→リリースノートを確認したら削除されていました:https://docs.djangoproject.com/ja/2.1/releases/2.1/#features-removed-in-2-1

  4. コード例:Django 1.9 から 2.1 に上げる時の備忘録 - Qiita

「The macOS installation couldn't be completed」にOS再インストールで対応しました

はじめに

いつも心は虹色に! nikkieです。
先日MacBook Proに問題が発生し、なんとか解決したので、備忘録がてら残します。

発生した問題

Macを再起動したら「The macOS installation couldn't be completed」というエラーメッセージが表示されました。

このエラーメッセージから抜け出せずに弱りました。。

  • Shutdown:シャットダウン後、再度起動すると同様のエラーメッセージが表示される
  • Restart:再起動が完了すると同様のエラーメッセージが表示される

MacBook Proについて

  • macOS 10.13.x(High Sierra1
  • FileVaultを有効にしている

解決策

いったんMacをシャットダウンした後、リカバリーモード(Cmd+R押し)で起動して、Macintosh HDにOSを再インストールしました。

注意:この方法はデータが消えないとは言い切れないので、リスキーです。自己責任で実施してください。

試したこと:セーフモード起動

OS再インストールの前にセーフモード(Shift押し)起動を試しました。
先ほどのエラーメッセージは表示されませんでしたが、プログレスバーが100%に達した後、画面が遷移しない事象が発生。。
やむなく(リスクを取って)電源ボタン長押しで強制終了しています。

Appleサポート曰く

Appleサポートの推奨する対応は、外付けハードディスクを用意することだそうです。

  1. 外付けハードディスクにOS再インストール
  2. 外付けハードディスクのOSで起動し、Macintosh HDのバックアップを取得する(必要なファイルのコピーをとる)
  3. Macintosh HDにOS再インストール

Macintosh HDにOSを再インストールすると、理論上はOSの部分だけが置き換わるはずですが、ユーザのデータに影響がないとは言い切れないため、外付けハードディスクの用意を推奨しているそうです。

外付けハードディスクについて

教訓:APFSでフォーマットできるものを選びましょう。

Mac向け・フォーマット不要」と謳った外付けハードディスクを用意したところ、APFS2でのフォーマットに失敗しました。
どうやらHigh SIerra以降のAPFSに対応していなかったようです。
「もういいや。まっさらでも仕事できないよりマシ」と割り切り、リスクを取って再インストールする決断ができました。

OS再インストールの副作用

Xcodeコマンドラインツールが消えていたので入れました。
xcode-select --install
現時点ではそのくらいで、ほとんどのデータは消えていないようです。

終わりに

OS再インストールで、データが消えずに解決して本当によかったです。
PCはいつ動かなくなるかわからないと痛感したので、クラウド上にデータを置くことを習慣化します。(日々の忙しさで後回しにしてしまいがちだったので要反省)
PCにグレートリセットがかかっても、問題ないと言えるようにしないといけませんね。

今回Appleサポートの方には非常に素晴らしい対応をしていただきました。
本当にありがとうございました。

OS再インストールにて「復旧サーバに接続できない」と表示される場合の対応(12/2 追記)

  1. Wi-Fi接続の確認
  2. PCの時刻の確認(リカバリーモードでもターミナルが起動できる。dateコマンドで確認する。再設定もdateコマンドを使う)

参考:macOSの再インストールで「復旧サーバに接続できませんでした。」とエラーが出たときの対処方法 - creativi.tea

参考情報


  1. おそらく10.13.6です(参考情報(1)によるとこの事象は10.13.4〜6で発生するらしいです)

  2. 詳細には立ち入りませんが、High Sierra以降のファイルフォーマットです

Django Girls Tutorial ExtensionsをDjango2系で動かす(Part 1/3) #モグモグDjango

はじめに

いつも心は虹色に! nikkieです。
2018/11/10に参加した #モグモグDjango で、Django Girls Tutorial Extensions がDjango2系で動作するように確認しました。
ExtensionsをDjango 2系で動かす中で気づいたことをアウトプットします。

勉強会の概要

akiyokoさんの『現場で使えるDjangoの教科書』頒布をきっかけに始まった、Djangoもくもく会です。
第3回 モグモグDjango - connpass

Djangoもくもく会 モグモグDjango を開催します. Django初心者の方から,上級者の方までどなたでもご参加下さい(^^)

この会は,しーーっんとしているもくもく会ではなく,質問や分からないところがあったら,その場で聞くことができる環境にしたい!と思っています.

取り組んだこと

Django Gitls Tutorial(Djangoでブログアプリを作るチュートリアル)にはExtensionsという拡張版があります。
Introduction · Django Girls Tutorial: Extensions
9月のPyConJP Sprintにて有志で翻訳したのですが、ExtensionsはコードがDjango 1系ということが発覚していました。1
GitHub - DjangoGirlsJapan/tutorial-extensions: Additional tasks for tutorial (翻訳はWIP、また未レビューです)
Extensions翻訳を完了させるために、コードをDjango 2系に置き換えたいとメンバー間で考えており、今回のもくもく会で着手しました。

達成したこと

Django 2系に書き換える対象は、3ページあります。

このうち、機能追加とセキュリティについてDjango2系で動作確認できました

以下では、機能追加のパートを進める中で気づいたことを書いていきます。(セキュリティについては記事を分けます)

ブログアプリに機能追加

このパートで追加する機能は、大きく分けて3つです。

  • ドラフト(下書き)の一覧機能
  • ドラフトを公開する機能
  • 記事を削除する機能

前提

以下の環境で動かしています。

なお、機能追加のチュートリアルは、9月から11月までの間にコードがDjango2系に更新されていました。(確認しやすかったです。ありがとうございます!)

Djangoの機能追加手順

これまで手を動かしてきた経験を踏まえると、機能追加するには以下の順がよさそうです。2

  1. 新規ページへ遷移するリンクを追加
  2. 新規ページのURL設定
  3. 新規ページのビュー作成
  4. 新規ページのテンプレート作成

Djangoは機能追加する際に触る箇所が多いので、「機能追加手順のチェックリストを持つと、使いやすく感じられるかな」と考えています。

ドラフトの一覧機能

まず、ドラフト一覧画面に遷移するアイコンをヘッダーに追加します。
(記事が作成できるのはログインしているユーザのみとしていたので、ドラフトが見えるのもログインしているユーザに限定しています)

blog/templates/blog/base.html

<!-- 省略 -->
  <div class="page-header">
    {% if user.is_authenticated %}
      <a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
      <a href="{% url 'post_draft_list' %}" class="top-menu"><span class="glyphicon glyphicon-edit"></span></a> <!-- 追加 -->
    {% endif %}
    <h1><a href="/">Django Girls Blog</a></h1>
  </div>
<!-- 省略 -->

次に、ドラフト一覧画面のURLを追加します。

blog/urls.py

urlpatterns = [
    # 省略
    path('drafts/', views.post_draft_list, name='post_draft_list'), # 追加
]

ビューの編集では2つのことを行います。

1つ目は、記事を作成・編集したときにpublished_dateを設定しないようにすること。
これにより、作成した記事が即時公開されなくなり、ドラフト扱いとすることができます。

  • 新規作成した場合、published_dateは空(ドラフト状態)
  • ドラフトの記事を編集した場合、published_dateは空のまま(ドラフトのまま)
  • 既に公開した記事を編集した場合、published_dateの値は変わらない(公開されたまま)

2つ目は、ドラフトの記事の一覧を表示するための関数を追加すること。
ドラフトの記事はpublished_datenullです。

blog/views.py

def post_new(request):
    if request.method == "POST":
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            # post.published_date = timezone.now() # 削除
            post.save()
            return redirect('post_detail', pk=post.pk)
    else:
        form = PostForm()
    return render(request, 'blog/post_edit.html', {'form': form})

def post_edit(request, pk):
    post = get_object_or_404(Post, pk=pk)
    if request.method == "POST":
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            # post.published_date = timezone.now() # 削除
            post.save()
            return redirect('post_detail', pk=post.pk)
    else:
        form = PostForm(instance=post)
    return render(request, 'blog/post_edit.html', {'form': form})

# 以下を追加
def post_draft_list(request):
    posts = Post.objects.filter(published_date__isnull=True).order_by('created_date')
    return render(request, 'blog/post_draft_list.html', {'posts': posts})

最後に、ドラフト一覧のテンプレートを作成します。

blog/templates/blog/post_draft_list.html

{% extends 'blog/base.html' %}

{% block content %}
  {% for post in posts %}
    <div class="post">
      <p class="date">created: {{ post.created_date|date:'d-m-Y' }}</p>
      <h1><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h1>
      <p>{{ post.text|truncatechars:200 }}</p>
    </div>
  {% endfor %}
{% endblock %}

このテンプレートには2つのフィルタが登場します。

  • date
    • 指定したフォーマットで日付を表示するフィルタ
    • d-m-Y:日(2桁)-月(2桁)-年(4桁)
  • truncatechar
    • 文字列の後ろを切り捨てて、指定した長さ(ここでは200文字)とするフィルタ
    • 切り捨てた文字列は...と3文字で表されるので、post.textの先頭から197文字が取り出される
    • ドキュメント記載の例 {{ "Joel is a slug"|truncatechars:9 }}Joel i...Joel iの6文字+...の3文字で合計9文字)

ここまでで、ドラフトボタンからドラフト一覧画面に遷移できます。
f:id:nikkie-ftnext:20181110195137p:plain

ドラフトを公開する機能

まず、記事の詳細画面にドラフトを公開するボタンを作ります。
(公開されていない記事=ドラフトの場合のみ、公開ボタンが見えるようにしています3

blog/templates/blog/post_detail.html

    {% if post.published_date %}
      <div class="date">
        {{ post.published_date }}
      </div>
    {% else %} <!-- 追加 -->
      <a class="btn btn-default" href="{% url 'post_publish' pk=post.pk %}">Publish</a> <!-- 追加 -->
    {% endif %}

次に、ドラフト公開に使うURLを追加します。
Extensionsの原文のまま('post/<pk>/publish/')でもビューのget_object_or_404は動きましたが、チュートリアル本編のURLの設定に合わせて'post/<int:pk>/publish/'としています。4

blog/urls.py

urlpatterns = [
    # 省略
    path('drafts/', views.post_draft_list, name='post_draft_list'),
    path('post/<int:pk>/publish/', views.post_publish, name='post_publish'),  # 追加
]

最後にビューにpost_publish関数を追加します。

blog/views.py

def post_publish(request, pk):
    post = get_object_or_404(Post, pk=pk)
    post.publish()
    return redirect('post_detail', pk=pk)

追加した関数で使われているpublishメソッドですが、これは Djangoモデル · Django Girls Tutorial で定義したものです。
Extensionsにて、伏線がようやく回収されました!

記事を公開した後は記事詳細にリダイレクトするので、新規で作成するテンプレートはありません。

以上で、ドラフト公開ボタンが付きました!
f:id:nikkie-ftnext:20181110195249p:plain

記事を削除する機能

記事の削除機能の追加は、ドラフト公開機能と同様の流れです。

記事の削除ボタンが見えるのは、ログインしているユーザのみです。

blog/templates/blog/post_detail.html

    {% if user.is_authenticated %}
      <a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
      <a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a> <!-- 追加 -->
    {% endif %}

削除機能の場合も、URLの設定はチュートリアル本編の記載に合わせています。

blog/urls.py

urlpatterns = [
    # 省略
    path('drafts/', views.post_draft_list, name='post_draft_list'),
    path('post/<int:pk>/publish/', views.post_publish, name='post_publish'),
    path('post/<int:pk>/remove/', views.post_remove, name='post_remove'),  # 追加
]

blog/views.py

def post_remove(request, pk):
    post = get_object_or_404(Post, pk=pk)
    post.delete()
    return redirect('post_list')

deleteDjangoモデルが持っているメソッドだそうです。

こうして、記事が削除できるようになりました!
f:id:nikkie-ftnext:20181110195316p:plain

感想

Django Girls Tutorialの懇切丁寧な解説から方向転換し、Extensionsは「気になるところは自分で調べてね」という感じです。(独り立ちを意識しているのかもしれません)
ファイルの変更箇所を明確にする意図でこの記事は詳しく書いていますが、実際に手を入れる箇所はそんなに多くはありませんでした。
下書き機能もついて、ブログアプリの機能が充実してきて嬉しい限りです^ ^

教えていただいたもの

今回アウトプットが遅くなってしまいましたが、モグモグDjango参加者、運営者の皆さま、どうもありがとうございました!
Extensionsはperfectじゃなくてもいいので、なる早でdoneに持っていく所存です。

脚注


  1. path関数ではなくurl関数が使われていたため、発覚しました。

  2. 参照 週末ログ | Django Girls Tutorial翻訳レビュー 100%到達! - nikkie-ftnextの日記 なお、機能追加にモデルが必要な場合は作成が必要です。(ビューの前に作ることになると思います)

  3. ブログを書いていて気づいたのですが、Extensionsのとおりに進めると、ログインしていないユーザでも公開できてしまうみたいですね。セキュリティのパートを終えると、ログインしているユーザだけが公開できるようになりました

  4. 原文のまま('post/<pk>/publish/')だとstrのpk(例:'1')でget_object_or_404が動きます。'post/<int:pk>/publish/'とすると、intのpk(例:1)がget_object_or_404に渡ります。

Event report | Python Web Day (additional track in #ploneconf2018 )

はじめに

いつも心は虹色に! nikkieです。
手伝っていたPlone Conf 2018併設イベント「Python Web Day」は全プログラム終了しました。
英語も織り交ぜてレポートブログに挑戦します。

Hello, Everyone! This is nikkie.
"Python Web Day" has finished all programs.
I try to write the report in Japanese and English.

前提(About nikkie)

  • ソフトウェアエンジニア3年目 (3rd year software engineer)
  • Pythonでは半年程度のWeb開発の経験あり (web development with Python about half of a year)
  • Ploneは未経験(先日vagrantで環境構築してみました)(novice about Plone. I tried creating an environment with vagrant)

  • 英語は読むことが多く、話そうとすると言葉に詰まりがちです。(I often read English. I do not speak and write much)

多くの方の力を借りて、併設イベントの手伝いをやりきれました。
深くお礼申し上げます。
With the help of many people, I was able to run Python Web Day.
Thank you very much, especially @terapyon, @takanory, @mamix1116, @kaizumaki.

イベントの概要 (About Python Web Day)

Python製のCMS Ploneについての国際カンファレンスです。
海外からの参加者に日本のエンジニアの活動を知ってもらい、交流するという狙いで併設イベントも開催されました。
Python Web Day」はWebについて話す併設イベントです。 @mamix1116さん(Django Girlsのオーガナイザー)のサポートとして、10月から手伝っていました。

#ploneconf2018 is an international conference about Plone.
We have additional tracks so participants from overseas can know activities of engineers in Japan and interact with each other.
Python Web Day is an additional Track on 7 Nov.
I was helping in the operation from October as a support of @mamix1116, the organizer of Django Girls in Japan,

オープニング

「どこから来ましたか」で盛り上がりました。
多くの方がヨーロッパから来られていて驚き!
また、多くの方が4回以上参加されているそうです。

It got excited at the topic "Where did you come from?"
So many people came from Europe!
And many people have participated more than 3 times!

Keynote: THE STATE OF PLONE

Zopeゴジラ、「Difficult to Kill」で会場大爆笑でした。
A huge laugh happened at the topic Zope = Godzilla, "Difficult to Kill".

バトンタッチしたPaulさん(Plone FoundationのChair)からPython Web Dayモデレータとして紹介いただくという素敵なサプライズもありました!
There was also a nice surprise that Paul introduced @mamix1116 and me as moderators of Python Web Day!

カンファレンス本編のトークは後ほどYouTubeに上がるそうです。
The conference talks will be uploaded to YouTube later.

以下、Python Web Dayのトークを紹介します。
I introduce talks of Python Web Day.

Build a RESTful API with the Serverless Framework

@masahitoさんによるトークです。

  • AWSではAWS API GatewayAWS LambdaでAPIを作れる(We can create a API in AWS with AWS API Gateway and AWS Lambda)
  • Serverless Frameworkを導入すると1コマンドでデプロイできる(We can deploy with 1 command using Serverless Framework)
  • プラグインを使うとデプロイしやすくなる(Plugins of Serverless Framework make deploy easier)

Azure Functionsで使ってみたいと思いました。
I want to try Serverless Framework with Azure Functions.

Building a REST API with Django and Django REST Framework

@checkpointさんによるトークです。

  • REST APIを一から作るのは大変なので、フレームワークを使う(It is hard to create a REST API from scratch, so we use a framework)
  • Django REST Frameworkを使いこなすにはSerializerが肝」と感じた(It seems for me that Serializer is important to master Django REST Framework)

Powerful geographic web framework GeoDjango

@omegaさんによるトークです。

GeoDjangoは聞いたことはありますが、触ったことはありません。
確かに地理情報を扱いやすそうです。
I have heard of GeoDjango, but I have never touched it.
It certainly seems easy to handle geographic information.

@mamix1116さんからも話を聞くことが多いので、この機に触ってみようと思います。
I will try the tutorial that I taught. (@mamix1116 loves GeoDjango)
GeoDjango Tutorial | Django documentation | Django

Sphinx customization for OGP support

@shimizukawaさんによるトークです。

Sphinx ExtensionでのOGPタグの生成ロジックを聞いて、少しOGPの理解が深まったと感じています。
I feel that my understanding of OGP has improved a bit, listening to the generation logic of OGP tags in Sphinx Extension.

Sphinxつながりで、LTにて紹介された:linenos:なども試してみたいです。
I'd like to try :linenos: introduced in LT about Sphinx.

How to make the fastest Router in Python

GitHub - kwatch/router-sample: sample Router classes in Python

@makotokuwataさんによるトークです。

  • Linear search is slow
  • Regex search is fast(ただし工夫は必要 But need some ingenuity)
  • State Machine approach is the fastest

ルータを早くするために、計算コストが小さい処理で実装するという観点は勉強になりました。
I was glad to hear about implementation with processing with a small calculation cost (for fastest router).

Micro Service Architecture with Machine Learning Application

GitHub - Swall0w/microservice-ml-demo: Micro service architecture using rest API

  • モデルをデプロイしやすくために、Flaskアプリケーションから切り出す(Separate a model from a Flask application to make deploy easier)
  • クライアントとFlaskアプリケーション間はREST API (REST API is used between a client and the Flask application)
  • FlaskアプリケーションとML Model間がgRPC (gRPC is used between the Flask application and the model)

終わりに

最後までお読みいただきありがとうございました。
今後トークのメモのリンクを追加します。(イベント準備総括ブログも書く予定です)
英語の表現に不自然なところがあったら教えていただけると嬉しいです。

Thank you for reading.
I will add a talk note link later. (I'm also planning to write an event preparation summary blog.)
I would be happy if you could tell me if there are unnatural English expressions.

イベントレポート | 第93回 #pyhack にて #ploneconf 併設イベント準備を進めました

はじめに

いつも心は虹色に! nikkieです。
定期的に参加している #pyhack で、Plone Conf 併設イベント Python Web Day の準備に取り組みました。

勉強会の概要

(第93回)Python mini Hack-a-thon - connpass

スプリントのゆるい版みたいな感じで各自自分でやりたいことを持ってきて、勝手に開発を進めています。参加費は無料です。 初めての方も常連さんもぜひご参加ください。

今回はいつもより人数が少なめでこぢんまりとした雰囲気でした。
常連が少ないのと対照的に初参加の方が多かったです。

なお、裏番組としてオープンソースカンファレンスがありました。(Plone Confのアピールも行われたそうです)
オープンソースカンファレンス2018 Tokyo/Fall - オープンソースの文化祭!

Plone Conf 情報まとめ

2018/10/14からのアップデートをまとめておきます。

カンファレンスの併設イベントは

  • 11/7:Python Web Day
  • 11/8:Database Day
  • 11/9:Frontend Day

です。
「ちょっと興味あるかも」という方、国内開催のまたとない機会です!
ぜひご来場ください。

11/5のイベントのトピックの一つ、ヘッドレス(頭がない)からGuillotina(ギロチン)だそうです。(一本取られた)

取り組んだこと

併設イベントについて、海外からの参加者に周知するためのスライドのドラフトを作成しました。
(pyhackで作成したものを別リポジトリに切り分けました。10/29-週でアップデートしていきます)

キーノートの後に少し時間をいただいて併設イベント「Python Web Day」についてお知らせします。
内容は

  • 併設イベントがあることを紹介(11/7はPython Web Day)
  • Python Web Dayの狙いを共有
  • Python Web Dayのトークラインナップを紹介

です。
私自身英語でのトークはほとんど経験がないのですが、可能な限り準備して臨みます。

移動時間に部屋の前で呼び込みに使うスライドや、タイムキープに使うスライドのドラフトも準備しました。

他の方の取り組みから

感想

今回も非常に楽しい時間でした。
今回は懇親会まで参加したのですが、笑い話から考えさせられる話まで盛りだくさんであっという間でした。
転職して感じていることには別の見方があるということを、懇親会という思いもよらないタイミングで気づいたのが一番の収穫です。
1日ありがとうございました!

Plone Con併設イベント(Python Web Day)の準備を手伝っています #ploneconf

はじめに

いつも心は虹色に! nikkieです。
先週くらいからPlone Conの併設イベント準備を手伝っています。
イベントが盛り上がることを願って、準備のプロセスをブログに残します。

Plone Conとは?

Ploneとは、Python製のCMSと理解しています。
WordPressPython版というイメージ)
詳しくは知らないので、今後触ってみます。

Ploneの国際カンファレンスが今年は日本で開催されます。
https://2018.ploneconf.org

11/5(月)〜11(日)の1週間、東京でPlone Conferenceが行われます。

  • 11/5-6:Training
  • 11/7-9:Talks
  • 11/10-11:Sprint

会場はpyconjpと同じ「大田区産業プラザPiO」です。
(注意:Sprintは会場が違うようです。詳しくはPlone Conのページでご確認ください)

11/7(水)〜9(金)のTalkの裏で、併設イベントが企画されています。

  • 11/7:Python Web Day
  • 11/8:Database Day
  • 11/9:Frontend Day

私が手伝っているのが、11/7のPython Web Dayです。
Frontend Day担当の方の情報発信に触発され、私も発信することにしました。
Frontend Day ビルドダイアリー を始めます|Kazuhiro Hara.|note

併設イベント:Python Web Day

併設イベントの狙いは、「日本からの参加者を呼び込み、Plone Conを盛り上げる」ことです。
カンファレンス自体は1週間ですが、併設イベント用に1Dayチケットが用意されます。
併設イベントに惹かれた方は是非ご参加いただければと思います。
(参加はWeb Dayでなくても構いません。Plone Conが盛り上がるのが何より嬉しいです)

カンファレンス本編のトークに併設イベントのトークトラックを追加するイメージです。
(カンファレンス本編と併設イベントを行き来できるようにする)

私は「Webって広いなー」と感じているので、Webの広がりをお届けできるようにスピーカー候補の方にお声がけしています。
こんなトークが聞けるように準備しています。

併設イベントのトークは「Ploneを扱っていなくてもOK!」です。
海外からPlone Conに来られた方に、日本のPythonistaの活動のありのままを知っていただこうという意図です。
(そこから何か新しいものが芽生えたら素敵ですね)
スピーカー候補の皆さま、お力をお貸しいただけると大変助かります!

動いているメンバー

  • @takanoryさん(pyhackでお世話になっています)
  • @mamix1116さん(Django Girlsでお世話になっています)
  • nikkie

登壇者募集中!

話したいことがある方はお気軽にご連絡ください。
トークにあたって、以下のお願いがありますので、連絡前にご確認ください。

  • スライドは英語でお願いします
  • トークは英語で挑戦していただけると嬉しいですが、日本語でもOKです
  • 恐れ入りますが、Plone Con 1日分の参加費が発生します。(1万円程度の1Dayチケットが用意されると聞いています)

トークは20分枠(6枠予定)と40分枠(2枠予定)で用意しています。
(40分の枠が5つあり、40分枠をいくつか分割することにしました)

日本にいながらにして国際カンファレンスで登壇できる機会です。
英語での登壇に挑戦してみたいという方いらっしゃいましたら、私宛にTwitter DMでお気軽にお問い合わせください。

最後までお読みくださりありがとうございました。
この記事を読んで併催イベントに登壇してくださる方やPlone Conにいらしてくださる方がいたら、それ以上に嬉しいことはありません。
国際カンファレンスの準備に関われるなんてめったにないことだと思うので、準備を楽しんでいきます!

イべントレポート | 横浜のDjango Girls Workshopでコーチデビューしました #djangogirlsyokohama

はじめに

いつも心は虹色に! nikkieです。
2018/10/06に横浜のDjango Girls Workshopでコーチをしてきました。
とても楽しい一日だったというのと、Django Girlsの取り組みがますます広がることを願って、イベントレポートを残します。

勉強会の概要

これからWebサイトの作り方を学びたい、プログラミングを学びたいと思っている女性のみなさん、初心者向けの1-Dayワークショップを開催します!

このブログでもたびたび取り上げていますが、2018年5月からDjango Girls Tutorial翻訳に参加してきました。
Tutorialを数周したことで、「次は教えるという形で手伝えるんじゃないか」と考え、コーチに手を挙げました。

上記サイトの会場までの地図が非常にわかりやすく、方向音痴な私は大変助かりました!

イベントレポートお品書き

  • コーチをやってみて
  • Pythonを始める方に伝えたいこと
  • コミュニティに関わるということ

コーチをやってみて

  • はじめてプログラミングされる方のコーチをした
  • 意外なつまづきポイント:エディタ
  • 私の理解が進んだこと:関数とメソッド

はじめてプログラミングされる方のコーチをした

はじめてプログラミングされる島(3名)を担当しました。(コーチは2人体制)
夕方はコーチを増員して1:1の体制を取り、全員Djangoに触ることができました!
プログラミング未経験で、1日で以下の3つをやりきるというのは本当に素晴らしいです。
チュートリアルにもある表現ですが、「自分で自分を褒めてあげて」ください!

  1. コマンドプロンプトに慣れる(普段はマウス操作)
  2. Pythonに入門する
  3. DjangoでWebサイトを動かす(開発用Webサーバを動かし、管理画面から記事を書くところまでは全員進められたと思います)

意外なつまづきポイント:エディタ

Python入門でエディタからインタプリタに切り替えるところで難しく感じることがわかりました。
Python入門 「保存しよう!」
エディタでの開発に慣れている身にとっては新鮮な気づきでした。

AtomPythonを書いて保存し、コマンドプロンプトでファイルを実行するのですが、腹落ちするのが難しい箇所のようです。

コマンドプロンプトの役割が「Pythonを書くところ」から「Pythonを実行するところ」に変わり、Atomという「Pythonを書く」役割の新しい登場人物が出てくるからかと思います。

私の理解が進んだこと:関数とメソッド

Python入門 「文字列」から

「関数とメソッドはどう違うんですか?」という質問、回答がなかなか難しかったです。

  • 関数は「異なるタイプのオブジェクトに」適用できる(=複数のオブジェクトに適用できる)
    • len()関数はstrlistに適用できる(適用できないオブジェクトもある:例えばint
    • str()関数はintfloatに適用できる
    • 一番わかりやすいのはprint()でしょうか
  • メソッドは特定のオブジェクトに限って適用できる
    • "Ola".upper()のようにオブジェクト.メソッド名()という書き方になる
    • intオブジェクトのメソッドには、例えば、int.bit_length() というものがある

答えにくかったのは、オブジェクトの理解が甘いためと考えられるので、次回までにPythonチュートリアルを確認します。

Pythonを始める方に伝えたいこと

10/5のインストールDayの交流タイムから、「Pythonをはじめたときに作ったものを紹介できるのでは」と気づき、再演という形でLTさせていただきました。

伝えたいこと

  • Python(プログラミング)はWebサイトを作る以外にもいろいろなことができる
  • 私の場合、どんなことができるか知る上で『退屈なことはPythonにやらせよう』が役に立った(画像処理のほか、PythonからExcelを触るようなことも紹介されている)

公開されている原文をGoogle翻訳することで、日本語でも読めると思います。
Automate the Boring Stuff with Python

11月の東京開催に向けて、「プログラミングを始めた方に共有したいこと」としてLTを準備してみます!
始めた後はいかに継続するかだと思うので、継続する上で私が学んだこと・大切にしていることを共有予定です。

コミュニティに関わるということ

「コミュニティに関わってよかった」と感じたすばらしい1日でした。

ワークショップでは、初めてプログラミングされる方が、1日でDjangoを触る姿を見て感銘を受けました。
翻訳したTutorialに目の前で取り組んでいただき、直接フィードバックもいただけて感無量でした!

懇親会はさまざまな年代の方が入り混じり、たくさんの興味深いお話が聞けました。
今後の展開などさまざまなアイデアがうごめいていて、「なんだか素敵なことが始まろうとしている」という高揚感でいっぱいでした。
コミュニティ活動をしてみて、「カイゼン・ジャーニーで言うところの『1人の限界を超える』ってこういうことでもあるのかな」と感じました。

また、コーチのミヤモトさんのお知り合いが私に興味を持ってくださっているそうです!
Django Girlsとは別なのですが、「あにべん!」でアニメから学んだことLTをしたのがきっかけで、興味を持ってくださったと知り、大変うれしく思います。
もしこの記事を読んでくださっていたら、遠慮なくDMなど飛ばしていただければ、お会いする時間を設けたいなと思います。

終わりに

私自身はすごく素敵な1日を過ごすことができ、参加者、コーチ、運営の皆さまに心からお礼申し上げます。
素敵な1日をありがとうございました。
そして、参加された他の方にとっても素敵な1日だったのであれば、こんなにも嬉しいことはありません。

知識を補い、LT準備をし、次回の東京ワークショップに備えます。

最後までお読みいただきありがとうございました。
Django Girls Tutorial 日本語版へのフィードバックや、Django Girlsの活動への参加やご支援をいただけましたら、幸甚に存じます。