65

メールに収まるようにaltertableを実行auth_userするusernameことに何か問題がありますか?varchar(75)どちらかといえば、それは何を壊しますか?

どこに変更auth_user.usernameするvarchar(75)場合、djangoを変更する必要がありますか?ソースコードを30から75に変更するだけですか?

username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))

または、変更する必要があるこのフィールドに関する他の検証、または変更するための他の影響はありますか?

それを行う理由については、以下のbartekとのコメントディスカッションを参照してください。

編集:何ヶ月も経った後、これを振り返ります。前提を知らない人のために:一部のアプリにはユーザー名を使用する要件や希望がなく、登録と認証に電子メールのみを使用します。残念ながら、django auth.contribでは、ユーザー名が必要です。ユーザー名フィールドにメールを入力することもできますが、このフィールドは30文字しかないため、実際にはメールが長くなる可能性があります。ここで提案されている75文字よりも長い可能性がありますが、75文字はほとんどの正常な電子メールアドレスに対応します。この質問は、電子メール認証ベースのアプリケーションで発生するこの状況を対象としています。

4

13 に答える 13

78

コアモデルに触れることなく、継承せずにそれを達成する方法がありますが、それは間違いなくハックであり、私は特別な注意を払ってそれを使用します。

シグナルに関するDjangoのドキュメントを見ると、と呼ばれるものがあることがわかります。class_preparedこれは基本的に、メタクラスによって実際のモデルクラスが作成されると送信されます。その瞬間が、魔法が発生する前にモデルを変更する最後のチャンスです(つまり、、、、ModelFormなどModelAdminsyncdb

したがって、計画は単純です。そのシグナルを、Userモデルに対して呼び出されたときに検出するハンドラーに登録してから、フィールドのmax_lengthプロパティを変更するだけです。username

ここで問題となるのは、このコードはどこにあるべきかということです。Userモデルをロードする前に実行する必要があるため、多くの場合、非常に早い段階を意味します。残念ながら、そこにインポートすると問題が発生するため、(django 1.1.1、別のバージョンで確認していない)それを入れることはできません。settingssignals

より良い選択は、それをダミーアプリのモデルモジュールに配置し、そのアプリをリスト/タプルの一番上にINSTALLED_APPS配置することです(したがって、他の何よりも先にインポートされます)。これがあなたが持つことができるものの例ですmyhackishfix_app/models.py

from django.db.models.signals import class_prepared

def longer_username(sender, *args, **kwargs):
    # You can't just do `if sender == django.contrib.auth.models.User`
    # because you would have to import the model
    # You have to test using __name__ and __module__
    if sender.__name__ == "User" and sender.__module__ == "django.contrib.auth.models":
        sender._meta.get_field("username").max_length = 75

class_prepared.connect(longer_username)

それでうまくいきます。

ただし、いくつかの注意事項:

  • help_text新しい最大長を反映するために、フィールドのも変更することをお勧めします
  • 自動管理を使用する場合は、サブクラス化する必要がありますUserChangeFormUserCreationForm最大AuthenticationForm長はモデルフィールドから推定されるのではなく、フォームフィールド宣言で直接推定されるためです。

Southを使用している場合は、次の移行を作成して、基になるデータベースの列を変更できます。

import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):

        # Changing field 'User.username'
        db.alter_column('auth_user', 'username', models.CharField(max_length=75))


    def backwards(self, orm):

        # Changing field 'User.username'
        db.alter_column('auth_user', 'username', models.CharField(max_length=35))


    models = { 

# ... Copy the remainder of the file from the previous migration, being sure 
# to change the value for auth.user / usename / maxlength
于 2010-04-10T12:39:12.390 に答える
25

上記のClémentとMattMillerのすばらしい組み合わせの回答に基づいて、それを実装する簡単なアプリをまとめました。Pipのインストール、移行、および実行。これをコメントとして入れますが、まだ信用を持っていません!

https://github.com/GoodCloud/django-longer-username

2014年12月8日編集

上記のモジュールは廃止され、https://github.com/madssj/django-longer-username-and-emailが採用されました。

于 2011-07-28T01:36:55.397 に答える
21

Django 1.3バージョンの更新されたソリューション(manage.pyを変更せずに):

新しいdjango-appを作成します。

monkey_patch/
    __init__.py
    models.py

最初にインストールします:(settings.py)

INSTALLED_APPS = (
    'monkey_patch', 
    #...
)

これがmodels.pyです:

from django.contrib.auth.models import User
from django.core.validators import MaxLengthValidator

NEW_USERNAME_LENGTH = 300

def monkey_patch_username():
    username = User._meta.get_field("username")
    username.max_length = NEW_USERNAME_LENGTH
    for v in username.validators:
        if isinstance(v, MaxLengthValidator):
            v.limit_value = NEW_USERNAME_LENGTH

monkey_patch_username()
于 2011-06-23T11:34:51.617 に答える
5

上記の解決策は、モデルの長さを更新しているようです。ただし、カスタムの長さをadminに反映するには、adminフォームもオーバーライドする必要があります(イライラすることに、モデルから長さを継承するだけではありません)。

from django.contrib.auth.forms import UserChangeForm, UserCreationForm

UserChangeForm.base_fields['username'].max_length = NEW_USERNAME_LENGTH
UserChangeForm.base_fields['username'].widget.attrs['maxlength'] = NEW_USERNAME_LENGTH
UserChangeForm.base_fields['username'].validators[0].limit_value = NEW_USERNAME_LENGTH
UserChangeForm.base_fields['username'].help_text = UserChangeForm.base_fields['username'].help_text.replace('30', str(NEW_USERNAME_LENGTH))

UserCreationForm.base_fields['username'].max_length = NEW_USERNAME_LENGTH
UserCreationForm.base_fields['username'].widget.attrs['maxlength'] = NEW_USERNAME_LENGTH
UserCreationForm.base_fields['username'].validators[0].limit_value = NEW_USERNAME_LENGTH
UserCreationForm.base_fields['username'].help_text = UserChangeForm.base_fields['username'].help_text.replace('30', str(NEW_USERNAME_LENGTH))
于 2012-10-12T20:31:56.110 に答える
2

私の知る限り、問題を解決するDjango 1.5以降、ユーザーモデルをオーバーライドできます。ここでの簡単な例

于 2013-03-25T08:34:55.030 に答える
1

データベーステーブルを変更するだけの場合でも、Djangoの検証を処理する必要があるため、30文字を超える文字を作成することはできません。さらに、ユーザー名は、フィールドの長さを変更するだけでは機能しないような特殊文字を使用できないように検証されます。@私の悪い、それはそれを処理するように見えます。django.contrib.authのmodels.pyのユーザー名フィールドは次のとおりです。

username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))

メール認証の作成は難しくありません。これが、使用できる非常にシンプルなメール認証バックエンドです。その後に行う必要があるのは、電子メールアドレスが一意であることを確認するための検証を追加することです。とても簡単です。

于 2010-04-09T19:14:32.577 に答える
1

はい、できます。少なくとも、これはうまくいくはずだと思います。私は認証モデル全体を置き換えることになったので、これがうまくいかない場合は修正する準備ができています...

気になるユーザーレコードがない場合:

  1. auth_userテーブルを削除します
  2. モデルでユーザー名をmax_length=75に変更します
  3. syncdb

保持する必要のあるユーザーレコードがある場合は、何らかの方法でそれらを移行する必要があるため、より複雑になります。最も簡単なのは、次のような古いテーブルから新しいテーブルへのデータのバックアップと復元です。

  1. ユーザーテーブルデータをバックアップする
  2. テーブルをドロップ
  3. syncdb
  4. ユーザーデータを新しいテーブルに再インポートします。元のID値を復元するように注意してください

または、狂ったpython-djangoスキルを使用して、ユーザーモデルインスタンスを古いものから新しいものにコピーし、次のものを置き換えます。

  1. カスタムモデルを作成し、デフォルトモデルの横に一時的に置きます
  2. デフォルトモデルから新しいモデルにインスタンスをコピーするスクリプトを作成します
  3. デフォルトモデルをカスタムモデルに置き換えます

後者は思ったほど難しくはありませんが、明らかにもう少し作業が必要です。

于 2010-04-10T09:04:14.260 に答える
1

基本的に、問題は、一部の人々が一意の識別子として電子メールアドレスを使用したいのに対し、Djangoのユーザー認証システムは最大30文字の一意のユーザー名を必要とすることです。おそらくそれは将来変わるでしょうが、私が書いているDjango1.3の場合もそうです。

30文字は多くのメールアドレスには短すぎることがわかっています。「データベース内の電子メールアドレスの最適な長さはどれくらいですか?」で説明されているように、75文字でも一部の電子メールアドレスを表すには不十分です。。

私は単純な解決策が好きなので、Djangoのユーザー名の制限に適合するユーザー名にメールアドレスをハッシュすることをお勧めします。Djangoのユーザー認証によると、ユーザー名は最大30文字で、英数字と_、@、+ 、.で構成されている必要があります。と -。したがって、特殊文字を慎重に置き換えてbase-64エンコーディングを使用すると、最大180ビットになります。したがって、SHA-1のような160ビットのハッシュ関数を次のように使用できます。

import hashlib
import base64

def hash_user(email_address):
    """Create a username from an email address"""
    hash = hashlib.sha1(email_address).digest()
    return base64.b64encode(hash, '_.').replace('=', '')

つまり、この関数は任意の電子メールアドレスにユーザー名を関連付けます。ハッシュ関数で衝突が発生する可能性はごくわずかですが、これはほとんどのアプリケーションで問題になることはありません。

于 2012-03-09T19:07:31.270 に答える
0

settings.pyの下部に以下のコードを追加するだけです

from django.contrib.auth.models import User
User._meta.get_field("username").max_length = 75
于 2013-05-23T03:38:57.767 に答える
0

C:... \ venv \ Lib \ site-packages \ django \ contrib \ auth \ models.py

first_name = models.CharField(_('first name')、max_length = 30、blank = True)

への変更

first_name = models.CharField(_('first name')、max_length = 75、blank = True)

保存する

データベースの変更

于 2018-07-30T12:50:45.357 に答える
-1

私はdjango1.4.3を使用しています。これにより、非常に簡単になり、ユーザー名として長いメールアドレスを使用したいと思った後、コード内で他に何も変更する必要がなくなりました。

データベースに直接アクセスできる場合は、データベースを希望の文字数(私の場合は100文字)に変更します。

アプリモデル(myapp / models.py)に以下を追加します

from django.contrib.auth.models import User

class UserProfile(models.Model):

    # This field is required.
    User._meta.get_field("username").max_length = 100
    user = models.OneToOneField(User)

次に、settings.pyでモデルを指定します。

AUTH_USER_MODEL = 'myapp.UserProfile'
于 2014-05-13T11:05:38.847 に答える
-2

venv(仮想環境)を使用している場合、最も簡単な解決策は、コアコードを直接更新することです。つまり、次の2つのファイルを開きます。--- venv / lib / python2.7 / sites-packages / django / contrib / auth / model .py --venv / lib / python2.7 / sites-packages / django / contrib / auth / forms.pyすべてのユーザー名フィールドを検索し、max_lengthを30から100に変更します。すでにvenvを使用しているため、安全です。 t他のDjangoプロジェクトに影響を与えます。

于 2013-01-07T05:09:06.730 に答える
-3

最善の解決策は、電子メールに電子メールフィールドを使用し、ユーザー名にユーザー名を使用することです。

入力ログインフォームの検証で、データがユーザー名か電子メールかを確認し、電子メールの場合は電子メールフィールドにクエリを実行します。

contrib.auth.forms.login_formこれには、対応するビューの数行にあるモンキーパッチのみが必要です。

そして、モデルとデータベーステーブルを変更しようとするよりもはるかに優れています。

于 2010-04-11T07:32:04.720 に答える