如何描述Django模型中的多对多sql关系

时间:2018-04-07 08:30:38

标签: python django django-models many-to-many

我在mysql数据库中创建了类型和书籍表

create table genres
(
  gID varchar(20) not null,
  gName varchar(100) not null,
  primary key(gID)
);


create table books
(
  ISBN varchar(20) not null,
  BookTitle varchar(255) not null,
  Description text,
  PageCount int not null,
  Rating  numeric(3, 2),
  Language varchar(20),
  CoverImage varchar(255),
  Price numeric(5, 2),
  PublishedDate date,
  publisher_pID varchar(20) not null,
  VoteCount int default 0,
  primary key(ISBN),
  foreign key(publisher_pID) references publishers(pID)
);

create table books_genres
(
  Book_ISBN varchar(20) not null,
  Genre_gID varchar(20) not null,
  primary key(Book_ISBN, Genre_gID),
  foreign key(Book_ISBN) references books(ISBN) on delete cascade,
  foreign key(Genre_gID) references genres(gID) on delete cascade
);

我使用" python manage.py inspectdb>在django中导入它们models.py ",然后执行所有需要的迁移。导入的模型(编辑一点):

class Genres(models.Model):
    gid = models.CharField(db_column='gID', primary_key=True, max_length=20)  # Field name made lowercase.
    gname = models.CharField(db_column='gName', max_length=100)  # Field name made lowercase.

    class Meta:
        verbose_name_plural = "Genres"
        db_table = 'genres'


class Books(models.Model):
    isbn = models.CharField(db_column='ISBN', primary_key=True, max_length=20)  # Field name made lowercase.
    booktitle = models.CharField(db_column='BookTitle', max_length=255)  # Field name made lowercase.
    description = models.TextField(db_column='Description', blank=True, null=True)  # Field name made lowercase.
    pagecount = models.IntegerField(db_column='PageCount')  # Field name made lowercase.
    rating = models.DecimalField(db_column='Rating', max_digits=3, decimal_places=2, blank=True, null=True)  # Field name made lowercase.
    language = models.CharField(db_column='Language', max_length=20, blank=True, null=True)  # Field name made lowercase.
    coverimage = models.CharField(db_column='CoverImage', max_length=255, blank=True, null=True)  # Field name made lowercase.
    price = models.DecimalField(db_column='Price', max_digits=5, decimal_places=2, blank=True, null=True)  # Field name made lowercase.
    publisheddate = models.DateField(db_column='PublishedDate', blank=True, null=True)  # Field name made lowercase.
    publisher_pid = models.ForeignKey(Publishers, on_delete=models.CASCADE, db_column='publisher_pID')  # Field name made lowercase.
    votecount = models.IntegerField(db_column='VoteCount', blank=True, null=True)  # Field name made lowercase.

    class Meta:
        verbose_name_plural = "Books"
        db_table = 'books'


class BooksGenres(models.Model):
    book_isbn = models.ForeignKey(Books, on_delete=models.CASCADE, db_column='Book_ISBN', primary_key=True)  # Field name made lowercase.
    genre_gid = models.ForeignKey(Genres, on_delete=models.CASCADE, db_column='Genre_gID', primary_key=True)  # Field name made lowercase.

    class Meta:
        verbose_name_plural = "Books_Genres"
        db_table = 'books_genres'
        unique_together = (('book_isbn', 'genre_gid'),)

现在,问题出在书籍和流派的多对多关系表中。 Django不支持多个密钥。但我的数据库包含4000多个关系。 每本书都有多种类型(最多10个)。

服务器运行正常,但是当我尝试访问django管理页面中的Books_Genre模型(下面附带的图像)时。它返回 MultipleObjectsReturned 错误:

MultipleObjectsReturned at /admin/first_app/booksgenres/9507399194/change/
get() returned more than one BooksGenres -- it returned 8!

图片:Django-admin site snap

通过运行命令,我可以很容易地在mysql中看到所有类型(比如isbn = 9507399194):

SELECT
  isbn,
  BookTitle,
  gName AS genreCount
FROM books
JOIN books_genres
  ON books.isbn = books_genres.book_isbn
JOIN genres
  ON genres.gid = books_genres.genre_gid
WHERE isbn = 9507399194;

输出:

+------------+---------------+---------------------+
| isbn       | BookTitle     | genreCount          |
+------------+---------------+---------------------+
| 9507399194 | Fuenteovejuna | Classics            |
| 9507399194 | Fuenteovejuna | Plays               |
| 9507399194 | Fuenteovejuna | Fiction             |
| 9507399194 | Fuenteovejuna | Academic            |
| 9507399194 | Fuenteovejuna | Drama               |
| 9507399194 | Fuenteovejuna | Literature          |
| 9507399194 | Fuenteovejuna | Cultural            |
| 9507399194 | Fuenteovejuna | European Literature |
+------------+---------------+---------------------+

那么如何在Django中处理MultipleObjectsReturned。我是否需要对books_genres的表定义进行一些更改?

我在Django上读到了关于ManytomanyField的内容,但无法理解如何应用它。请帮助我,其他工作正常,因为我可以访问django-admin网站上的其他表

0 个答案:

没有答案