<class> не имеет внешнего ключа к <class> в Django при попытке встроить модели
-
03-07-2019 - |
Вопрос
Мне нужно иметь возможность создать приложение типа викторины с 20 несколько нечетными вопросами с множественным выбором.
У меня есть 3 модели: Quizzes
, Questions
, и Answers
.
Я хочу в интерфейсе администратора создать тест и встроить элементы викторины и ответа.
Цель состоит в том, чтобы нажать "Добавить тест" и перейти на страницу с 20 полями вопросов, по 4 поля ответа на каждое.
Вот что у меня есть на данный момент:
class Quiz(models.Model):
label = models.CharField(blank=true, max_length=50)
class Question(models.Model):
label = models.CharField(blank=true, max_length=50)
quiz = models.ForeignKey(Quiz)
class Answer(models.Model):
label = models.CharField(blank=true, max_length=50)
question = models.ForeignKey(Question)
class QuestionInline(admin.TabularInline):
model = Question
extra = 20
class QuestionAdmin(admin.ModelAdmin):
inlines = [QuestionInline]
class AnswerInline(admin.TabularInline):
model = Answer
extra = 4
class AnswerAdmin(admin.ModelAdmin):
inlines = [AnswerInline]
class QuizAdmin(admin.ModelAdmin):
inlines = [QuestionInline, AnswerInline]
admin.site.register(Question, QuestionAdmin)
admin.site.register(Answer, AnswerAdmin)
admin.site.register(Quiz, QuizAdmin)
Я получаю следующую ошибку при попытке добавить тест:
class 'quizzer.quiz.models.Answer'> has no ForeignKey to <class 'quizzer.quiz.models.Quiz'>
Выполнимо ли это, или я пытаюсь извлечь слишком много из приложения Django Admin?
Решение
Вы не можете " вложенные " inline в админке Django (т.е. у вас не может быть викторины со встроенными вопросами, при этом каждый встроенный вопрос имеет встроенные ответы). Поэтому вам нужно понизить прицел до наличия встроенных Вопросов (тогда, если вы перейдете к просмотру одного Вопроса, у него могут быть встроенные Ответы).
Итак, с вашими моделями все в порядке, но ваш код администратора должен выглядеть следующим образом:
class QuestionInline(admin.TabularInline):
model = Question
extra = 20
class AnswerInline(admin.TabularInline):
model = Answer
extra = 4
class QuestionAdmin(admin.ModelAdmin):
inlines = [AnswerInline]
class AnswerAdmin(admin.ModelAdmin):
pass
class QuizAdmin(admin.ModelAdmin):
inlines = [QuestionInline]
Для AnswerAdmin не имеет смысла иметь AnswerInline, или QuestionAdmin иметь QuestionInline (если это не были модели с независимым внешним ключом). И у QuizAdmin не может быть AnswerInline, потому что у ответа нет внешнего ключа к Quiz.
Если бы Django действительно поддерживал вложенные строки, логический синтаксис был бы для QuestionInline, чтобы принимать " inlines " атрибут, который вы бы установить на [AnswerInline]. Но это не так.
Также обратите внимание, что " extra = 20 " означает, что у вас будет 20 пустых форм Вопросов в нижней части каждого Теста, каждый раз, когда вы загружаете его (даже если у него уже есть 20 фактических Вопросов). Может быть, это то, что вы хотите - создает длинную страницу, но позволяет легко добавлять множество вопросов одновременно.
Другие советы
Давайте пройдем через это шаг за шагом.
Ошибка:"Ответ не имеет отношения к Тестированию".
Это верно.Модель ответов не имеет никакого отношения к Тестированию.В нем есть Возможность задавать Вопросы, но не Викторина.
Почему для ответа на тест нужен FK?
У администратора викторины есть строка ответа и строка вопроса.Чтобы у администратора были встроенные строки, это означает, что встроенные модели (Answer и Question) должны иметь FK для родительского администратора.
Давайте проверим.Вопрос имеет отношение к Викторине.
И.Ответ не имеет отношения к Тестированию.Итак, ваш администратор викторины требует FK, которого нет в вашей модели.В этом и заключается ошибка.
Правильно: пытаться извлечь слишком много из приложения администратора :) Для встроенных моделей требуется внешний ключ к родительской модели.