Self-Curation

新卒社会人で営業マンになりました

Laravel#2 ユーザー情報と認証機能の実装(7.x)

f:id:scuration:20200802232227p:plain

「あるユーザーの投稿一覧を表示する」機能を実装したい。

すると後から実装するくらいなら、先に実装した方が応用利くのではないかと思って序盤からいきなり取り組もうと考えた次第です。

そのためにはまずユーザー情報のテーブルが必要、ですので今回はユーザー情報テーブルとついでに認証機能を追加したいと思います。

続きを読む

Laravel#1 XAMPPを使った環境構築

f:id:scuration:20200802232227p:plain

これまでRailsDjangoを触ってきましたが、PHPの方が最終的にサーバーの選択肢も多いのではないかと思って乗り換えた次第です。


オリンピックの影響もあって(新型肺炎の影響でなくなりましたが)7月23日からは4連休でしたね。
社会人になると中々自分の時間が取れないこともあって0から何か学ぶのって結構大変なんです。


私は4連休をLaravelのインプットに費やしました。
今も学習を継続しておりますが、基本的なところからアウトプットにしていき少しでも誰かの役に立てればと存じております。

続きを読む

#Django2 リダイレクトページを挟んで投稿時に任意の処理を行う

f:id:scuration:20200607213312p:plain

前回の記事ではDjangoの汎用ビューを使って投稿フォームを簡単に作成できました。

シンプルな機能であれば汎用ビューは他言語・フレームワークにはない便利なものです。

しかしその分融通が利かないデメリットがあるとも感じています。

例えば「投稿と同時にデータベースに任意の処理を加えたい」という場合です。

今回は任意の処理を行うためのリダイレクトページを挟むことによる解決策を書いていきたいと思います。

関数とは

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world!")



上記のようなdefから始まるものは関数と呼ばれるものです。
こちらのサンプルコードの場合、urls.pyで設定した上でexample.com/indexにアクセスすると「Hello World」を返すものとなっております。

投稿と同時処理はできなさそう


defから始まる処理は基本的にページが読み込まれた段階で処理されます。

なので「投稿フォームのメールアドレスを継承→メールアドレスから固有のパラメータを作成→送信したデータと一緒にデータベースに保存」といったことは難しそうです。

ただしリダイレクトページにパラメータを継承することは簡単なので、今回はその方法を試したいと思います。

リダイレクトページの生成

フォーム送信後にリダイレクトページに飛ぶにはViewを以下のように記述します。

from django.urls import reverse_lazy
from django.views.generic import CreateView
from .models import PostModel

class NewReviewClass(CreateView):
    template_name = 'newreview.html'
    model = PostModel
    fields = ('title','url','comment',)    

    def get_success_url(self):
         return reverse('redirect', kwargs={'pk': self.object.id})

ポイントはget_success_urlの関数です。
''で囲まれているredirectは後程urls.pyで設定する名前で、保存された各データに割り振られるid(プライマリーキー)を'pk'として継承。

urls.pyでは以下のようにリダイレクトページのパスを指定します。

path('redirect/<int:pk>', redirect, name='redirect'),

name=はget_success_urlの値と合うようにredirectにします。
これでexample.com/redirect/PK(プライマリキー)のページが自動的に生成され、遷移します。

リダイレクトページにデータ継承

from django.urls import path
from django.conf.urls import url
from .views import NewReviewClass
from .views import redirect

urlpatterns = [
    path('newreview/', NewReviewClass.as_view(), name='newreview'), 
    path('redirect/<int:pk>', redirect, name='redirect'),
]

urls.pyについては上記のような感じになると思います
path()の中にある2番目のredirectは実際に生成されたリダイレクトページに対応するviewを指定します。

from django.urls import reverse_lazy
from django.views.generic import CreateView
from .models import PostModel

class NewReviewClass(CreateView):
    template_name = 'newreview.html'
    model = PostModel
    fields = ('title','url','comment',)    

    def get_success_url(self):
         return reverse('redirect', kwargs={'pk': self.object.id})

def redirect(request, pk):
    return render(request, 'redirect.html', {'id': id})

これで「フォーム送信→フォームのデータを継承したリダイレクトページに飛ぶ」という流れは出来ているはずです。

DJagno#1 とりあえず投稿フォームを作成する

f:id:scuration:20200607213312p:plain

Djangoを弄って1ヶ月くらいになります。

MVCとかMTVモデルとか出てきますが概念の理解に努めるより、コピペでも実際にコードを書いて動かしてみた方が早い気がします。

その点Djangoでフォームを作成することは、MTVモデルの理解にもってこいなのではないかと思ったので今回書かせていただきました。

【目次】

プロジェクトとアプリの作成

$ django-admin startproject mysite

$ python manage.py startapp form


任意の名前でプロジェクト→アプリの順にプリセットを作成しましょう。

scuration.hateblo.jp

環境構築~アプリ作成までは以前の記事で解説しているので、こちらご参照いただければと思います。

今回はmysiteというプロジェクトを作成して、その中にformという名前のアプリを作成しました。

編集するファイル

簡単なフォームを作成して動作させるために必要なファイルを先に列挙しておきます。

mysite
│  asgi.py
│  settings.py
│  urls.py
│  wsgi.py
│  __init__.py
│
└─__pycache__

プロジェクトフォルダの以下ファイルが編集対象です。

setting.py
urls.py

■アプリ
models.py
views.py
url.py

プロジェクトファイルの編集

setting.py

setting.pyを開いてINSTALLED_APPSの項目に先ほど作成したformアプリを記述します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
#追加
    'form',
]

このように記述しておかなければユーザーが作成したアプリが認識されません。

ついでに同ファイルのTEMPLATESという項目も御覧ください。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR, 'templates'],
        'APP_DIRS': True,
        #…(省略)
    },
]

DIRSの箇所は初期設定で空白([])となっているので「BASE_DIR, 'templates'」と足しておきましょう。
これはテンプレートファイルを呼び出すときにどこを捜索するか指定するもので、空白だと捜索が行われません。
後ほどプロジェクトフォルダのディレクトリに「templates」という名前でテンプレートフォルダを作成します。

urls.py(アプリ間ルーティング)

setting.pyと同フォルダにあるurls.pyを開いてください。
ここではルーティングを行います。

例えばexample.com/formapp/form.htmlというURLにアクセスしたとき、formアプリフォルダを参照するように設定する必要があります。

from django.urls import path , include

urlpatterns = [
     path('admin/', admin.site.urls),
     path('formapp/', include('form.urls')),
]

まずfrom django.urls import pathとなっている場合はincludeを追加してください。
ちなみにこの「from ~ import XX 」というのは「~という場所からXX関数を呼び出して使用可能にする」記述です。

そしてurlpatternsにpath('formapp/', include('form.urls')),を追加します。
example.com/formapp/にアクセスするとそれ以下のディレクトリはformアプリ内のurl.confに処理を任せるようになります。
このように特定のディレクトリで処理に用いるurl.confを変更可能にするのがinclude関数です。

アプリディレクトリ内の編集

modelsの記述

modelとはデータベースを定義するものです。

「投稿フォームから送信された内容を保存する箱を作る」
もしデータベースが分からなくてもこのようにイメージ持ってもらえればと思います。

from django.db import models

class PostModel(models.Model):
    title = models.CharField(max_length=50)
    content = models.TextField()

それではmodels.pyを開いてください。

今回はタイトルと内容だけの投稿フォームを作成予定なので、上記のようなクラスを作成しました。
クラス名のあとに続く(models.Model)とは継承元クラスを指しております。

viewsの記述

MTVモデルのMとTまで記述できました。
あとはviewファイルです。

form\views.pyを開いて以下のように記述します。

from django.views.generic import ListView, CreateView
from django.urls import reverse_lazy
from .models import PostModel

class ListClass(ListView):
    template_name = 'list.html'
    model = PostModel

class FormClass(CreateView):
    template_name = 'form.html'
    model = PostModel
    fields = ('title','content')
    success_url = reverse_lazy('list')

他より長くなりますが1個1個説明していきます。

まずインポートした関数について。

from django.views.generic import ListView, CreateView
まず新規投稿においてはCreateView、投稿一覧表示にはListViewという汎用ビューを使用します。

from django.urls import reverse_lazy
投稿後にリダイレクト先を指定できます。

from .models import PostModel
models.pyで作成したモデルも読み込んでおかないとデータの受け渡しができません。

次に作成したクラスについて。

class ListClass(ListView):
汎用ビューを使用する場合は継承します。

template_name = 'list.html'
viewファイルを裏側で処理する部分だとすれば、対応する表側のテンプレートファイルを指定する必要あり。

success_url = reverse_lazy('list')
投稿に成功(データベースへの保存)したときの遷移先を指定します。

urls.pyの記述(アプリ内ルーティング)

最後にアプリファイル内のurls.pyを設定します。
プロジェクト(mysite)内のフォルダにあるurls.pyでは、example.com/formapp/以下にアクセスされた場合にform\urls.pyに振る設定を行いました。

こちらのurls.pyは自分で作成する必要があるので、form\urls.pyに作成しましょう。

from django.urls import path
from .views import FormClass, ListClass

urlpatterns = [
    path('form/', FormClass.as_view(), name='form'),
    path('list/', ListClass.as_view(), name='list'),
]

任意のパスを設定し、viewに記述されたどのクラスと対応するのか記述します。
記述したクラスについてはimport関数で呼び出しておく必要ありです。

ちなみにviews.pyでsuccess_url = reverse_lazy('list')と出てきましたが、ここでname='list'と記述することによって名前で呼び出せるようになっていたのです。

templateの記述

urls.pyの項目でテンプレートファイルの参照先にtemplatesフォルダを指定しました。
以下のようにmysite\templetesを作成し、テンプレートファイルform.htmlとlist.htmlを作成します。

mysite
│  manage.py
│
├─form
│  │  admin.py
│  │  apps.py
│  │  models.py
│  │  tests.py
│  │  views.py
│  │  __init__.py
│  │
│  └─migrations
│          __init__.py
│
├─templates
│      list.html
│      form.html
│
└─mysite
    │  asgi.py
    │  settings.py
    │  urls.py
    │  wsgi.py
    │  __init__.py
    │
    └─__pycache__

form.htmlに投稿画面、list.htmlに投稿一覧の内容をそれぞれ記述します。

投稿画面

作成したform.htmlをエディタで開き以下のように記述してみましょう。

<form method="POST">
{% csrf_token %}
  <p>タイトル:<input type="text" name="title"></p>
  <p>内容:<input type="text" name="content"></p>
  <input type="submit" value="投稿する">
</form>

htmlの話になってしまうのですが、formタグと呼ばれるものを記述しました。
formタグの中にinput typeなどの要素を配置して簡単に入力フォームを作成できます。

{% csrf_token %}の記述は、CSRF(クロスサイトリクエストフォージェリ)という脆弱性を狙った攻撃を防ぐセキュリティ対策の記述です。

余談ですがmethodにはPOSTやGETが存在します。前者はDBの変更を伴うもの、後者は読み取り専用で使われることが多いようです。

投稿一覧

次にlist.htmlを以下のように編集しましょう。

<div class="container">
  {% for post in object_list %}
  <div class="post">
    <p>タイトル:{{ post.title }}</p>
    <p>内容:{{ post.contant }}</p>
    <p>--------------------</p>
  </div>
  {% endfor %}
</div>

何が書かれてあるかというと「POSTモデルから全投稿のタイトルと内容を表示する」というものです。
djangoではデータベースのデータを{{ }}で囲んで記述することで、テンプレートに表示させることが可能です。

マイグレーションを行う

さて、必要なファイルは揃えたのであとはプログラムを実行します。

その前にマイグレーション作業を行わなければなりません。
マイグレーションとは簡単に言うとモデルの変更などをデータベースに反映させることです。

$ python manage.py makemigrations
$ python manage.py migrate

ローカルサーバーでテストする前に上記2つのコマンドを実行しておけば大丈夫です。

ローカルサーバー起動

$ python manage.py runserver

localhostを実行しhttp://127.0.0.1:8000/formapp/formへアクセスします。
(今回はトップページを設定していないので)

するとこのようなフォームが表示されるのではないでしょうか。
f:id:scuration:20200712233145p:plain

投稿するとこのように投稿一覧画面に遷移するはずです。
f:id:scuration:20200712233218p:plain


=====

こんな感じでしばらくDjangoに関する記事を上げていければと思います。

どなたかの参考にでもなれば幸いです。