MawaLog

一日一日、楽しく生きる。技術と音楽が好き。

Django:social-auth-app-djangoとUUIDフィールドで苦労した話

Anthology

Anthology

コメント

最初にDjangoで運営してるメディアで、TwitterのSocialAuthでいきなりエラーがでてログインできなくなったんですよ!いままでは問題なく動いてたのに!!これが起きてしまったPYPIパッケージはsocial-auth-app-django==2.1.0でしたご注意を!!

HTTPError: 403 Client Error: Forbidden for url: https://api.twitter.com/oauth/request_token

ほっといても直らないし、APIの制限にひっかかることもしてない(Twitterデベロッパー管理画面でチェックしてもなにも制限されてる旨の表示はなし。キーを一回再生成したけど意味なし)らちがあかないので、もうメール認証でユーザーログイン機能を実装しなおそうと思い始めました。

経緯

#usermanage/models.py

class User(AbstractBaseUser, PermissionsMixin):

    uuid = models.UUIDField(default=uuid_lib.uuid4, primary_key=True, editable=False)
    #↑idのかわりにuuidを使ってみている

そうすると、ユーザー新規登録時にエラーがでてしまう。

・・・(中略)・・・
UUID('<uuidの文字列>') is not JSON serializable

なんだこれは・・・Oauthでは出なかったのにぃ・・・と、ググると、Django1.7以前あたりは有名なバグだったらしいが、今はDjango2.0だし、解決されてるよかったね的な公式記事が・・・うーむ。

https://code.djangoproject.com/ticket/24320

一旦諦めてuuidをやめようとするが・・・

うーん。でもuuidをPrimaryKeyにしちゃってるし、今からIDフィールド別途作ってとか・・・危険な感じしかしない・・・と、いうわけで多少安全そう??な(誤解)UUIDフィールドをPrimaryKeyのままCharfieldにしちゃうとシリアライザ−エラーが直ってハッピーなのでは??と仮説を立てる。で、実行。ついでにuuidの文字列がなにかリスクがあるのかもしれないと、数字だけで小さいメディアだし、かぶりにくいだろうタイムスタンプの羅列でチャレンジ。こういう感じ

uuid = models.CharField(max_length=500, default=datetime.datetime.now().strftime("%Y%m%d%H%M%S%f"),
                            primary_key=True, editable=False)

ローカルslqliteでは無事マイグレーションもできて動く!OK!いい感じだ。

で、herokuにデプロイ。migrat...エラーあああ!!!

DETAIL:  Key columns "user_id" and "uuid" are of incompatible types: uuid and character varying.

うーむ。調べるとPostgreではなんかフィールドをUUIDから変えようとするとなる症状らしいっぽい。。。

UUIDのままだと、最初のエラーがでるし、奇策のCharfield作戦は、Postgreに阻まれる。おいおいプロジェクト作り直し??絶望・・・

しかし諦めずに調べると、神記事が現れた!

arthurpemberton.com

これ!!!しかもうまくいきますようにみたいなお祈りも書いてる、、、良い人だ〜〜^^/

#usermanage/models.py に追記する↓

#↓ここから追記開始↓
from json import JSONEncoder
from uuid import UUID

JSONEncoder_olddefault = JSONEncoder.default

def JSONEncoder_newdefault(self, o):
    if isinstance(o, UUID): return str(o)
    return JSONEncoder_olddefault(self, o)

JSONEncoder.default = JSONEncoder_newdefault
#↑追記はここまで↑

class User(AbstractBaseUser, PermissionsMixin):

    uuid = models.UUIDField(default=uuid_lib.uuid4, primary_key=True, editable=False)
    #下記、モデルの続きが書いてある

すると、エラーが消えた!!!ありがとう〜〜〜m( )m