Django Postgres:作为主键的CharField的长度

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

在我的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.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)