2017年4月27日木曜日

Djangoチュートリアルの続き

前回からの続き。

下記のDjangoチュートリアルでやったことの続きを書いて行きます。
Django Girls Tutorial

今回はurlsからのやったことメモをだらだらと。

urlsの設定 ---------------------------------------------------------------------
mysite/urls.pyを編集(このurlsには各アプリをインポートするだけにして簡潔にする)
    from django.conf.urls import include, url
    from django.contrib import admin

    urlpatterns = [
        url(r'^admin/', include(admin.site.urls)),
        url(r'', include('blog.urls')),
    ]

blog/urls.pyを作成編集(blog/view.pyに記述がないのでこの時点ではサーバーが起動しなくなる)
    from django.conf.urls import include, url
    from . import views
    urlpatterns = [
        url(r'^$', views.post_list),
    ]

blog/views.pyの編集
$ vi blog/views.py
    def post_list(request):
        return render(request, 'blog/post_list.html', {})

テンプレート作成(HTMLファイル)
$ vi blog/templates/blog/post_list.html
<html>
    <head>
        <title>Django Girls blog</title>
    </head>
    <body>
        <div>
            <h1><a href="">Django Girls Blog</a></h1>
        </div>

        <div>
            <p>published: 14.06.2014, 12:14</p>
            <h2><a href="">My first post</a></h2>
            <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
        </div>

        <div>
            <p>published: 14.06.2014, 12:14</p>
            <h2><a href="">My second post</a></h2>
            <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.</p>
        </div>
    </body>
</html>

サーバを起動して表示を確認
$ python manage.py runserver 192.168.55.2:8000

herokuへ再デプロイ
    $ git status        # ファイルの更新状態確認
    $ git add -A .      # 全変更をgitに追加
    $ git status
    $ git commit -m "Changed the HTML for the site."    # commit
    $ git push heroku master        # herokuへ再デプロイ

クエリセット(Django ORM)
シェル起動
$ python manage.py shell
# Post全データ取得
from blog.models import Post
Post.objects.all()

# Postデータ追加(Postするユーザ情報を取得してから)
from django.contrib.auth.models import User
User.objects.all()
me = User.objects.get(username='admin')
Post.objects.create(author = me, title = 'Sample title', text = 'Test')

# Postデータの絞り込み取得
Post.objects.filter(author=me)
Post.objects.filter(title__contains='title')

# 公開しているPostデータの絞り込み取得
from django.utils import timezone
Post.objects.filter(published_date__lte=timezone.now())

# Postデータの公開フラグ変更
post = Post.objects.get(id=1)
post.publish()
Post.objects.filter(published_date__lte=timezone.now())

# 並び替え
Post.objects.order_by('created_date')
Post.objects.order_by('-created_date')

exit()

モデル→ビュー→テンプレート(HTML)
どのモデルのデータをどのテンプレートに表示させるかビューに記述
ビューの内容を編集
    $ vi blog/views.py
        from django.shortcuts import render
        from django.utils import timezone
        from .models import Post

        def post_list(request):
            posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
            return render(request, 'blog/post_list.html', {'posts': posts})

モデルから取得したデータをテンプレートに表示
    $ vi blog/templates/blog/post_list.html
        <html>
            <head>
                <title>Django Girls blog</title>
            </head>
            <body>
                <div>
                    <h1><a href="/">Django Girls Blog</a></h1>
                </div>

                {% for post in posts %}
                    <div>
                        <p>published: {{ post.published_date }}</p>
                        <h1><a href="">{{ post.title }}</a></h1>
                        <p>{{ post.text|linebreaks }}</p>
                    </div>
                {% endfor %}
            </body>
        </html>

再デプロイ
    herokuへ再デプロイ
    $ git status        # ファイルの更新状態確認
    $ git add -A .      # 全変更をgitに追加
    $ git status
    $ git commit -m "Added views to create/edit blog post inside the site."    # commit
    $ git push heroku master        # herokuへ再デプロイ

見た目をよくする
Bootstrapの導入
blog/templates/blog/post_list.htmlの<head>に以下を追加
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">

静的ファイルの設定
    djangogirls/staticディレクトリ追加
    mysite/settings.pyに以下を追加
        STATICFILES_DIRS = (
            os.path.join(BASE_DIR, "static"),
        )
htmlファイルとcssの更新
    $ vi static/css/blog.css
        h1 a {
            color: #FCA205;
            font-family: 'Lobster';
        }
        body {
            padding-left: 15px;
        }

        .page-header {
            background-color: #ff9400;
            margin-top: 0;
            padding: 20px 20px 20px 40px;
        }

        .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a
            color: #ffffff;
            font-size: 36pt;
            text-decoration: none;
        }

        .content {
            margin-left: 40px;
        }

        h1, h2, h3, h4 {
            font-family: 'Lobster', cursive;
        }

        .date {
            float: right;
            color: #828282;
        }

        .save {
            float: right;
        }

        .post-form textarea, .post-form input {
            width: 100%;
        }

        .top-menu, .top-menu:hover, .top-menu:visited {
            color: #ffffff;
            float: right;
            font-size: 26pt;
            margin-right: 20px;
        }

        .post {
            margin-bottom: 70px;
        }

        .post h1 a, .post h1 a:visited {
            color: #000000;
        }


    $ vi blog/templates/blog/post_list.html
        <!DOCTYPE html>
        {% load staticfiles %}
        <html>
        <head>
        <meta charset="UTF-8">
        <title>Django Blog</title>
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/boots
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/boots
        <link rel="stylesheet" href="{% static 'css/blog.css' %}">
        <link href="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ex
        </head>
        <body>
            <div class="page-header">
                <h1><a href="/">Django Blog</a></h1>
            </div>
            {% for post in posts %}
                <div class="content container">
                    <div class="row">
                        <div class="col-md-8">
                            {% for post in posts %}
                                <div class="post">
                                    <div class="date">
                                        {{ post.published_date }}
                                    </div>
                                    <h1><a href="">{{ post.title }}</a></h1>
                                    <p>{{ post.text|linebreaks }}</p>
                                </div>
                            {% endfor %}
                        </div>
                    </div>
                </div>
            {% endfor %}
        </body>
        </html>

ほぼコーディングなしで、
ブログっぽいのができちゃいました。

チュートリアルはもう少し続きますが、
メモが・・ここまでしか残っていなかった・・。

気が向いたら続きをやりたいと思います。

ぜひ、上にリンクを張っているので、やってみることをおすすめします。
コマンドラインの説明などもあって、初心者に優しいチュートリアルです。

中途半端ですが、
以上です。

DjangoアプリをHerokuへデプロイ

前回からの続き。

下記のDjangoチュートリアルでやったことの続きを書いて行きます。
Django Girls Tutorial

前回作成したDjangoアプリのHerokuへのデプロイからです。

HerokuとはPaaS(platform as a service)を提供している会社のサービス。
アプリケーションを実行するための環境を提供してくれます。

CentOSを使用していたので、ここはかなり苦労しました。
何故かHeroku公式インストール手順通りやってもうまくいかず・・。
なので、Heroku CLIのインストールはチュートリアルとは違う内容でやっています。

デプロイ -----------------------------------------------------------------------
Herokuを使うために必要ないくつかのパッケージをインストール
    $ pip install dj-database-url gunicorn whitenoise

requirements.txtを作成 (djangogirlsディレクトリに)
    $ pip freeze > requirements.txt
requirements.txt編集、以下を追加 (Herokuで動かすために必要な1行)
(バージョンはチュートリアル通りじゃなく2.6.2を入れてみた)
    psycopg2==2.5.4

Procfile作成し以下を入力
(どのコマンドを実行してウェブサイトをスタートするかHerokuに伝える)
    $ vi Procfile
    web: gunicorn mysite.wsgi

runtime.txt作成
(Herokuに使っているPythonのバージョンを伝える)
    $ echo python-3.5.3 >> runtime.txt

mysite/local_settings.py(ローカル環境で動かすための設定を追加する)
    $ vi mysite/local_settings.py
    import os
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

    DEBUG = True

mysite/settings.py設定変更 最終行に以下を追加
    $ vi mysite/settings.py
    import dj_database_url
    DATABASES['default'] = dj_database_url.config()

    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

    ALLOWED_HOSTS = ['*']

    STATIC_ROOT = 'staticfiles'

    DEBUG = False

    try:
        from .local_settings import *
    except ImportError:
        pass

mysite/wsgi.py修正 最終行に以下を追加
    $ vi mysite/wsgi.py
    from whitenoise.django import DjangoWhiteNoise
    application = DjangoWhiteNoise(application)

Heroku CLIのインストール
    $ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
    $ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
    $ echo '# Ruby 設定(HerokuCLIで使用する)'  >> ~/.bash_profile
    $ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
    $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
    $ . ~/.bash_profile
    $ rbenv --version                       # Ruby仮想環境のバージョン確認
    $ rbenv install 2.3.1                   # Rubyのインストール
    $ rbenv versions                        # インストール済みRubyの確認
    $ rbenv global 2.3.1                    # Rubyのバージョン選択
    $ rbenv version                         # カレントディレクトリで有効な Ruby バージョン確認
    $ gem update --system                   # gem のアップデート
    $ gem install rails --no-rdoc --no-ri   # Railsインストール、たぶんやらなくていい
    $ wget https://cli-assets.heroku.com/branches/stable/heroku-linux-amd64.tar.gz
    $ tar -xvzf heroku-linux-amd64.tar.gz
    $ sudo mv heroku /usr/local/
    $ echo '' >> ~/.bash_profile
    $ echo '# HerokuCLIの設定' >> ~/.bash_profile
    $ echo 'export PATH="/usr/local/heroku/bin:$PATH"' >> ~/.bash_profile

.gitignoreファイルを作成して以下の内容を記述する。(djangogirlsで行う)
    myvenv
    __pycache__
    staticfiles
    local_settings.py
    db.sqlite3
    *.py[co]

Gitリポジトリ作成
    $ git init
        Initialized empty Git repository in ~/djangogirls/.git/
    $ git config user.name "Your Name"
    $ git config user.email you@example.com

gitコマンド
    変更されたファイルの一覧を表示
    $ git status
    作業ディレクトリ内の変更をステージングエリア(次回コミットの対象)に追加
    $ git add -A .          ($ git add -p インタラクティブなステージングセッションを開始 ファイルの一部を選択してステージできる)
    $ git commit -m "My Django Girls app"

アプリケーション名を決める(すでに使われている名前は使用できない)
    今回はアプリケーション名の指定なしで作成(自動でつけてくれる)
    $ heroku create <アプリケーション名>
        https://guarded-everglades-99999.herokuapp.com/
        https://git.heroku.com/guarded-everglades-99999.git
    変更したい場合は以下のコマンドで変更できる。
    $ heroku apps:rename the-new-name

Herokuにアプリケーションをデプロイ
    $ git push heroku master
        Verifying deploy.... done.

Herokuのウェブプロセスを起動
    $ heroku ps:scale web=1

Webブラウザで以下のURLにアクセス (まだheroku上にDBを設定していないのでエラーになる)
    https://<アプリケーション名>.herokuapp.com/
    https://<アプリケーション名>.herokuapp.com/admin

herokuへのDBのセットアップ
    $ heroku run python manage.py migrate
    $ heroku run python manage.py createsuperuser

デプロイ完了!

またまた長くなるので・・。

Djangoやってみる。

2,3年ぐらい前に、プログラマーのバイトでPythonとDjangoを使った開発に参加しました。
もう過去の話でどんなんだったか、思い出せないので久しぶりにDjangoのチュートリアルでもやって懐かしもうと思います。

おすすめチュートリアルとして、以下のチュートリアルを見つけたのでそれをやります。

ちなみに公式のチュートリアルもあります。
これは昔やった記憶がうっすらとあるので今回はパス。

内容は実際のチュートリアルを見てもらうほうが分かりやすくて良いともいます。
なので、ここではざっくりとやりながら取ったメモ書きを張るだけにします。

Django -------------------------------------------------------------------------
仮想環境(開発環境)作成
    $ python -m venv myvenv

開発環境の開始
    $ . myvenv/bin/activate
    行頭に(myvenv)が現れる
    $ deactivate        # 環境停止

Djangoインストール
    $ pip install django==1.10
    Successfully installed django-1.10
    $ pip list
    Django (1.10)
    pip (9.0.1)
    setuptools (28.8.0)

Django プロジェクト ------------------------------------------------------------
Djangoプロジェクトの作成
    $ django-admin startproject mysite .

タイムゾーンの変更
    mysite/settings.pyの以下の箇所を変更する
    befor:
        TIME_ZONE = 'UTC'
        USE_TZ = True
    after:
        TIME_ZONE = 'Asia/Tokyo'
        USE_TZ = False
    補足:DBの設定は同ファイル内の以下の箇所で設定している
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

DBのマイグレーション
    $ python manage.py migrate

サーバーの起動
    $ python manage.py runserver 192.168.55.2:8000
    Webブラウザでhttp://192.168.55.2:8000/にアクセスすると「It worked!」と表示される

アプリケーションの作成
    $ python manage.py startapp blog

Djangoにアプリケーションを認識させる
    mysite/settings.pyの以下の箇所を変更する
    INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',                         # 追加
)

モデルを定義する
    blog/models.pyの内容を以下に変更する
    from django.db import models
    from django.utils import timezone

    class Post(models.Model):
        author = models.ForeignKey('auth.User')
        title = models.CharField(max_length=200)
        text = models.TextField()
        created_date = models.DateTimeField(
                default=timezone.now)
        published_date = models.DateTimeField(
                blank=True, null=True)

        def publish(self):
            self.published_date = timezone.now()
            self.save()

        def __str__(self):
            return self.title

データベースにモデル用のテーブルを作る
    データベースに入れる為の移行ファイルを作成
    $ python manage.py makemigrations blog
    データベースへ反映
    $ python manage.py migrate blog

作成したポストを追加、編集、削除用Django adminページの設定
    blog/admin.pyを以下のように編集
    from django.contrib import admin
    from .models import Post

    admin.site.register(Post)

Django admin ログイン用ユーザ(superuser)作成
    $ python manage.py createsuperuser
    Username (leave blank to use 'vagrant'): admin
    Email address: admin@admin.com
    Password:admin12345

サーバーを起動しDjango adminにログイン
    $ python manage.py runserver 192.168.55.2:8000
    以下のURLにアクセス
    http://192.168.55.2:8000/admin/

    POSTとかを試してみる。
    Blog/Postsでデータの登録とかできるよ。


長くなるので、今回はここまでにします。
次はHerokuへのデプロイから(/・ω・)/

Pythonインストール

python2,python3を共存させてどちらも使えるように設定する。
pyenvを使うと複数のバージョンを共存させ、簡単に切り替えることができる。

必要な依存関係をインストール
    $ sudo yum install -y gcc zlib-devel bzip2 bzip2-devel readline readline-devel sqlite sqlite-devel openssl openssl-devel git

pyenvをダウンロード(clone)
    $ git clone https://github.com/yyuu/pyenv.git ~/.pyenv

pyenvにPATHを通す
    bash_profileに環境変数を記述
    $ vim .bash_profile

    以下を追記
    export PYENV_ROOT="$HOME/.pyenv"
    export PATH="$PYENV_ROOT/bin:$PATH"
    eval "$(pyenv init -)"
    bash_profileを反映。

    変更を反映
    $ source .bash_profile

    パスが通ったことを確認
    $ pyenv

python3系のインストール (herokuがサポートしているpythonバージョンが3.6.0)
    インストールできるバージョンを一覧表示
    $ pyenv install --list
    3.6.0をインストール
    $ pyenv install 3.6.0

pythonのバージョンを確認
    $ python --version
    Python 2.7.5    # 現在のバージョンが表示される

python3.6.0に切り替え
    $ pyenv global 3.6.0
    $ pyenv rehash
    $ python --version
    Python 3.6.0    # 変更したバージョンが表示される

利用可能なバージョンが表示
    $ pyenv versions
    system
    * 3.6.0 (set by /root/.pyenv/version)
    # systemに切り替えるとバージョンが2.7.5に戻る

参考にしたサイト
すいません忘れちゃいました。。(´Д`)

追記
pyenvについてこんな記事を見つけました。
pyenvが必要かどうかフローチャート
確かにインストールに使っただけで恩恵をそんな受けてない・・(・・;)