DullCodes’s diary

programming,c++,python,MachineLearning,Math,Django,Competitive

Django アプリ 課題進捗管理 1

課題進捗管理アプリ

最高に簡単なやつを作る 目標は一時間で

Djangoで作っているアプリとかこの本をどこまで読んだだとか
Excelで管理するのはダサいのでDjangoDe勉強がてらアプリを作る

一つのProjectには
content(たくさん) と Tag(たくさん) をつける

はい完成
ユーザなどいない たった一人で使うアプリ

リレーション

モデルは3つ

  • Project
  • Content
  • Tag

でそれぞれの関係性は多分これでいいはず

1 個のProject には n 個の content があり
1個の content は 1 個のProjectにのみ繋がっている

うん

1個のProject には n 個の Tag があり
1個の Tag は n 個のProjectについている可能性がある

ので n : n の関係性だな?

f:id:DullCodes:20200326065601p:plain
Project manager model relations

こういう考え方でよいはず こういうのってデータベースでも勉強すると学べるのだろうか
まぁいいや というわけでモデルの作成

モデルとフィールド

project, conet, tag の3つのモデルがあればOK
startproject, startapp, settings.pyを適当にいじって作成

$ tree /ProjectManager-project
ProjectManager-project
│
├── config # config
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── content # app
├── project # app
├── tag     # app
├── static
├── db.sqlite3
├── manage.py
└── templates
  • Project

Project には本の名前とか、作っているアプリの名前を入力
タイトルでなにをやっているのか分かって、ちょっと説明を入れる
そのプロジェクトが終了したかどうかが知りたいのでそのbool値
よってフィールドは name, detail, is_finished の3つ

  • Content

content は todo の小項目みたいなもん
titleと、いつ設定したか(datetime)、完成したかどうか(bool)とコメントがあればOK
todo みたいに項目は消さないで残しておくので、bool で消すかどうかを管理する
フィールドは title, detail(comment), is_finishedの3つ
updated_at, created_at は全部のモデルに付ける

  • Tag

tag はそのまんま
name があれば良い

on_delete オプション

リレーションが繋がっている先のデータが消えた場合
自分はどうなるのかを決めるのが on_delete オプション

  • Project <-> Content

Project本体が消えたら、当然そこについているcontentは行き場は無いので削除
よって CASCADE

  • Project <-> Tag

Project本体が消えても Tag は n 個に relation がつながっているので
削除する必要はない つまり PROTECTになる

以上でモデルの完成 -> 実装

モデルたち

Project

from django.db import models
from tag.models import Tag


class Project(models.Model):
    class Meta:
        db_table = 'project'
        verbose_name = 'Project'
        verbose_name_plural = 'Projects'

    name = models.CharField(max_length=255)
    detail = models.TextField()
    is_finished = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    # Many To Many (n : n)
    tag = models.ManyToManyField(
        Tag,
        verbose_name='tag',
        related_name='project')

    def __str__(self):
        return self.name

Content

from django.db import models
from project.models import Project


class Content(models.Model):
    class Meta:
        db_table = 'content'
        verbose_name = 'content'
        verbose_name_plural = 'contents'

    # fields
    name = models.CharField(max_length=200)
    detail = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    # foreign key (1 : n)
    project = models.ForeignKey(
        Project,
        verbose_name='Project',
        on_delete=models.CASCADE,
        related_name='content')

    def __str__(self):
        return self.name

Tag

from django.db import models


class Tag(models.Model):
    class Meta:
        db_table = 'tag'
        verbose_name = "tag"
        verbose_name_plural = "tags"

    # field
    name = models.CharField(max_length=30)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

vscodedjango拡張機能のsnippetsを使うとMetaの3項目がついてくる

逆リレーション?について

Project と content の関係について

class Project(models.Model):
    ...

と

class Content(models.Model):
    # foreign key (1 : n)
    project = models.ForeignKey(
        Project,verbose_name='Project', on_delete=models.CASCADE)

となっている時、Content -> Project にはリレーションが張ってあるが
Project -> Content へのリレーションがどうなっているかが不明
というかProject を見てもContent との関係性が明らかになっていない
そこで設定するのが related_name

class Content(models.Model):
    # foreign key (1 : n)
    project = models.ForeignKey(
        Project,
        verbose_name='Project',
        on_delete=models.CASCADE,
        # これ
        related_name='content')

これを設定することによって、(見た目的に)一方的に張ってあるリレーションの
を辿れるようになる
実際の使い方はこんな感じ

<main>
  <h1>Project</h1>

  <div class="p_box">
    {% for project in projects %}
    <div>
      <p>
        {{project.updated_at}} | <b>{{project.name}}</b>
        {% if not project.is_finished %}
          <span> - In progress</span>
        {% endif %}
      </p>
      <p>{{project.detail}}</p>

      <div>
        {% for content in project.content.all %}
          <p class="c_box">{{content.name}}</p>
        {% endfor %}
      </div>
      <br>

      <div>
        <span>Tags : </span>
        {% for tag in project.tag.all %}
          <span>{{tag}}</span>
        {% endfor %}
      </div>
    </div>
    {% endfor %}
  </div>
</main>

で、templates を設定したところで1時間で閉店

f:id:DullCodes:20200326180245p:plain
one hour django challenge

まとめ

1時間じゃ無理だね

残り必要な機能は
Project, Content, Tag を Form で追加する機能
Content にチェックボックスをつけて、完成したかどうかを確認する
Tag を 追加する機能をつける
adminから登録している状態なのでエクセル以上に使いづらい

f:id:DullCodes:20200326181645p:plain
add Matome