1

I am using Djano to develop a simple web app to display and manage database data. I hooked up a MySQL db and used inspectdb to auto generate a model based on the database tables and this is what I got back, which looks good.

# 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'),)

In the admin.py file for this app I included the models like so, so that I could at least see the data up there.

# -*- 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)

When I access the default Django admin page, I'll see the tables registered on admin page. I click on Bookings and see the multiple records, without names (for other reasons), but if I click on one of them I get the MultipleObjectsReturned Error

I've read everything I could find, and the closest thing to a reason I could find for why this is happening has to do with there being composite keys in some of the models. But, again, I don't know if that's the actual reason, I could also be missing something? I don't know.

Ian Hoyos
  • 95
  • 1
  • 2
  • 8

2 Answers2

1

I guess the reason is that data of Booking table not consistent with your model declaration. Django's admin detail view retrieves model by primary key.

You marked hotelno as PK:

hotelno = models.OneToOneField('Hotel', models.DO_NOTHING, db_column='hotelNo', primary_key=True)

Since some data already exists in Booking table, you have to make sure that hotelno values (hotelNo column) are unique or you will get MultipleObjectsReturned exception for non-unique pk values. Also make sure you've read this part of the documentation https://docs.djangoproject.com/en/1.11/ref/models/options/#managed

Sergei Zherevchuk
  • 562
  • 1
  • 5
  • 14
1

It looks like your booking table does not have a primary key and inspectdb guessed wrong when affecting it to the hotelno column of your booking table.

When the admin try to get the record by it's id it get multiple result since different booking can reference the same hotel multiple time.

What I would do on the booking model :

  • change hotelno and roomno to ForeignKey
  • remove the primary on hotelno

The new problem is now you have a model with no primary key. Django does not allow that. If you can alter the MySQL table add a primary key column to it and alter the booking model accordingly. If you can't alter the table I see no easy way to make it works.

Niko B
  • 751
  • 5
  • 9
  • I can definitely alter the Database as need be. I'm just new to Django so I wasn't sure what would work. Let me try this and I'll get back to you. – Ian Hoyos Dec 02 '17 at 04:54