# 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/ を確認するとここでも確認できる、ぴゃおおい〜。