简体   繁体   中英

Why does Django set a shorter maximum length of foreign keys to auth.User.username?

I have a model with a foreign key that references the username field of auth.User . The original field has a maximum length of 150. But Django generates a foreign key with a maximum length of 30.

In my app's models.py:

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

In django.contrib.auth.models:

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

Generated SQL:

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

This only happens when referencing auth.User.username. If I reference a long field in my own model, the foreign key is generated fine.

Why is that? How can I overcome it?

Using Django 1.11.4 and Python 3.6.2. I tried PostgreSQL and SQLite and the problem occurs on both.

CLARIFICATION: From the answers so far I think my question was misunderstood. I am not looking for a way to have long usernames. My problem is that the stock User model that comes with Django has one max_length (150), but when your model refers to it, the foreign hey has a shorter max_length of 30. Therefore if a user is registered with a username of 31 characters, I will not be able to create child objects of that user, because the foreign key constraint will be violated. And I need this because I have a REST API whose URLs nest resources under uses, that are referred by username, not ID. For example: /users/<username>/profiles/...

UPDATE: I think the reason for this behavior is the undocumented swappable property of the User model. It is designed to be replaceable by custom models. However, the configured model must have its data in the initial migration of the app that defines the model. The migrations code seems to generate references to the initial migration of swappable models. I am using the default User model, and its initial migration sets the username to 30 chars. Hence my username FKs are 30 chars long. I am able to work around this with a RunSQL migration to alter the FK data type to varchar(15), but I am in doubt if it's the right thing to do.

Is recommended use short identifier, varchar(30) is a long number, something like 999999999999999999999999999999, when Django make identifiers always use the same number. I don't think that you are going to use so much users if you reach that number you should create another type of identifier. Remember the long of the user_id field is the id of the username and not the string

You can use this hack described in this SO answer , but be very careful!.

Or you can use this package .

However, I think that, as described in this discussion , the best way would be to create a custom User model and do whatever you want there.

Hope it helps!

You must use custom user model.Taken from django docs.

150 characters or fewer. Usernames may contain alphanumeric, _, @, +, . and - characters.

The max_length should be sufficient for many use cases. If you need a longer length, please use a custom user model. If you use MySQL with the utf8mb4 encoding (recommended for proper Unicode support), specify at most max_length=191 because MySQL can only create unique indexes with 191 characters in that case by default.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM