Пользовательский первичный ключ Django

Когда я проверяю базу данных Trac, я получаю:

class TicketChange(models.Model):
    ticket = models.IntegerField()
    time = models.BigIntegerField()
    author = models.TextField(blank=True)
    field = models.TextField()
    oldvalue = models.TextField(blank=True)
    newvalue = models.TextField(blank=True)
    class Meta:
        managed = False
        db_table = 'ticket_change'

С не первичным ключом:

>>> TicketChange.objects.all()
DatabaseError: column ticket_change.id does not exist
LINE 1: SELECT "ticket_change"."id", "ticket_change"."ticket", "tick...

Потому что мне нужно указать pk, но исходный первичный ключ ticket_change в Trac:

Primary key (ticket, time, field)

Но это невозможно в Django: Обсуждение многостолбцового первичного ключа Django.

Если я определяю time как pk, я не могу добавить два изменения билетов одновременно.

Что я могу сделать?


person Ignacio Pérez    schedule 15.11.2013    source источник
comment
я реализовал базовую поддержку виртуальных составных ключей. Никаких модификаций базы данных не требуется. Проверьте мой ответ здесь - stackoverflow.com/a/65404017/46548   -  person kmmbvnr    schedule 22.12.2020


Ответы (3)


Ты прав. Это известная проблема. Таким образом, единственными решениями являются хаки (вроде).

Лучше всего использовать django-compositepks. Недостатки заключаются в том, что он на самом деле не поддерживает модельные отношения, поэтому вы не сможете перейти к каким-либо отношениям из вашей композитной модели pk. Однако, глядя на вашу модель TicketChange, это не кажется проблемой (если только у вас нет других моделей, связанных с этой).

Другим вариантом было бы вручную добавить столбец id (и обязательно применить любые дополнительные изменения к базе данных), тем самым создав новый первичный ключ с одним столбцом. Третий вариант (и то, что я, вероятно, сделал бы), очень похожий на последний, но более чистый, заключается в создании новой базы данных с нуля, а затем заполнении ее сценарием, извлекая данные из вашей существующей устаревшей базы данных.

Извините, у меня нет лучшего решения для вас, так оно и есть. Устаревшие dbs и django всегда вызывают головную боль, я сам прошел через некоторые подобные процессы. Надеюсь это поможет!

person yuvi    schedule 15.11.2013

Это вариант использования, который Django ORM просто не поддерживает. Если вы можете изменить схему базы данных, добавьте дополнительный столбец, который будет служить первичным ключом для Django: целочисленное поле с AUTO_INCREMENT (MySQL) или SERIAL (PostgreSQL). Это не должно мешать вашим другим приложениям, использующим таблицу, поскольку она будет управляться вашей базой данных при вставке новых записей. Вы по-прежнему можете использовать фактический первичный ключ при выполнении запросов через ORM:

ticket_change = TicketChange.objects.get(ticket=1234, time=5678, field='myfield')
person sjaensch    schedule 15.11.2013

Если вы хотите указать собственный первичный ключ, укажите primary_key=True в одном из ваших полей. Если Django увидит, что вы явно установили Field.primary_key, он не добавит столбец с автоматическим идентификатором. Каждая модель требует, чтобы только одно поле имело значение primary_key=True (объявленное явно или добавленное автоматически).

https://docs.djangoproject.com/en/3.1/topics/db/models/#automatic-primary-key-fields

person Jerome Blacq    schedule 02.10.2020