# Django は必ず CustomUserモデルを使え!という話 ###### tags: `Django` `DRF` `python` 続きに twitter ログイン書く ## 参考: + [wsvincent/drfx: A framework for launching new Django Rest Framework projects quickly.](https://github.com/wsvincent/drfx) + [Djangoでは常にカスタムUserを使用すべき - Qiita](https://qiita.com/NAKKA-K/items/7627b6a22f364941b989) ## つまり: + ユーザーモデルを変更しないことは「ない」! + なのに、チュートリアルとかではいきなりcreatesuperuser させる、あいつら! + これをすると、あとでユーザーモデルに email とか address とか個人情報的なフィールドをもたせるのが大変。migration で時間かかりすぎる。強情だから! + `django.db.migrations.exceptions.InconsistentMigrationHistory: Migration authtoken.0001_initial is applied before its dependency user.0001_initial on database 'default'. ` エラーは、CustomUserモデルを適用する前に一度でも `python manage.py makemigration` した場合に起きる. おそらくだけど、アプリごと `python manage.py makemigration event` とかやってる間は、user モデルには影響しないのでは?と思う。一度でも0001を作ると起きるみたい + このエラーが起きた場合、 `settings.py ` ```python INSTALLED_APPS = [ #'django.contrib.admin', ] ``` して、`python manage.py migrate`する。 いったんこれをすれば`'django.contrib.admin',` はコメントをはずしてOK.参照([python - django.db.migrations.exceptions.InconsistentMigrationHistory - Stack Overflow](https://stackoverflow.com/questions/44651760/django-db-migrations-exceptions-inconsistentmigrationhistory/48476148#48476148)) + もしくは、db.sqlite3 削除、user/migrations 下のファイル全削除するしかないっぽい。 + もしかしたら db.sqlite3 削除 せずに、drop table user だけでもいいかもしれない。 ## install ``` $ pip install djangorestframework $ pip install django-rest-auth $ pip install django-allauth ``` ## project ``` $ django-admin startproject config . $ python manage.py startapp user $ python manage.py startapp v1 ``` ## 設定 + config/settings.py ```python INSTALLED_APPS = [ : : : 'django.contrib.sites', 'user', 'v1', 'rest_framework', 'rest_framework.authtoken', 'rest_auth', 'allauth', 'allauth.account', 'rest_auth.registration', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', ] } AUTH_USER_MODEL = 'user.CustomUser' EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' SITE_ID = 1 ``` + config/urls.py ```python from django.contrib import admin from django.urls import path, include # 127.0.0.1/8000/の配下。 # 管理画面は admin # rest は api/v1 以下 urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/', include('v1.urls')), ] ``` ## user アプリ + user/models.py ```python from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): pass ``` + user/admins.py ```python from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import CustomUser class CustomUserAdmin(UserAdmin): model = CustomUser admin.site.register(CustomUser, CustomUserAdmin) ``` + user/serializsers.py ```python from rest_framework import serializers from . import models class UserSerializer(serializers.ModelSerializer): class Meta: model = models.CustomUser fields = ('email', 'username') ``` + user/views.py ```python from rest_framework import generics from . import models from . import serializers class UserListView(generics.ListCreateAPIView): queryset = models.CustomUser.objects.all() serializer_class = serializers.UserSerializer ``` + user/urls.py ```python from django.urls import include, path from . import views urlpatterns = [ path('', views.UserListView.as_view()), ] ``` ## v1 アプリ + v1/urls.py ```python from django.urls import include, path # ここはすべて /api/v1 の配下 urlpatterns = [ path('rest-auth/', include('rest_auth.urls')), path('rest-auth/registration/', include('rest_auth.registration.urls')), path('user/', include('user.urls')), ] ``` ## endpoint + http://127.0.0.1:8000/admin + http://127.0.0.1:8000/rest-auth/login/ + http://127.0.0.1:8000/rest-auth/logout/ + http://127.0.0.1:8000/api/v1/user/ (ユーザーリスト) + http://127.0.0.1:8000/api/v1/rest-auth/registration/ (ユーザ登録) + http://127.0.0.1:8000/api/v1/rest-auth/user/(ユーザー詳細リスト) ## twitter login 参照:[Django Rest Frameworkでソーシャル認証 - Ahogrammer](https://hironsan.hatenablog.com/entry/django-rest-framework-social-oauth) twitter 用の serializer や view はすでに用意されているのでそれを使う user/views.py ```python from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter from rest_auth.registration.views import SocialLoginView from rest_auth.social_serializers import TwitterLoginSerializer class TwitterLogin(SocialLoginView): serializer_class = TwitterLoginSerializer adapter_class = TwitterOAuthAdapter ``` user/urls.py ```python from django.urls import include, path from . import views urlpatterns = [ path('', views.UserListView.as_view()), path('rest-auth/twitter/', views.TwitterLogin.as_view(), name='twitter_login') ] ``` ご指南書通りに取れる(URLは違う) ![](https://cdn-ak.f.st-hatena.com/images/fotolife/H/Hironsan/20190423/20190423083113.png) ## Twitter Dev 登録 https://developer.twitter.com/en/apps/6420090 を流用した。 ## Sites http://127.0.0.1:8000/admin/ > Sites > example.com + Domain name: 127.0.0.1:8000 + Display name: example.com ## Social application http://127.0.0.1:8000/admin/ > Social application > Add Social Application + Provider : Twitter + Name: Twitter (任意) + Client ID : Twitter の Consumer API keys の **API Key** + Secret key : Twitter の Consumer API keys の **API secret key** + Sites: 127.0.0.1:8080 を Chosen sites に追加 ## twitter app 登録 http://127.0.0.1:8000/api/v1/user/rest-auth/twitter/ + Access token: Twitter の Access token & access token secret の Access token + Access secret: Twitter の Access token & access token secret の Access token secret ## twitter でログイン まずは、allauthの設定 + config/urls.py ```python urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/', include('v1.urls')), path('accounts/', include('allauth.urls')),# 127.0.0.1:8000/accounts/ ] ``` https://developer.twitter.com/en/apps/6420090 + Callback URL: http://127.0.0.1:8000/accounts/twitter/login/callback/ + Website URL : https://finance.yahoo.co.jp/ + App usage: 100文字以上なにかかけば通るので、適当にどっかから日本語をコピーしてきてペースト。 + http://127.0.0.1:8000/accounts/twitter/login/ + :heavy_exclamation_mark: 注意: http://localhost:8000/accounts/twitter/login/ でログインすると、【**Social Network Login Failure. An error occurred while attempting to login via your social network account.**】が出ます。気をつけてね + ログインしたあと、 http://127.0.0.1:8000/accounts/profile/ に遷移して not found 言われたらOK! + http://127.0.0.1:8000/admin/user/customuser/ を確認すると、今ログインしたアカウントが確認できるはずですひゃっほー + http://127.0.0.1:8000/api/v1/user/ を確認するとここでも確認できる、ぴゃおおい〜。