Django Postgres:作为主键的CharField的长度
在我的Django模型中,有一个CharField作为主键,有250个字符作为Django Postgres:作为主键的CharField的长度,django,postgresql,django-models,Django,Postgresql,Django Models,在我的Django模型中,有一个CharField作为主键,有250个字符作为max_length和一个ManyToManyField: class GenericRoom(models.Model): key = models.CharField(primary_key=True, max_length=250) name = models.CharField(max_length=500, default='') extension = models.IntegerF
max_length
和一个ManyToManyField
:
class GenericRoom(models.Model):
key = models.CharField(primary_key=True, max_length=250)
name = models.CharField(max_length=500, default='')
extension = models.IntegerField(null=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, related_name="%(app_label)s_%(class)s_owner",
on_delete=models.CASCADE)
moderators = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="%(app_label)s_%(class)s_moderators",
blank=True)
type = models.CharField(max_length=50, choices=ROOM_TYPE_CHOICES, default='meeting')
class Room(GenericRoom):
pin = models.IntegerField(null=True)
此外,在Postgres中,键
列的最大长度为250,如下所示:
Column | Type | Collation | Nullable | Default
---------------------+------------------------+-----------+----------+---------
key | character varying(250) | | not null |
但是,当我给出的密钥超过50个字符时,我会:
r=Room.objects.create(key='a_veeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeery_long_key')
r.moderators.add(User.objects.get(id=123))
我得到:
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
psycopg2.DataError: value too long for type character varying(50)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 898, in add
self._add_items(self.source_field_name, self.target_field_name, *objs)
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 1065, in _add_items
for obj_id in new_ids
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/models/query.py", line 466, in bulk_create
ids = self._batched_insert(objs_without_pk, fields, batch_size)
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/models/query.py", line 1142, in _batched_insert
inserted_id = self._insert(item, fields=fields, using=self.db, return_id=True)
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/models/query.py", line 1125, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1283, in execute_sql
cursor.execute(sql, params)
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/ilias/.virtualenvs/vsceneapi/local/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/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
File "/home/ilias/.virtualenvs/vsceneapi/local/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/ilias/.virtualenvs/vsceneapi/local/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
django.db.utils.DataError: value too long for type character varying(50)
使用长varchar作为主键从来都不是一个好主意。 使用序列值作为pk是更好的做法
但是,由于您需要它,我进行了快速搜索并发现:“一个限制是不能在长度超过2000个字符的列上创建索引”(找到了)。不同的数据库后端对索引列中的字符串长度有不同的限制 对于postgres,您可以找到限制(长度为2000的字符串) 对于mysql,您可以找到它的局限性[以及一篇更好地解释它的文章,这是一个长度为255的字符串) 所以从理论上讲,没有理由不这样做(Django还增加了处理DB可移植性的限制,但密钥的长度在该范围内) 我怀疑原因在于您管理DB的方式,因为我看到您的模型和实际DB表之间不匹配(DB中的键
type
是varchar(100)
,但模型中的max_length=50
)
我建议您查看您的迁移并仔细检查它们,也可能重新创建表会起作用,可能是出了问题
希望它能有所帮助。不要使用字符域作为主键,最好使用默认的pk或uuid
import uuid
class YourModel(model.Model):
uuid = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
我认为问题在于
类型
列/字段。在PG中有100个,而您的模型最大有50个
请转到使用适合您的方法查看SQL查询。一般来说,这种问题来自复杂性。将其分割,直到有足够小的部分来解决问题。建议是查看精确的查询-这样您可以查看问题是在DB还是在应用程序/模型中。然后您可以尝试更小的模型,或更小的表,如两列s-键+某些东西,没有继承权…无论如何-我的打赌模型:)你能显示导致这种行为的查询吗?你有任何相关字段吗?@WillemVanOnsem请查看我问题的编辑版本。这是当我添加到多对多字段时。@houzayfari请查看我问题的编辑版本。有一个多对多字段你能得到表格的实际描述并提供它吗?
import uuid
class YourModel(model.Model):
uuid = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)