Django-Postgres: длина CharField в качестве первичного ключа - PullRequest
0 голосов
/ 08 июня 2018

В моей модели 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 максимальная длина столбца key равна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)

Для ключей короче 50 все работает нормально.

Таким образом, для столбца key должно быть неявное ограничение в 50 символов, даже если ограничение составляет 250.

Но почему?И как я могу это изменить?

РЕДАКТИРОВАТЬ:

Описание таблицы от Postgres:

       Column        |          Type          | Collation | Nullable | Default 
---------------------+------------------------+-----------+----------+---------
 key                 | character varying(250) |           | not null | 
 owner_id            | integer                |           |          | 
 extension           | integer                |           |          | 
 name                | character varying(500) |           | not null | 
 type                | character varying(100) |           | not null | 
 pexip_conference_id | integer                |           |          | 
 pin                 | integer                |           |          | 
Indexes:
    "rooms_room_pkey" PRIMARY KEY, btree (key)
    "rooms_room_key_ca48250b_like" btree (key varchar_pattern_ops)
    "rooms_room_owner_id_13734245" btree (owner_id)
Foreign-key constraints:
    "rooms_room_owner_id_13734245_fk_users_user_id" FOREIGN KEY (owner_id) REFERENCES users_user(id) DEFERRABLE INITIALLY DEFERRED
Referenced by:
    TABLE "meeting_spaces_meetingspace" CONSTRAINT "meeting_spaces_meetingspace_room_id_10905900_fk" FOREIGN KEY (room_id) REFERENCES rooms_room(key) DEFERRABLE INITIALLY DEFERRED
    TABLE "meetings_meeting" CONSTRAINT "meetings_meeting_room_id_02a205a4_fk" FOREIGN KEY (room_id) REFERENCES rooms_room(key) DEFERRABLE INITIALLY DEFERRED
    TABLE "recordings_recording" CONSTRAINT "recordings_recording_room_id_799f40af_fk" FOREIGN KEY (room_id) REFERENCES rooms_room(key) DEFERRABLE INITIALLY DEFERRED
    TABLE "rooms_room_moderators" CONSTRAINT "rooms_room_moderators_room_id_abd2abc5_fk_rooms_room_key" FOREIGN KEY (room_id) REFERENCES rooms_room(key) DEFERRABLE INITIALLY DEFERRED
    TABLE "users_user" CONSTRAINT "users_user_room_id_06ed4152_fk" FOREIGN KEY (room_id) REFERENCES rooms_room(key) DEFERRABLE INITIALLY DEFERRED

Ответы [ 4 ]

0 голосов
/ 15 июня 2018

Я думаю, проблема в type столбце / поле.У PG 100, а у вашей модели 50 - максимальный размер.

Пожалуйста, перейдите здесь , чтобы использовать подходящий вам метод для просмотра SQL-запросов.В общем, такого рода проблемы возникают из-за сложности.Разделите, нарежьте, пока у вас не будет достаточно маленького кусочка, чтобы решить проблему.Предложение состоит в том, чтобы видеть точные запросы - таким образом, вы можете увидеть, есть ли проблема в БД или в приложении / модели.Тогда вы можете попробовать меньшую модель или меньшую таблицу, например, два столбца - ключ + что-то, без наследования ... В любом случае - моя ставка - модель.:)

0 голосов
/ 14 июня 2018

Различные базы данных имеют разные ограничения на длину строк в индексированном столбце.

Для postgres вы можете найти ограничения здесь (это строка длиной 2000)

Для mysql вы можете найти ограничения здесь [И пост SO, объясняющий это лучше здесь , который является строкой длиной 255)

Таким образом, теоретически не должно быть никаких причин, по которым это не должно работать (Django также добавляет ограничение для обработки переносимости БД, допускает использование пользовательских primary_keys, с max_length = 255 , но длина вашего ключа находится в этом диапазоне).

Я подозреваю, что причина заключается в том, как вы управляете вашей БД, поскольку я вижу несоответствие между вашей моделью и реальной таблицей БД (ключ type равен varchar(100) в БД, но max_length=50 в вашей модели).

Я бы посоветовал вам взглянуть на ваши миграции и перепроверить их, также, возможно, воссоздание таблицы будет работать, возможно, что-то там пошло не так.

Надеюсьпомогает, может быть.

0 голосов
/ 14 июня 2018

Не используйте CharFields в качестве первичных ключей, лучше используйте pk или uuid по умолчанию

import uuid
class YourModel(model.Model):
    uuid = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
0 голосов
/ 13 июня 2018

Никогда не стоит использовать длинные varchars в качестве первичного ключа.Лучше использовать последовательное значение в качестве pk.

Но, поскольку вы хотели, я сделал быстрый поиск и обнаружил следующее: «Одно ограничение состоит в том, что индексы нельзя создавать для столбцов, длина которых превышает примерно 2000символы "(найдено здесь ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...