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, добавьте в нее столбец первичного ключа и измените модель бронирования соответствующим образом. Если вы не можете изменить таблицу, я не вижу простого способа заставить ее работать.

Другие вопросы по тегам