Django:尝试使用自引用默认值进行用户迁移
Django: Trying to make Users migration with a self-referential default value
我正在尝试为我添加到我的用户模型的字段设置默认值,但我必须做很多杂技才能让它工作。
我想添加一个 'identifier' SlugField,它具有在函数中定义的默认值,如下所示:
def create_identifier():
while True:
identifier = ''.join(random.SystemRandom().choice('23456789BCDFGHJKMNPQRSTVWXYZ') for _ in range(15))
if not User.objects.filter(identifier=identifier).exists():
return identifier
class User(AbstractUser):
identifier = models.SlugField(default=create_identifier, max_length=16)
def __str__(self):
return self.username
这个确切的场景在不同的(不是用户)nodel class 上工作正常,但是当我尝试使用此代码为用户 运行 迁移时,我得到:
Traceback (most recent call last):
File "manage.py", line 29, in <module>
execute_from_command_line(sys.argv)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/base.py", line 332, in execute
self.check()
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/base.py", line 364, in check
include_deployment_checks=include_deployment_checks,
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/commands/migrate.py", line 58, in _run_checks
issues.extend(super()._run_checks(**kwargs))
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/base.py", line 351, in _run_checks
return checks.run_checks(**kwargs)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/checks/registry.py", line 73, in run_checks
new_errors = check(app_configs=app_configs)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/contrib/auth/checks.py", line 74, in check_user_model
if isinstance(cls().is_anonymous, MethodType):
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/base.py", line 469, in __init__
val = field.get_default()
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 775, in get_default
return self._get_default()
File "/home/myprojectname/myprojectname/myprojectname/users/models.py", line 34, in create_identifier
if not User.objects.filter(identifier=identifier).exists():
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/query.py", line 715, in exists
return self.query.has_results(using=self.db)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/sql/query.py", line 509, in has_results
return compiler.has_results()
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1037, in has_results
return bool(self.execute_sql(SINGLE))
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1068, in execute_sql
cursor.execute(sql, params)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "users_user" does not exist
LINE 1: SELECT (1) AS "a" FROM "users_user" WHERE "users_user"."iden...
我必须手动修改迁移:
migrations.CreateModel(
name='User',
fields=[
...
('identifier', models.SlugField(default='', max_length=16)),
...
),
migrations.AlterField(
model_name='user',
name='identifier',
field=models.SlugField(default=myprojectname.users.models.create_identifier, max_length=16),
),
然后如果我最初在 models.py 和 运行 迁移中设置 default='' 它会起作用,我可以改回 default=create_identifier事后.
class User(AbstractUser):
identifier = models.SlugField(default='', max_length=16)
def __str__(self):
return self.username
有什么方法可以让我在不采取这些措施的情况下完成这项工作吗?
编辑:如果字段为空或空,我是否最好只保留 blank=True,null=True 并覆盖模型的 save() 方法来更改值?
我似乎已经通过将 create_identifier 修改为以下内容来解决问题:
def create_identifier():
while True:
identifier = ''.join(random.SystemRandom().choice('23456789BCDFGHJKMNPQRSTVWXYZ') for _ in range(15))
try:
present = User.objects.first()
except:
present = None
if present:
if not User.objects.filter(identifier=identifier).exists():
return identifier
else:
return identifier
我正在尝试为我添加到我的用户模型的字段设置默认值,但我必须做很多杂技才能让它工作。
我想添加一个 'identifier' SlugField,它具有在函数中定义的默认值,如下所示:
def create_identifier():
while True:
identifier = ''.join(random.SystemRandom().choice('23456789BCDFGHJKMNPQRSTVWXYZ') for _ in range(15))
if not User.objects.filter(identifier=identifier).exists():
return identifier
class User(AbstractUser):
identifier = models.SlugField(default=create_identifier, max_length=16)
def __str__(self):
return self.username
这个确切的场景在不同的(不是用户)nodel class 上工作正常,但是当我尝试使用此代码为用户 运行 迁移时,我得到:
Traceback (most recent call last):
File "manage.py", line 29, in <module>
execute_from_command_line(sys.argv)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/__init__.py", line 365, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/base.py", line 332, in execute
self.check()
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/base.py", line 364, in check
include_deployment_checks=include_deployment_checks,
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/commands/migrate.py", line 58, in _run_checks
issues.extend(super()._run_checks(**kwargs))
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/management/base.py", line 351, in _run_checks
return checks.run_checks(**kwargs)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/core/checks/registry.py", line 73, in run_checks
new_errors = check(app_configs=app_configs)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/contrib/auth/checks.py", line 74, in check_user_model
if isinstance(cls().is_anonymous, MethodType):
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/base.py", line 469, in __init__
val = field.get_default()
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 775, in get_default
return self._get_default()
File "/home/myprojectname/myprojectname/myprojectname/users/models.py", line 34, in create_identifier
if not User.objects.filter(identifier=identifier).exists():
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/query.py", line 715, in exists
return self.query.has_results(using=self.db)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/sql/query.py", line 509, in has_results
return compiler.has_results()
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1037, in has_results
return bool(self.execute_sql(SINGLE))
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1068, in execute_sql
cursor.execute(sql, params)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/myprojectname/.local/share/virtualenvs/myprojectname-Uef4Bstr/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "users_user" does not exist
LINE 1: SELECT (1) AS "a" FROM "users_user" WHERE "users_user"."iden...
我必须手动修改迁移:
migrations.CreateModel(
name='User',
fields=[
...
('identifier', models.SlugField(default='', max_length=16)),
...
),
migrations.AlterField(
model_name='user',
name='identifier',
field=models.SlugField(default=myprojectname.users.models.create_identifier, max_length=16),
),
然后如果我最初在 models.py 和 运行 迁移中设置 default='' 它会起作用,我可以改回 default=create_identifier事后.
class User(AbstractUser):
identifier = models.SlugField(default='', max_length=16)
def __str__(self):
return self.username
有什么方法可以让我在不采取这些措施的情况下完成这项工作吗?
编辑:如果字段为空或空,我是否最好只保留 blank=True,null=True 并覆盖模型的 save() 方法来更改值?
我似乎已经通过将 create_identifier 修改为以下内容来解决问题:
def create_identifier():
while True:
identifier = ''.join(random.SystemRandom().choice('23456789BCDFGHJKMNPQRSTVWXYZ') for _ in range(15))
try:
present = User.objects.first()
except:
present = None
if present:
if not User.objects.filter(identifier=identifier).exists():
return identifier
else:
return identifier