その1では、プロジェクトの作成から、テンプレートの作成までを行います。
プロジェクト作成
デスクトップにmyappディレクトリを作成し、その中にプロジェクトを作ります。
$ cd desktop
$ mkdir myapp
VScodeでmyappを開き、VScodeのターミナルで仮想環境を作ります。
ついでに、pipとsetuptoolsのアップグレードもしておきます。
$ python -m venv env
$ source env/bin/activate
(env)$ pip install --upgrade pip setuptools
Djangoをインストールします。
(env)$ pip install django
さらに必要なパッケージを一気にインストールします。
- django-allauth
ログイン等の認証関係を手軽に実装するためのパッケージ - django-autoslug
URLにslugを使うための便利パッケージ - pillow
画像を扱うためのパッケージ。ImageFieldを使う場合は必要です。
(env)$ pip install django-allauth django-autoslug pillow
念の為に、pipの依存関係をチェック
(env)$ pip check
No broken requirements found.
「sampleapp」プロジェクトと「sns」アプリを作ります。
(env)$ django-admin startproject sampleapp
(env)$ cd sampleapp
(env)$ python manage.py startapp sns
基本設定
settings.pyでアプリの追加、日本化、必要であればデータベースの設定もします。
# snsとallauth関係を追加
INSTALLED_APPS = [
'sns', # snsを追加
...
'django.contrib.sites', # 追加
'allauth', # 追加
'allauth.account', # 追加
'allauth.socialaccount', # 追加
]
# allauthに必要なので追加
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend',
]
# 日本語に変更
LANGUAGE_CODE = 'ja'
# タイムゾーンを変更
TIME_ZONE = 'Asia/Tokyo'
# staticを使うのに必要
STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
#メディアルーティング
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = 'media/'
# allauthに必要
SITE_ID = 1
# allauthをMyUserモデルに対応させる
AUTH_USER_MODEL = 'sns.MyUser'
AUTH_USER_MODELのMyUserに関しては次の項目でモデルを定義します。
ユーザーモデルの設定
django-allauthを使う場合は、初回migrate前にユーザーモデルを定義しておかないといけないので作成します。
django-allauthはDjangoのUser、AbstractUser、AbstractBaseUserを元にユーザーモデルが作成されるので、AbstractBaseUserモデルを定義する。
AbstractBaseUserは、少し難しく感じるかもしれませんが自由にフィールドを設定できるので使い慣れておくと良いです。Django公式でもAbstractBaseUserの使用を薦めています。
作成するフィールド
Twitter風のSNSを作るので次のフィールドを作成します。
- ユーザーネーム(@usernameの部分)
- ニックネーム
- 誕生日
- プロフィール画像
- webサイトのurl
- 自己紹介
- 登録日
- スラッグ(usernameをurlに使う)
- フォロー
- フォロワー
from django.db import models
from django.contrib.auth.models import BaseUserManager, PermissionsMixin, AbstractBaseUser
from django.core.validators import MinLengthValidator, RegexValidator
from autoslug import AutoSlugField
class MyUserManager(BaseUserManager):
def create_user(self, username, email, password=None):
if not username:
raise ValueError('Users must have an username')
if not email:
raise ValueError('Users must have an email address')
user = self.model(
username=username,
email=self.normalize_email(email),
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email, password):
user = self.create_user(
username=username,
email=self.normalize_email(email),
password=password,
)
user.is_admin=True
user.is_staff=True
user.is_superuser=True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(verbose_name = 'username', max_length = 50, unique = True, validators=[MinLengthValidator(5,), RegexValidator(r'^[a-zA-Z0-9]*$',)])
email = models.EmailField(verbose_name = 'Email', max_length = 50, unique = True)
nickname = models.CharField(verbose_name = 'ニックネーム', max_length = 50, blank = False, null = False)
date_of_birth = models.DateField(verbose_name = "誕生日", blank = True, null = True )
image = models.ImageField(verbose_name = 'プロフィール画像', upload_to = "myimage", blank = True, null = True)
website = models.URLField(verbose_name = 'webサイト', blank = True, null = True)
introduction = models.TextField(verbose_name = '自己紹介', max_length = 140, blank = True, null = True)
date_joined = models.DateTimeField(verbose_name = '登録日', auto_now_add = True )
slug = AutoSlugField(populate_from='username', always_update=True)
follow = models.ManyToManyField("self", symmetrical=False, blank=True, related_name='follows')
follower = models.ManyToManyField("self", symmetrical=False, blank=True, related_name='followers')
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ["username"]
def __str__(self):
return f"{self.nickname}({self.username})"
def get_absolute_url(self):
return f"/{self.slug}"
誰かをfollowした時、相手が自分を自動でfollowしてしまわないように、manytomanyフィールドにsymmetrical=Falseとrelated_name=”を設定して非対処にしています。
BaseUserManager
AbstractBaseUserを使うには、BaseUserManagerが必要なので設定します。基本はコピペで大丈夫です。
MyUser内で、objects = MyUserManager()と書き呼び出します。
USERNAME_FIELD
ログインする時のユーザーネームをemailに変えます。
REQUIRED_FIELDS
アカウント作成時に必須の項目を指定。
def get_absolute_url(self):
ユーザーのurlを呼び出す時に使います。
データベースに反映
ユーザーモデルが定義できたので、makemigrationsとmigrateを実行します。
$ python manage.py makemigrations
$ python manage.py migrate
スーパーユーザー作成
メールアドレス、ユーザー名、パスワードは自由に設定してください。
$ python manage.py createsuperuser
Email: *******@mail.com
Username: ******
Password: ********
Password (again): ********
Superuser created successfully.
これでadminページにログインできるようになりました。
adminページに追加
snsのadmin.pyにMyUserモデルを追加します。
MyUserAdminで、MyUserのページを見やすくカスタマイズしています。
from django.contrib import admin
from sns.models import MyUser
class MyUserAdmin(admin.ModelAdmin):
filter_horizontal = ('follow', 'follower')
fieldsets = [
("基本情報", {'fields': ('username', 'password', 'email', 'nickname', 'date_of_birth','image', 'website', 'introduction')}),
('フォロー', {'fields': ('follow',)}),
('フォロワー', {'fields': ('follower',)}),
]
admin.site.register(MyUser, MyUserAdmin)
http://127.0.0.1:8000/adminにアクセスしログインします。
My Usersという項目があるので、そこで自分のニックネームと自己紹介を編集しておきましょう。
URLの設定
sampleapp/urls.pyに以下の内容に修正してください。
from django.contrib import admin
from django.urls import path, include
#メディアファイル保存
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('allauth.urls')),
path('', include("sns.urls")),
]
if settings.DEBUG:の部分は「開発環境であれば」settingsのMEDIA_ROOT(media)から画像を探すようになっています。
DEBUG=Trueだとエラーの内容が詳しく表示されるので開発環境でのみTrueに設定し、本番環境ではエラーを詳しく表示するとセキュリティー的に問題なのでFalseに設定します。
snsアプリにurls.pyを作成しpathを設定します。
from django.urls import path
from . import views
app_name = "sns"
urlpatterns = [
path('', views.index, name = "index"),
]
エラーが分かるように仮想サーバーを起動しておきます。
$ python manage.py runserver
viewの設定
sns/views.pyにindexページのviewを作成しておきます。
from django.shortcuts import render
def index(request):
context = {}
return render(request, 'sns/index.html', context)
templatesの設定
snsアプリ内にtemplatesディレクトリを作成。さらにその中にsnsのディレクトリを作成します。
作成したsnsディレクトリの中に、index.htmlを作成します。
<p>hello world</p>
これで、http://127.0.0.1:8000/にアクセスすれば「hello world」が表示されるはずです。
これで最低限の設定ができました。
次は、Twitter風のテンプレートを用意し、ツイート一覧、ツイート機能、フォロー機能を実装していきます。