Django MultipleObjectsReturned при использовании устаревшей базы данных
Я использую Djano для разработки простого веб-приложения для отображения и управления данными базы данных. Я подключил базу данных MySQL и использовал inspectdb для автоматической генерации модели на основе таблиц базы данных, и это то, что я получил, что выглядит неплохо.
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
# * Rearrange models' order
# * Make sure each model has one field with primary_key=True
# * Make sure each ForeignKey has `on_delete` set to the desired behavior.
# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from __future__ import unicode_literals
from django.core.exceptions import MultipleObjectsReturned
from django.db import models
class Booking(models.Model):
class Meta:
managed = False
db_table = 'Booking'
unique_together = (('hotelno', 'guestno', 'datefrom'),)
hotelno = models.OneToOneField('Hotel', models.DO_NOTHING, db_column='hotelNo', primary_key=True) # Field name made lowercase.
guestno = models.IntegerField(db_column='guestNo') # Field name made lowercase.
datefrom = models.DateTimeField(db_column='dateFrom') # Field name made lowercase.
dateto = models.DateTimeField(db_column='dateTo', blank=True, null=True) # Field name made lowercase.
roomno = models.OneToOneField('Room', models.DO_NOTHING, db_column='roomNo') # Field name made lowercase.
list_display =
#def __str__(self):
# return ("".join(hotelno) + "".join(guestno) + "".join(datefrom))
class Guest(models.Model):
guestno = models.AutoField(db_column='guestNo', primary_key=True) # Field name made lowercase.
guestname = models.CharField(db_column='guestName', max_length=255) # Field name made lowercase.
guestaddress = models.CharField(db_column='guestAddress', max_length=255, blank=True, null=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'Guest'
class Hotel(models.Model):
hotelno = models.AutoField(db_column='hotelNo', primary_key=True) # Field name made lowercase.
hotelname = models.CharField(db_column='hotelName', max_length=255, blank=True, null=True) # Field name made lowercase.
city = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = False
db_table = 'Hotel'
class Room(models.Model):
roomno = models.IntegerField(db_column='roomNo', primary_key=True) # Field name made lowercase.
hotelno = models.ForeignKey(Hotel, models.DO_NOTHING, db_column='hotelNo') # Field name made lowercase.
type = models.CharField(max_length=255, blank=True, null=True)
price = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'Room'
unique_together = (('roomno', 'hotelno'),)
В файле admin.py для этого приложения я включил такие модели, чтобы я мог хотя бы увидеть данные там.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
# Register your models here.
from .models import Hotel, Room, Guest, Booking
admin.site.register(Hotel)
admin.site.register(Room)
admin.site.register(Guest)
admin.site.register(Booking)
Когда я получу доступ к странице администратора Django по умолчанию, я увижу таблицы, зарегистрированные на странице администратора. Я нажимаю на "Заказы" и вижу несколько записей без имен (по другим причинам), но если я нажимаю на одну из них, я получаю ошибку MultipleObjectsReturned Error
Я прочитал все, что смог найти, и наиболее близкая причина, по которой я смог найти причину, по которой это происходит, связана с наличием составных ключей в некоторых моделях. Но, опять же, я не знаю, является ли это реальной причиной, я тоже мог что-то упустить? Я не знаю.
2 ответа
Я думаю, причина в том, что данные Booking
таблица не соответствует объявлению вашей модели. Подробное представление администратора Django позволяет получить модель по первичному ключу.
Вы отметили hotelno
как ПК:
hotelno = models.OneToOneField('Hotel', models.DO_NOTHING, db_column='hotelNo', primary_key=True)
Поскольку некоторые данные уже существуют в Booking
стол, вы должны убедиться, что hotelno
значения (столбец hotelNo) являются уникальными или вы получите MultipleObjectsReturned
исключение для неуникальных значений pk. Также убедитесь, что вы прочитали эту часть документации https://docs.djangoproject.com/en/1.11/ref/models/options/
Похоже, что в вашей таблице бронирования нет первичного ключа, и команда inspectdb догадалась неправильно, если указывать ее в столбце hotelno таблицы бронирования.
Когда администратор пытается получить запись по его идентификатору, он получает несколько результатов, так как разные бронирования могут ссылаться на один и тот же отель несколько раз.
Что я буду делать на модели бронирования:
- изменить hotelno и roomno на ForeignKey
- убрать предмет по отельно
Новая проблема - теперь у вас есть модель без первичного ключа. Джанго не позволяет этого. Если вы можете изменить таблицу MySQL, добавьте в нее столбец первичного ключа и измените модель бронирования соответствующим образом. Если вы не можете изменить таблицу, я не вижу простого способа заставить ее работать.