django의 auth_user.username이 varchar (75)가 될 수 있습니까? 어떻게 할 수 있습니까?
에 테이블 변경을 실행하는이 아무것도 잘못 auth_user
만드는 username
일 varchar(75)
이 이메일에 맞게 수는? 그게 뭐가 깨지나요?
장고를 수정해야하는 곳 으로 변경 auth_user.username
하려면 varchar(75)
? 단순히 소스 코드를 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 자에는 대부분의 정상적인 이메일 주소가 포함됩니다. 질문은 이메일 인증 기반 애플리케이션에서 발생하는이 상황을 대상으로합니다.
핵심 모델을 건드리지 않고 상속없이이를 달성 할 수있는 방법이 있습니다.하지만 확실히 엉터리이며 특별히주의해서 사용할 것입니다.
신호에 대한 Django의 문서를 보면 class_prepared
기본적으로 메타 클래스에 의해 실제 모델 클래스가 생성되면 전송되는 라는 이름 이 있습니다. 어떤 전에 그 순간 어떤 모델을 수정하는 마지막 기회 마법이 일어난다 (예 : ModelForm
, ModelAdmin
, syncdb
, 등 ...).
따라서 계획은 간단합니다. User
모델에 대해 호출 될 때이를 감지하는 핸들러로 해당 신호를 등록한 다음 필드 의 max_length
속성 을 변경하기 만하면됩니다 username
.
이제 문제는이 코드가 어디에 있어야 하는가입니다. User
모델이로드 되기 전에 실행되어야 하므로 종종 매우 이른 시간을 의미 합니다. 안타깝게도 (django 1.1.1 , 다른 버전으로 확인하지 않음) settings
가져올 수 signals
없습니다.
더 나은 선택은 그것을 더미 앱의 모델 모듈에 넣고 해당 앱 을 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
새로운 최대 길이를 반영하기 위해 필드의 를 변경할 수도 있습니다.- 당신은 자동으로 관리자를 사용하려면 서브 클래스에있을 것이다
UserChangeForm
,UserCreationForm
그리고AuthenticationForm
최대 길이로 모델 필드에서 추론되지 않지만, 직접 양식 필드 선언한다.
당신이 사용하는 경우 남쪽 , 당신은 기본 데이터베이스에 열을 변경하려면 다음 마이그레이션을 생성 할 수 있습니다 :
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
위의 Clément와 Matt Miller의 훌륭한 결합 답변을 기반으로이를 구현하는 빠른 앱을 모았습니다. Pip 설치, 마이그레이션 및 이동. 이것을 코멘트로 넣을 것이지만 아직 신용이 없습니다!
https://github.com/GoodCloud/django-longer-username
2014-12-08 수정
위 모듈은 이제 https://github.com/madssj/django-longer-username-and-email 을 위해 더 이상 사용되지 않습니다.
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()
위의 솔루션은 모델 길이를 업데이트하는 것 같습니다. 그러나 사용자 지정 길이를 관리자에 반영하려면 관리자 양식도 재정의해야합니다 (단순히 모델에서 길이를 상속하지 않음).
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))
내가 아는 한 문제를 해결할 Django 1.5 이후 사용자 모델을 재정의 할 수 있습니다 . 여기에 간단한 예
If you simply modify the database table, you'll still have to deal with Django's validation, so it won't let you make one over 30 characters anyways.
Additionally, the username validates so that it can't have special characters like
My bad, looks like it handles that. Here's the username field from models.py in django.contrib.auth:@
so simply modifying the length of the field wouldn't work anyways.
username = models.CharField(_('username'), max_length=30, unique=True, help_text=_("Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"))
Creating email auth is not hard. Here's a super simple email auth backend you can use. Al l you need to do after that is add some validation to ensure the email address is unique and you're done. That easy.
Yes, it can be done. At least I think this should work; I wound up replacing the whole auth model, so am ready to be corrected if this doesn't work out...
If you have no user records you care about:
- drop the auth_user table
- change username to max_length=75 in the model
- syncdb
If you have user records you need to retain then it's more complicated as you need to migrate them somehow. Easiest is backup and restore of the data from old to new table, something like:
- backup the user table data
- drop the table
- syncdb
- reimport user data to the new table; taking care to restore the original id values
Alternatively, using your mad python-django skillz, copy the user model instances from old to new and replace:
- create your custom model and temporarily stand it alongside the default model
- write a script which copies the instances from the default model to the new model
- replace the default model with your custom one
The latter is not as hard as it sounds, but obviously involves a bit more work.
Fundamentally, the problem is that some people want to use an email address as the unique identifier, while the user authentication system in Django requires a unique username of at most 30 characters. Perhaps that will change in the future, but that's the case with Django 1.3 as I'm writing.
We know that 30 characters is too short for many email addresses; even 75 characters is not enough to represent some email addresses, as explained in What is the optimal length for an email address in a database?.
I like simple solutions, so I recommend hashing the email address into a username that fits the restrictions for usernames in Django. According to User authentication in Django, a username must be at most 30 characters, consisting of alphanumeric characters and _, @, +, . and -. Thus, if we use base-64 encoding with careful substitution of the special characters, we have up to 180 bits. So we can use a 160-bit hash function like SHA-1 as follows:
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('=', '')
In short, this function associates a username for any email address. I'm aware that there is a tiny probability of a collision in the hash function, but this should not be an issue in most applications.
Just adding the below code at the bottom of settings.py
from django.contrib.auth.models import User
User._meta.get_field("username").max_length = 75
C:...\venv\Lib\site-packages\django\contrib\auth\models.py
first_name = models.CharField(_('first name'), max_length=30, blank=True)
change to
first_name = models.CharField(_('first name'), max_length=75, blank=True)
save
and change in the database
I am using django 1.4.3 which makes it pretty easy and I did not have to change anything else in my code after realising I wanted to use long email addresses as usernames.
If you have direct access to the database, change it there to the amount of characters you would like to, in my case 100 characters.
In your app model (myapp/models.py) add the following
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)
Then in your settings.py you specify the model:
AUTH_USER_MODEL = 'myapp.UserProfile'
The best solution is to use email field for email and the username for username.
In the input login form validation, find whether the data is username or the email and if email, query the email field.
This only requires monkey patching the contrib.auth.forms.login_form
which is a few lines in the corresponding view.
And it is far better than trying to modify the models and the database tables.
If you are using venv (virtual environment), the simplest solution probably is just update the core code directly, i.e. opening the following two files: - - venv/lib/python2.7/sites-packages/django/contrib/auth/model.py - venv/lib/python2.7/sites-packages/django/contrib/auth/forms.py Search for all username field and change max_length from 30 to 100. It is safe since you are already using venv so it won't affect any other Django project.
'Program Tip' 카테고리의 다른 글
GNU C 매크로 envSet (name)에서 (void) ""이름은 무엇을 의미합니까? (0) | 2020.11.17 |
---|---|
Convert.ToBoolean 및 Boolean.Parse는 0과 1을 허용하지 않습니다. (0) | 2020.11.17 |
Rails 3 : 새 중첩 리소스를 만드는 방법은 무엇입니까? (0) | 2020.11.17 |
Python 패키지 내부에서 (정적) 파일을 읽는 방법은 무엇입니까? (0) | 2020.11.17 |
변수에서 대소 문자 구분을 무시하는 Windows 배치 명령 (0) | 2020.11.17 |