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

У меня две модели, Article и ArticlePost. ArticlePost ссылается на Article как на внешний ключ и находится в отдельном приложении к Article:

====app1/models.py:======
class Article(models.Model):

     name = models.CharField(max_length=200, primary_key=True)

====app2/models.py======
class ArticlePost(models.Model):

    article = models.ForeignKey(Article, null=False, db_index=True)
    created_at = models.DateTimeField(auto_now_add=True)
    comment = models.TextField(blank=True)

Я запустил python manage makemigrations, который дает следующее:

operations = [
migrations.CreateModel(
    name='ArticlePost',
    fields=[
        ('id', models.AutoField(auto_created=True, verbose_name='ID', serialize=False, primary_key=True)),
        ('created_at', models.DateTimeField(auto_now_add=True)),
        ('comment', models.TextField(blank=True)),
        ('article', models.ForeignKey(to='app2.Article')),
    ],
),
]

Однако, когда я запускаю python manage migrate, я получаю:

django.db.utils.ProgrammingError: there is no unique constraint matching given keys for referenced table "article"

Что странно, так это то, что у меня есть другая модель в app1, которая также ссылается на статью с внешним ключом, который отлично работает. Однако в этом случае может показаться, что Django не знает, какое поле является первичным ключом для Article. Единственное отличие состоит в том, что ArticlePost находится в другом приложении, чем Article. У меня Джанго 1.10. Кто-нибудь знает, что вызывает это и как это можно исправить?

В качестве альтернативы, если это просто ключевая проблема, возможно, решение состоит в том, чтобы удалить primary_key в статье и вместо этого использовать стандартное значение Django id. В этом случае, как лучше всего это сделать, сохраняя ссылки внешнего ключа из других моделей на статью в приложении1?


person mohevi    schedule 04.08.2016    source источник
comment
Это не отвечает на ваш вопрос, но вы можете удалить null=False в поле модели. По умолчанию null=False. Вам нужно добавить значение null только в том случае, если вы устанавливаете его на True.   -  person jape    schedule 04.08.2016


Ответы (2)


Итак, то, что вы пытались сделать, абсолютно правильно. Но проблема здесь с Джанго.

Когда вы устанавливаете name как primary_key, то в соответствии с официальной документацией -> https://docs.djangoproject.com/ja/1.9/ref/models/fields/#django.db.models.Field.unique

primary_key=True подразумевает null=False и unique=True.

Итак, технически у вас есть уникальное поле в вашей модели Article, но после просмотра нескольких других сообщений в Stackoverflow,

см. это как ссылку (также просмотрите комментарии) -> Первичный ключ и уникальный ключ в джанго

похоже, что-то не так с primary_key=true. Кажется, что django рассматривает его только как первичный ключ, но не как unique

Поэтому, когда вы используете primary_key=true вместо name, Django не создает собственные уникальные автоматически увеличивающиеся идентификаторы для объектов. Следовательно, теперь у вас нет уникального идентификатора объекта в модели Article, из-за которого вы получаете ошибку, которую получаете.

Итак, просто удалите primary_key=true и позвольте Django использовать свои собственные автоматически увеличивающиеся уникальные идентификаторы, и вы не должны получить эту ошибку.

person Ankush Raghuvanshi    schedule 04.08.2016
comment
Спасибо за это, Анкуш, приятно знать, что происходит. Когда я пытаюсь это сделать, я получаю You are trying to add a non-nullable field 'id' to Article without a default; we can't do that (the database needs something to populate existing rows). Каким должно быть это значение по умолчанию? Кажется, Django не понимает, что ему нужно автоматически заполнять существующие записи новым идентификатором. Во-вторых, если я могу указать значение, что произойдет с существующими моделями с внешним ключом Article? Будут ли они сохранены? - person mohevi; 04.08.2016
comment
Да, вы правы в том, что Django не понимает, что ему нужно автозаполнение, поскольку он добавляет этот уникальный идентификатор только тогда, когда в эту модель добавляется новый объект. Итак, теперь новые не добавляются, поэтому он не заполняет уже существующий. Я думаю, вам придется добавить их самостоятельно, используя python manage.py shell, а затем запустив для этого простой цикл. Или же, если вы можете сделать резервную копию своих данных, удалите текущую и снова добавьте эти данные обратно. Таким образом, он создаст идентификаторы для вновь созданных. Также удалите все миграции перед добавлением новых данных и выполните новые миграции. - person Ankush Raghuvanshi; 04.08.2016
comment
И я не уверен в вашем втором вопросе, но я чувствую, что если бы Django не позволял вам сохранить этот внешний ключ, то изначально внешний ключ не был бы сохранен, верно? Так что сценарий сопровождения не вписывается в картину. Имеет ли это? - person Ankush Raghuvanshi; 04.08.2016
comment
Я думаю, что у вас уже есть данные в базе данных, и теперь вы пытаетесь добавить отношение к таблице, поэтому, возможно, когда вы объявляете ее как первичный ключ, некоторые данные содержат нулевые значения или, возможно, этот столбец не имеет все уникальные значения. Тем не менее, если вы попытаетесь сделать unique=True, это выдаст вам ошибку. - person Piyush S. Wanare; 15.11.2016

@mohevi, проверьте, используете ли вы MongoDb в качестве базы данных, поскольку mongodb не поддерживает функцию внешнего ключа. они обычно поддерживаются в СУБД, таких как postgresql, MySQL и т. д.

person Rahul Kumar    schedule 13.05.2021