2017-08-28 80 views
3

我有一个外键模型引用用户名字段auth.User。原场有150的最大长度,但Django的产生与30为什么Django将外键的最大长度设置为auth.User.username?

,最大长度为外键在我的应用程序的models.py:

class Profile(models.Model): 
    user = models.ForeignKey('auth.User', to_field='username') 

在django.contrib.auth.models:

username = models.CharField(
    _('username'), 
    max_length=150, 

生成的SQL:

CREATE TABLE "myapp_profile" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "user_id" varchar(30) NOT NULL REFERENCES "auth_user" ("username") 
); 

这仅引用auth.User.username发生时。如果我在我自己的模型中引用一个长字段,则会生成外键。

这是为什么?我如何克服它?

使用Django 1.11.4和Python 3.6.2。我试过PostgreSQL和SQLite,两者都出现问题。

澄清: 从目前为止的答案,我认为我的问题被误解了。我不想找到一个长用户名的方法。我的问题是Django附带的股票用户模型有一个max_length(150),但是当你的模型引用它时,外部hey的max_length更短。因此,如果用户注册的用户名为31个字符,我将无法创建该用户的子对象,因为外键约束将被违反。我需要这个,因为我有一个REST API,它的URL在使用下嵌套资源,这些资源是由用户名引用的,而不是ID。例如:/users/<username>/profiles/...

UPDATE: 我认为这种现象的原因是用户模型的无证热插拔财产。它被设计成可由自定义模型替换。但是,配置的模型必须在定义模型的应用的初始迁移中有其数据。迁移代码似乎生成对可交换模型的初始迁移的引用。我使用默认的用户模型,并且其初始迁移将用户名设置为30个字符。因此我的用户名FK是30个字符长。我可以通过RunSQL迁移来解决此问题,以将FK数据类型更改为varchar(15),但我怀疑它是否正确。

+0

你为什么这样做?通常,外键指向外表的主键。你为什么需要改变它? –

+0

我有一个嵌套在User对象下的对象的REST API。 URL的格式为/ users//resources /。在这种情况下,找到父用户的正确外键就是用户名。 –

+0

这并不遵循,这些东西是不相关的。正如我所描述的,与fks建立嵌套关系是完全可能的 - 事实上也是正常的。 –

回答

1

建议使用短标识符,varchar(30)是一个很长的数字,类似于999999999999999999999999999999,当Django使标识符始终使用相同的数字。我认为如果你达到这个数字,你不会使用这么多的用户,你应该创建另一种类型的标识符。请记住user_id字段的长度是用户名的ID,而不是字符串

+0

父级用户已具有varchar(150)的用户名。即使我有一个用户名长度为31个字符的用户,由于外键约束,应用程序也无法插入引用它的资源。 –

+0

你能举一个例子说明你如何建立关系? –

+0

class profile(models.Model): user = models.ForeignKey('auth.User',to_field ='username') –

0

您可以使用this SO answer, 中描述的这种破解,但要非常小心!可以使用this package

但是,我认为,如this discussion所述,最好的方法是创建一个custom User model并在其中执行任何操作。

希望它有帮助!

+0

在那种情况下,他们正在修改用户列,在这种情况下,Victor使用关系,但用户名长度为150 –

0

您必须使用自定义用户模型。从django文档中获取。

150个字符或更少。用户名可能包含字母数字,_,@,+,。和 - 字符。

max_length应该足够用于许多用例。如果您需要更长的时间,请使用自定义用户模型。如果您使用utf8mb4编码的MySQL(建议适当的Unicode支持),请指定max_length = 191,因为默认情况下,MySQL只能创建191个字符的唯一索引。