DjangoでTwitterのようなフォロー、フォロワーの機能を実装する(models.py、ManyToManyField)
Djangoでフォロー機能をかんたんに実装したい
Toitterというアプリ名で、Twitterのようなフォロー機能の実現をしてみましょう。
今回はDjangoでなるべく簡単にフォロー機能を実装してみます。models.pyのデータベース定義部分がメインとなります。
またフォロー機能の設計にフォーカスを当てるためユーザーモデルはデフォルトのものを継承するのではなく、あらたにToitterUserモデルを作成していきます。
まずは結論
toitter/models.pyで以下のように定義
class ToitterUser(models.Model):
username = models.CharField(max_length=30)
following = models.ManyToManyField("self",related_name="followed_by",symmetrical=False,blank=True)
def __str__(self):
return self.name
symmetrical=Falseが重要だった、、。
それでははじめましょう🍻
前提
Git, Docker, 軽くDjango
バージョン
Django==3.2
サンプルコード
Githubのtwitter-like-modelブランチにあります。
ステップ1:環境構築をする
まずはターミナルで、以下のコマンドを順に実行してください。
git clone -b twitter-like-model https://github.com/yeconnect/django-baby-starter-template.git
cd django-baby-starter-template
docker compose up -d
docker compose run --rm web python manage.py migrate
ステップ2:models.pyに記述する
models.pyは以下のようになります。ToitterUserというモデルを定義しました。
from django.db import models
class ToitterUser(models.Model):
username = models.CharField(max_length=30, primary_key=True)
# ↓ここ!
following = models.ManyToManyField("self",related_name="followed_by",symmetrical=False,blank=True)
def __str__(self):
return self.username
usernameはすぐに理解できると思いますので、ここからfollowing=models.ManyToManyField(“self", related……….)の一行を解説していきます。
ManyToManyFieldを使う理由
例えば、ユーザーAには複数のフォロワーがおり、そのフォロワーは複数のユーザーをフォローしています。つまり多対多の関係にあります。
よって今回はManyToManyFieldを使います。
“self"とは?
Djangoはmodes.pyで自己参照するとき対象とするモデルに"self"と記述します。今回もToitterUserとToitterUserの関係性となり自己参照モデルです。
related_name="followed_by"とは?
AがBをフォローしている時、
AにとってBは「フォローしている人」、BにとってAは「フォロワー」です。後述しますが、このrelated_nameを書くことで、
Aの「フォローしている人」 → A.following.all()
Aの「フォロワー」 → A.followed_by.all()
と簡単に取ってくることができます。
symmetrical=Falseとは?
ManyToManyFieldで自己参照するとき、対象性がある場合とない場合があります。
対象性がある場合としては、友達関係があげられます。
例えばAがBの友達である場合、BもAの友達であることが確定します。(現実世界ではそうでもないかもしれませんが、。)
対象性がない場合としては、今回のようなフォロー、フォロワー関係です。
例えば一般人Aが有名人Bをフォローしているからといって、有名人Bは一般人Aをフォローしているわけではありません。
この対象性のある無しの設定はsymmetrical = True/Falseです。
よって今回のように自己参照のManyToManyFieldで、対象性がない場合はsymmetrical=Falseが必要です。
ステップ3:views.pyでの扱い方
ToitterUserをAとすると、フォローしている人を取得したい場合は
all = A.following.all()
フォロワーを取得したい場合は
all = A.followed_by.all()
と簡単に書けます。
またAがBをフォローするときは
A.following.add(B) # BはユーザBのオブジェクト
AがBをアンフォローするときは
A.following.remove(B)
ステップ4:動作確認
ブラウザで http://localhost:4989/toitter/ にアクセスしてみましょう!
まとめ&おまけ
Django BabyではDjangoの超入門チュートリアルやtipsをアップしていきます!
ディスカッション
コメント一覧
まだ、コメントがありません