auth.User
モデルのモノリシック性、その中の不適切なフィールドセット、および使用しなければならないすべてのトリックに直面しました。
誰もが倒錯しなければなりませんでした。dzhangaのユーザーだけでなく、中核となる開発者自身に対してもです。 たとえば、Django 1.2では、
username
フィールドで犬の文字(@)と
username
を使用できるようになったのを覚えてい
username
か? 理由を知っていますか? メールアドレスをログインとして使用できるようにします 。
私たち一般のユーザーも苦労しました。 ユーザーにいくつかの興味深いフィールドを追加してユーザーのプロファイルを変更するために-一見普通のことですよね? -さまざまな方法で行動しなければなりませんでした。
- たとえば、 継承を考えてみましょう。
auth.User
から継承した独自のモデルを作成する必要がありました...
# models.py from django.db import models from django.contrib.auth.models import User class MyUser(User): birthday = models.DateField()
...ミドルウェアを作成して、request.user
のクラスを置き換えます。 またはミドルウェアではなく、AUTHENTICATION_BACKEND
。 関係ありません:)
このスキームの利点は、「クライアント」コード(つまり、プロジェクトコード)が複雑にならず、通常のdzhangovskiyのようにユーザーと一緒に作業したことです。
このようなスキームの主なマイナス点は、モデルを継承するときに、データベースに1つのテーブルではなく、2つの元のdjango_authdjango_auth
とourproj_user
であり、ourproj_user
に外部キーがあることdjango_auth
。 はい、Djangoのモデルの継承は、いくつかの追加属性を備えたOneToOneField
すぎません。 使用したい-覚えておいてください。
- Djangoの作成者によって提案された、よく知られている松葉杖、いわゆるプロファイルモデル 。
auth.User
1対1のauth.User
を持つProfile
モデルを作成するように求められました...
# models.py from django.db import models from django.contrib.auth.models import User class Profile(models.Model): user = models.OneToOneField(User) birthday = models.DateField()
...そして、設定に何かを追加します:
AUTH_PROFILE_MODULE = 'accounts.Profile'
その後、クライアントコードで、プロファイルを操作できます。
profile = request.user.get_profile() profile.birthday = datetime.today() profile.save()
さらに、そのようなスキームでは、私は知りません:)名前のあるフィールドのセットですか? マイナスを使用すると、すべてがより透明になります。
- サポートの複雑さ:編集用のオブジェクトは1つではなく、2つになりました。
profile
の誕生日と、たとえばuser
のパスワードを変更することを忘れてはなりません。 当然、混乱します。
- リソースの不適切な浪費:
get_profile()
呼び出すたびにデータベースへのクエリが発生します。 ユーザーインスタンスが1つしかないページ(編集など)では、これは怖いことではありません。 そのようなことが、たとえばコメントにある場合、結果は悲惨なものになります。 もちろん、select_related()
、理解しているように、User
がProfile
に依存しないので保存されませんが、その逆も同様です。
- それでもあなたは手ですべてをしなければなりません!
User
モデルを作成しても、関連するProfile
モデルが自動的に作成されるわけではありません。 しかし、新しく作成されたユーザーのget_profile()
にアクセスすると、例外がスローされます-それに疑いの余地はありません。 そして、このトラブルは数行で最も単純な信号で処理されますが、
# profile.models from django.db import models from django.contrib.auth.models import User class Profile(models.Model): '- ' def create_profile(sender, **kwargs): if kwargs['created']: Profile.objects.create(user=kwargs['instance']) models.signals.post_save.connect(create_profile, sender=User)
それにもかかわらず、その「手動」ソリューションの必要性は迷惑です。
- サポートの複雑さ:編集用のオブジェクトは1つではなく、2つになりました。
- Mankipatching 。つまり、コードを書き換えずにプログラムの動作を変更します。 プロジェクト内のある場所(
urls
、ルートurls
、特別に作成されたアプリケーションのsettings
またはmodels
アプリケーションを初期化した後、ユーザーを変更するコードを記述しました。
# monkey_patching.models from django.db import models from django.contrib.auth.models import User User.add_to_class('birthday', models.DateField() )
さらに、継承と同様に、クライアントコードが簡単になります。 短所-非自明。 ご存知のように、マジックは誤って再定義される可能性があるため、非常に慎重に処理する必要がありますが、まったく別の場所に表示されます。 一方、非常に慎重であれば、なぜですか?
サルといえば......
伝説的なsorl.thumbnailを世界に与えた男たちは、再び卓越し、アカウントで別のキラーなものを作りました。 出会い: django-
auth.User
メソッドを使用するアプリケーション(霊長類とサル、相関関係を感じられますか?)自分のモデルを
auth.User
に非常に簡単に変えることができます。 つまり、ロシア語では、目的のフィールドのプロファイルを作成します。
始めるのは簡単です。 まず、django-primateを配置する必要があります。 PyPIで可能です:
pip install django-primate
...また、リポジトリから最新バージョンを取得することもできます。
pip install -e git+https://github.com/aino/django-primate.git#egg=django-primate
起動時にパッチを呼び出す必要があります。 作成者は、
manage.py
使用することをお勧めします
#!/usr/bin/env python from django.core.management import setup_environ, ManagementUtility import imp try: imp.find_module('settings') # Assumed to be in the same directory. except ImportError: import sys sys.stderr.write( "Error: Can't find the file 'settings.py' in the directory " "containing %r. It appears you've customized things.\nYou'll have to " "run django-admin.py, passing it your settings module.\n" % __file__ ) sys.exit(1) import settings if __name__ == "__main__": setup_environ(settings) import primate primate.patch() ManagementUtility().execute()
あとは、使用するモデル
settings
クラスを
settings
指定するだけです
AUTH_USER_MODEL = 'users.models.User'
...そして、あなたはモデルを考え出すことができます:
# users.models from django.db import models from primate.models import UserBase, UserMeta class User(UserBase): __metaclass__ = UserMeta birthday = models.DateField() # ?
これで、プロジェクトコンポーネント
django.contrib.auth.models.User
users.models.User
django.contrib.auth.models.User
たびに、
users.models.User
モデルを受け取ります。 逆もまた真です。 管理パネルには自動的にパッチが適用され、接続には特別な手順は必要ありません。
デフォルトでは、django-
auth.User
ユーザーモデルには
auth.User
次の違いがあります。
- フィールド
first_name
およびlast_name
れますが、name
追加されます。 -
username
フィールドの最大長は50文字です(auth.User
では30文字) -
email
フィールドに一意のインデックスが追加されています -
get_profile
メソッドはself
返すため、user.get_profile()
を使用してコードを心配することはできません。
それ以外の場合、霊長類のユーザーモデル
もちろん、絶対に任意のフィールドセットを使用できますが、この場合、サードパーティアプリケーション間で互換性がなくなるリスクがあるため、
username
、
password
、および
email
フィールドの名前を変更しないことをお勧めします。
別のポイント:jungaとの互換性のために、霊長類は
app_label
が
users
はなく(例のように)
auth
なるようにモデルをダウンロードします。 これは、しばらくの間理由を理解できないかもしれない南のユーザーに特に当てはまります。
./manage.py schemamigration users --auto
移行は作成されません。
しかし、誰もが私が非常に自由に翻訳したREADMEに精通することができます。 私が何かを見逃したり、間違えたり、不正確にしたりした場合は、コメントを書いたり、あなたの考えを共有してください。
ご清聴ありがとうございました:)