在auth_user
上运行alter table以使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的评论讨论。
编辑:经过几个月的回顾。对于不了解前提的人:某些应用程序没有要求或希望使用用户名,他们只使用电子邮件进行注册。 AUTH。不幸的是,在django auth.contrib中,用户名是必需的。您可以开始在用户名字段中添加电子邮件,但该字段只有30个字符,而现实世界中的电子邮件可能很长。可能比这里建议的75个字符更长,但75个字符可以容纳最理智的电子邮件地址。问题针对的是这种情况,正如基于电子邮件验证的应用程序所遇到的那样。
答案 0 :(得分:78)
有一种方法可以在不触及核心模型的情况下实现这一目标,并且没有继承,但它肯定是hackish,我会特别小心地使用它。
如果你看一下Django的文档on signals,你会看到有一个名为class_prepared
,它基本上是在元类创建任何实际模型类后发送的。那个时刻是你在任何魔法发生之前修改任何模型的最后机会(即:ModelForm
,ModelAdmin
,syncdb
等......)。 / p>
因此计划很简单,您只需使用处理程序注册该信号,该处理程序将检测何时为User
模型调用它,然后更改max_length
的{{1}}属性字段。
现在问题是,这段代码应该在哪里生活?它必须在加载username
模型之前执行,因此通常意味着很早。不幸的是,您不能(django 1.1.1 ,未检查其他版本)将其放在User
中,因为导入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
,因为最大长度不是从模型字段中推断出来的,而是直接在表格字段声明。如果您正在使用South,则可以创建以下迁移以更改基础数据库中的列:
AuthenticationForm
答案 1 :(得分:25)
根据Clément和Matt Miller的上述综合答案,我汇集了一个实现它的快速应用程序。 Pip安装,迁移和转发。将此作为评论,但还没有信誉!
https://github.com/GoodCloud/django-longer-username
编辑2014-12-08
现已弃用上述模块,转而使用https://github.com/madssj/django-longer-username-and-email
答案 2 :(得分: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()
答案 3 :(得分:5)
上述解决方案似乎确实更新了模型长度。但是,要在管理员中反映您的自定义长度,您还需要覆盖管理表单(令人沮丧的是,它们不会简单地从模型继承长度)。
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))
答案 4 :(得分:2)
据我所知,自Django 1.5以来可以override user model解决问题。简单示例here
答案 5 :(得分: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"))
创建电子邮件身份验证并不难。这是你可以使用的super simple email auth backend。您需要做的就是添加一些验证以确保电子邮件地址是唯一的并且您已完成。这很容易。
答案 6 :(得分:1)
是的,可以做到。至少我认为这应该有效;我最终取代了整个auth模型,所以如果不能解决这个问题我准备好了......
如果您没有关注的用户记录:
如果您有用户记录需要保留,那么它会更复杂,因为您需要以某种方式迁移它们。最简单的是从旧表到新表的备份和恢复数据,如:
或者,使用您的mad python-django skillz,将用户模型实例从old复制到new并替换:
后者并不像听起来那么难,但显然需要做更多的工作。
答案 7 :(得分:1)
从根本上说,问题是有些人想要使用电子邮件地址作为唯一标识符,而Django中的用户身份验证系统需要最多30个字符的唯一用户名。也许这将在未来发生变化,但正如我正在写的那样,Django 1.3也是如此。
我们知道许多电子邮件地址的30个字符太短;即使75个字符也不足以代表某些电子邮件地址,如What is the optimal length for an email address in a database?中所述。
我喜欢简单的解决方案,因此我建议将电子邮件地址散列为符合Django中用户名限制的用户名。根据{{3}},用户名必须最多为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('=', '')
简而言之,此功能会关联任何电子邮件地址的用户名。我知道哈希函数中存在很小的碰撞概率,但在大多数应用程序中这不应该是一个问题。
答案 8 :(得分:0)
只需在settings.py
的底部添加以下代码即可from django.contrib.auth.models import User
User._meta.get_field("username").max_length = 75
答案 9 :(得分: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)
保存
并更改数据库
答案 10 :(得分:-1)
我正在使用django 1.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'
答案 11 :(得分:-2)
最佳解决方案是使用电子邮件字段添加电子邮件和用户名。
在输入登录表单验证中,查找数据是用户名还是电子邮件,如果是电子邮件,请查询电子邮件字段。
这只需要猴子修补contrib.auth.forms.login_form
,这是相应视图中的几行。
它比尝试修改模型和数据库表要好得多。
答案 12 :(得分:-2)
如果您使用的是venv(虚拟环境),最简单的解决方案可能就是直接更新核心代码,即打开以下两个文件: - - 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,因此它不会影响任何其他Django项目。