Djangoプロジェクトを作成して実行【2020新卒】


この記事は2020年の新卒IT未経験の者が書きました。<br>
少しでも分かりやすくこの[Pycharm公式ドキュメント](https://pleiades.io/help/pycharm/creating-and-running-your-first-django-project.html)の手順をかみ砕いた記事です。<br>

### プロジェクトの作成

まずは新規プロジェクトを作成します<br>
![5ef324f27571490048e59e79.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/11788618-4b2b-cf07-8d9c-49ab357b7c0c.png)<br>

プロジェクトタイプはDjangoを選択し、プロジェクト名（ProjctTest）とApplication name（Poppo）はお好きなものを・・・<br>

![5ef325927571490048e59e7a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/41fdafac-4c61-b44b-ce33-736bc0482fc7.png)<br>



CreateをクリックしこれでDjangoプロジェクトが準備完了。<br>

### プロジェクトの構造
作成したプロジェクトにはすでにフレームワーク固有のファイルとディレクトリが含まれています。<br>

プロジェクトツールウィンドウのプロジェクトビューを見てみましょう。<br>

![5ef3274f7571490048e59e7c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/280dd24b-efe6-b4aa-7440-75c6c96487ac.png)
<br>

これはDjango固有のプロジェクト構造を示しています。<br>
> PoPPo と ProjectTest ディレクトリ（さっき設定したお好きな名前で作成されている）
>また、manage.py および settings.py ファイルが表示<br>

今回中身を編集するファイルは
- ProjectTest/urls.py 
- Poppo/models.py
- Poppo/views.py <br>
になります。


### Djangoサーバーの起動
では早速Djangoサーバーを起動してみましょう！<br>
manage.py ユーティリティの runserver タスクを起動するだけです。<br>

まずTerminalを開き<br>
`python manage.py runserver`<br>
と入力<br>

![5ef33645f67ca50048d05232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/f450c891-2585-55fb-7ba2-689f19d685c8.png)<br>

次にコンソールに表示されたURLをクリック<br>


![5ef33688f67ca50048d05233.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/a29091bf-8b21-ef3b-644b-4c9b1e793d70.png)<br>


この画面が表示されたら成功です🚀<br>
![5ef33692f67ca50048d05234.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/3f708812-ec06-5c06-67db-750870a3383c.png)<br>



### モデルの作成
次にmodels.pyを開いて、下記のコードを入力します。<br>
>このとき既にimport文があることに注意<br>

```
from django.db import models

# the following lines added:
import datetime
from django.utils import timezone

class Question(models.Model):
   question_text = models.CharField(max_length=200)
   pub_date = models.DateTimeField('date published')

   def __str__(self):
       return self.question_text

   def was_published_recently(self):
       now = timezone.now()
       return now - datetime.timedelta(days=1) <= self.pub_date <= now

   was_published_recently.admin_order_field = 'pub_date'
   was_published_recently.boolean = True
   was_published_recently.short_description = 'Published recently?'

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.DO_NOTHING,)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text
```

### データベースの作成
新しいモデル用のテーブルを作成する必要があります。<br>
そこでmanage.pyコンソールをCtrl+Alt+Rで呼び出し、`makemigrations Poppo`を入力。<br>

![5ef33943f67ca50048d05237.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/f12a0853-1ec5-6152-50cc-ff7e99c88727.png)
<br>

Djangoに2つの新しいモデル、つまり Choice と Questionが作成されたことを伝え、migrationsフォルダを作成しました。<br>

models.py<br>
![5ef33b61f67ca50048d0523c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/3fbeb805-bc58-d6cd-e189-09b938e6b66b.png)
<br>

作成されたmigrationフォルダ<br>
![5ef339e4f67ca50048d05239.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/049cccf6-2c57-852f-c0e7-1eba8115a9c2.png)
<br>

![5ef339faf67ca50048d0523a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/7a032bc3-eb54-ff65-9fac-6e8f22154f45.png)
<br>

次に再びmanage.pyコンソールで<br>
`sqlmigrate Poppo 0001`<br>
と入力。<br>

![5ef33d3ef67ca50048d0523d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/771ca94e-78be-345d-afb9-c467909aac99.png)
<br>

最後に`migrate` コマンドを実行して、データベースにこれらのテーブルを作成します。<br>

![5ef33d7df67ca50048d0523e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/9cb71605-1cf2-e3fe-c2c3-d71f6fbf8fe8.png)
<br>

### スーパーユーザーの作成
manage.py コンソールで　`createsuperuser` コマンドを入力し、自分のメールアドレスとパスワードを指定します。<br>

![5ef33e3cf67ca50048d05240 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/6077d9e2-984c-235e-c119-36b3f252ba00.png)
<br>

Superuser created successfully.と出たら作成完了。<br>

### 実行/デバッグ構成の準備
これで管理者ページに移動する準備が整いました。<br>
Djangoサーバーを実行し、ブラウザにアクセスし、アドレスバーにURL全体を入力することは可能ですが、PyCharmを使用すると簡単です。<br>
あらかじめ設定されたDjangoサーバーの実行構成を少し変更して使用します。<br>

ここを選択。<br>
![5ef3632cf67ca50048d0524b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/a6ff8799-6b60-d3c2-e899-c945af0ef3c4.png)<br>

Run/Debug Configurations ダイアログで、このRun/Debug Configurationsに名前（ここでは ProjectTest）を付け、デフォルトブラウザでアプリケーションの実行を有効にし（チェックボックスRun browserを選択）、デフォルトで開くサイトのページを指定します（ここでは http://127.0.0.1:8000/admin/です）。


![5ef3654df67ca50048d0524c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/623c9ea0-6030-a0b8-7043-94d1d34e8871.png)

<br>

これでOKをクリック<br>


### 管理サイトの起動

アプリケーションを起動するには、Shift+F10を押すか、メインツールバーの　Runボタン をクリックして、標準のDjangoサイトログインページを開きます。<br>
<br>
![5ef365e0f67ca50048d0524d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/063196d9-1e17-be27-6021-1aa3e957c2fe.png)
作成したスーパーユーザーでログイン。<br>


![5ef3671cf67ca50048d0524e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/c4035c13-6a00-6be7-f82f-e034dfa184db.png)
<br>


ログインすると、管理ページ（上の画像）が表示されます。認証と認可 (GroupsとUsers)セクションがありますが、投票(Questionの追加)は使用できません。なぜそうなるのでしょうか？<br>

Question オブジェクトには管理インターフェースがあることを管理者に伝える必要があります。<br>
そのために、Poppo/admin.py を開き、次のコードを入力します。<br>

```
from django.contrib import admin
from .models import Question #this line added
admin.site.register(Question)#this line added
```

ページをリフレッシュし、質問の投票セクションが表示されていることを確認します。<br>

追加完了。<br>
![5ef368baf67ca50048d05250.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/4f25bac1-9c5e-96ca-865e-bf96e792d397.png)
<br>

適当に質問を追加してみましょう。<br>

![5ef36946f67ca50048d05251.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/0aad1c1f-c275-00f3-c9f7-c4765145ac04.png)
<br>

質問が追加されました。<br>
![5ef36964f67ca50048d05252.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/e188b9df-3dee-db28-eec4-d2d7f2f8635e.png)
<br>


### admin.pyの編集

質問に対しての選択肢はまだありません。<br>
そこで再度 Poppo/admin.py を開き、次のように変更します。<br>

```
from django.contrib import admin
from .models import Choice, Question

class ChoiceInline(admin.TabularInline):
    model = Choice
    extra = 3

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
            (None,               {'fields': ['question_text']}),
            ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
                ]
    inlines = [ChoiceInline]

admin.site.register(Question, QuestionAdmin)
```

<br>
ページをリフレッシュし、追加した質問をクリックし、選択肢の追加が表示されていることを確認。<br>
選択肢や投票数を追加し保存する。<br>

![5ef36c27f67ca50048d05255.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/f5f37cdd-7f61-b89f-2dcf-d898bc87b13d.png)
<br>

### Viewの作成
ViewではIf文やWhile文、リスト、その他どのような構文もここで扱うことができるようになります。<br>
そして関数化することで次のtemplateに渡すことができるのです。<br>

さらにViewでは、関数ごとにどのHTMLファイルに情報を渡すのかを指定します。<br>
それによりそれぞれの関数をtemplateに紐付けていくことになります。<br>

Poppo/views.py を開き、次のコードを入力します。<br>

```
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
```
<br>

次に、urls.py という名前の新しいファイルを Poppo ディレクトリに追加し<br>
![5ef36fbaf67ca50048d05259.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/5d6d5510-fe8b-e25f-3d07-de065225aaa5.png)
<br>
次のコードを入力します。<br>

```
from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^$', views.index, name='index'),
]

```
<br>
最後に ProjectTest/urls.py （PyCharmがすでに作成している）を編集し、インデックスページのURLを末尾に追加します。<br>

```
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
    url(r'^Poppo/', include('Poppo.urls')), #this line added
    url(r'^admin/', admin.site.urls),
]
```
127.0.0.1:8000/Poppo/ を開いてみると・・・<br>
![5ef370cef67ca50048d0525c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/18de120f-8202-523f-43bd-be0e6045b64c.png)
<br>

次により多くのViewを追加してみます。<br>
再度、Poppo/views.pyに次のコードを追加します。<br>

```
def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

```

次の url() 呼び出しを追加する新しいViewを Poppo/urls.py モジュールに配線（末尾に追記）します。<br>

```
from django.conf.urls import url
from . import views

urlpatterns = [
url(r'^$', views.index, name='index'),
# ex: /Poppo/5/
url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /Poppo/5/results/
url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
# ex: /Poppo/5/vote/
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]
```
ブラウザで対応するページを開くと、次のように表示されます。<br>

![5ef3781d619aaa0048043a45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/be4d56a6-a415-ed59-877a-5c2f315701aa.png)
<br>
![5ef3784b619aaa0048043a47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/36f23ae4-0d0b-abcd-04cc-9cf57d5f3d94.png)
<br>
![5ef37868619aaa0048043a48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/20785093-b30c-3377-16f2-1a74faad7a35.png)
<br>


### Djangoテンプレートの作成
以上の通り、これらのページのデザインはビューにハードコードされています。<br>
読みやすくするために、対応するPythonコードを編集する必要があります。<br>
次に、Pythonからの出力の視覚的表現を分離しましょう。<br>
そうするために、templateを作成しましょう。<br>

Poppo/views.py を開き、その内容を次のコードに置き換えます。<br>

```
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse

from .models import Question, Choice


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'Poppo/index.html', context)


def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'Poppo/detail.html', {'question': question})


def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'Poppo/results.html', {'question': question})


def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render(request, 'Poppo/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('Poppo:results', args=(question.id,)))

```

ここで作成していないindex.htmlページを参照していることに気付くと思います。<br>

PyCharmはクイックフィックスという機能があります。<br>
電球をクリックするか Alt+Enterを押すと、対応するテンプレートファイルがtemplatesフォルダーに作成されます（PyCharmはこのテンプレートが存在するはずのディレクトリ Poppo も作成します）。<br>

![5ef37a26619aaa0048043a49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/b2c14ab5-dd2e-2026-b121-ba75a0af5221.png)
<br>

![5ef37a43619aaa0048043a4a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/9b286a4e-a287-42cb-c50b-947e1ec80e78.png)
<br>

![5ef37a65619aaa0048043a4b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/4d2c2fb0-813f-a335-be3b-14330e48b05e.png)
<br>

![5ef37a83619aaa0048043a4c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/79df02e7-5f13-1f65-3a18-53d17d1ee4fd.png)
<br>



同様にしてdetail.htmlとresults.htmlも作成します。<br>

今のところ index.html は空です。次のコードを追加します。<br>

```
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'Poppo/style.css' %}" />
{% if latest_question_list %}
           <ul>
    {% for question in latest_question_list %}
           <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
       </ul>
{% else %}
           <p>No polls are available.</p>
{% endif %}

```

### スタイルシートの作成
Viewファイル index.htmlに見られるように、スタイルシート(.cssファイル)の参照があり、そしてまだ作成していません。<br>

次のように作成します。<br>

1. ディレクトリを作成します。これを行うには、プロジェクトビューで、Pythonパッケージ Poppo を選択し、Alt+Insertを押します。<br>
![5ef37d85619aaa0048043a4f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/67bfcd96-e283-be9e-70bc-2c651806955b.png)


2. 表示されるポップアップメニューでディレクトリを選択し、ディレクトリ構造 static/Poppoを指定します。<br>
![5ef37df1619aaa0048043a50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/cb67bea2-c54c-69bb-edc5-95aa59f3e52b.png)


3. 次に、このディレクトリにスタイルシートを作成します。これを行うには、最も内側のディレクトリ Poppo/static/Poppoを選択し、Alt+Insertを押し、Stylesheetを選択して、表示されるダイアログでstyleを入力します。<br>
![5ef37e31619aaa0048043a51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/36ae4d18-0f12-2205-5c3c-17d7a641d16d.png)
<br>
![5ef37e98619aaa0048043a52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/c9ac3f22-3f9a-8641-3422-43918b0c8c4f.png)

4. 好みに応じて、作成されたスタイルシートに下記のコードを追加（例：質問のリストを緑色の文字で表示）。
```
li a {
color: green;
}
```

### 実行結果の確認
Runボタンをクリックしブラウザの<br>
`http://127.0.0.1:8080/admin/`を
`http://127.0.0.1:8080/Poppo/`に変更し入力して確認してみましょう。<br>

![5ef3817c619aaa0048043a53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661949/5eb0a834-3384-61f1-2998-0cdc1525118d.png)
<br>

出来ました。<br>
これを参考に自分のページを育ててみましょう🌱