[英]Django ForeignKey relationship is not working
由于外键关系,应该有一个名为“ book_book_author(s)”的表。 否则,我将无法访问Author.book_set。
class Author(models.Model):
name=models.CharField(max_length=255)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=255)
pub_date = models.DateField()
publisher = models.CharField(max_length=255)
language = models.CharField(max_length=255)
print_length = models.DecimalField(max_digits=6, decimal_places=0)
price = models.DecimalField(max_digits=10, decimal_places=2)
authors=models.ForeignKey(Author, on_delete=models.CASCADE)
def __str__(self):
return self.title
数据库:
mysql> show tables;
+-------------------------------+
| Tables_in_eshop |
+-------------------------------+
| account_user |
| account_user_groups |
| account_user_user_permissions |
| auth_group |
| auth_group_permissions |
| auth_permission |
| book_author |
| book_book |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+-------------------------------+
12 rows in set (0.00 sec)
如何解决此问题?
应该有一个名为'book_book_author(s)的表
否 :如果您编写了ForeignKey
关系,那么Django将在您的book
表中添加一列 author_id
。
现在,如果要获取给定Author
的Book
列表,则Django将构造一个查询,如下所示:
SELECT book.*
FROM book
WHERE author_id = 123
123
是您要查询的Author
的ID。 它不建立这样的额外的表。 这不会是在所有人都有益的,因为这将基本上导致相同的查询(尽管其它表,并与JOIN
,它可以使效率较低 )。
为了提高效率,Django默认会指示数据库还将在author_id
列上构造一个索引 ,以便它可以轻松获取Author
ID的相关Book
。 通常,这意味着在O(log n)甚至O(1)中,可以访问给定作者撰写的书籍列表。 根据所使用的数据库技术,索引(或大量索引)将存储在数据库中,因此查找将非常快。
因此,您可以将some_author.book_set
视为要执行的查询, 而不是表。
注意 :对于
ManyToManyField
,情况有所不同,在这种情况下,它将构造一个额外的表。 这是因为通常,一列不包含任意数量的值(有些数据库可以包含,但设计仍然很糟糕)。
您可以使用some_author.book_set.all()
获得some_author
的书。 此外,没有Author.book_set
(属于至少一位作者的书)。 在这种情况下,这仅意味着所有书籍,因为每本书都属于一个Author
。 如果ForeignKey
为NULL,则可以像Books.objects.filter(author__isnull=False)
那样Books.objects.filter(author__isnull=False)
过滤。
基本上,当您定义外键时,不会创建新表,而是创建相应行的引用。
在您的情况下,您要在Book表上创建Author的引用。 因此,您可以通过以下方式访问作者的所有书籍:
Book.objects.filter(author__id = 'authorid')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.