在Django中没有一对多关系,只有多对一关系。在子表上定义外键很奇怪的情况下,我们应该选择多对多吗?
例如:
书有很多页。如果我们在Page模型上定义外键,那么页面有一本书,这不是一件直观的事情(或说(。
选项 1:
class Book(models.Model):
name = models.CharField(max_length=100)
date_published = models.DateTimeField(default=timezone.now)
class Page(models.Model):
page_number = models.IntegerField()
page_text = RichTextField()
book = models.ForeignKey(Book, on_delete=models.CASCADE)
选项 2
class Book(models.Model):
name = models.CharField(max_length=100)
date_published = models.DateTimeField(default=timezone.now)
pages = models.ManytoMany(Page)
class Page(models.Model):
page_number = models.IntegerField()
page_text = RichTextField()
在选项2中,我可以通过book.pages访问书籍的页面。
在选项 1 中,我不知道如何访问页面,也许是 book.pages_set.objects.all(( 这并不漂亮。
我问了一个程序员同事,他说就用多对多。我了解每种方法的含义,我也了解两者在数据库中发生的事情方面的区别。我的问题是什么是更好/标准的方法。
我首选第一个选项,因为许多书籍没有公共页面及其包含。 因此,使用第一个选项,您可以使用以下查询集访问书籍页面
pages = book.page_set.all()
在这里,您还可以在外键字段中使用related_name参数为:
book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name="pages")
然后可以使用以下方法获取书籍页面
pages = book.pages.all()
我想使用第一个例子。由于书籍没有通用页面。要将书籍连接到页面,您必须使用向后关系。在此关系中,使用_set方法。所有型号名称和归档名称必须为小写字母,尽管它们是大写字母。
m=book.page_set.all()
现在,您可以使用m使用"书籍中的页面"的所有属性。 有关反向或反向关系的更多信息,请访问此处
在您的视图中,您可以传递书籍的 ID,并在查询中使用它来过滤它们链接到它的页面。
例如:
def show_pages(request, book_id):
pages = Pages.objects.filter(book=book_id)