在 Django 中,一对多关系通常通过外键(ForeignKey)来实现。以下是一个完整的示例,展示如何定义模型、创建一对多关系,并使用 Django ORM 进行连表查询。
1. 定义模型
假设我们有两个模型:Author
和 Book
。一个作者可以有多本书,这就是一对多的关系。
models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
publication_date = models.DateField()
author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)
def __str__(self):
return self.title
2. 创建和应用迁移
在定义好模型后,需要创建和应用数据库迁移。
python manage.py makemigrations
python manage.py migrate
3. 创建一些示例数据
你可以使用 Django 管理后台或 Django shell 来创建一些示例数据。
使用 Django shell
python manage.py shell
from myapp.models import Author, Book
# 创建作者
author1 = Author.objects.create(name="Author One", email="author1@example.com")
author2 = Author.objects.create(name="Author Two", email="author2@example.com")
# 创建书籍
Book.objects.create(title="Book One", publication_date="2023-01-01", author=author1)
Book.objects.create(title="Book Two", publication_date="2023-02-01", author=author1)
Book.objects.create(title="Book Three", publication_date="2023-03-01", author=author2)
4. 连表查询
现在可以使用 Django ORM 进行连表查询。
views.py
from django.shortcuts import render
from myapp.models import Author, Book
def author_books(request, author_id):
# 获取指定作者
author = Author.objects.get(id=author_id)
# 获取该作者的所有书籍
books = author.books.all()
return render(request, 'author_books.html', {'author': author, 'books': books})
urls.py
from django.urls import path
from myapp import views
urlpatterns = [
path('author/<int:author_id>/', views.author_books, name='author_books'),
]
author_books.html
<!DOCTYPE html>
<html>
<head>
<title>Author Books</title>
</head>
<body>
<h1>Books by {{ author.name }}</h1>
<ul>
{% for book in books %}
<li>{{ book.title }} ({{ book.publication_date }})</li>
{% endfor %}
</ul>
</body>
</html>
5. 复杂查询示例
如果需要进行更复杂的查询,比如获取所有书籍及其对应的作者,可以使用 select_related
或 prefetch_related
。
使用 select_related
def all_books(request):
# 获取所有书籍及其对应的作者
books = Book.objects.select_related('author').all()
return render(request, 'all_books.html', {'books': books})
all_books.html
<!DOCTYPE html>
<html>
<head>
<title>All Books</title>
</head>
<body>
<h1>All Books</h1>
<ul>
{% for book in books %}
<li>{{ book.title }} by {{ book.author.name }} ({{ book.publication_date }})</li>
{% endfor %}
</ul>
</body>
</html>
6. 更新 urls.py
urlpatterns = [
path('author/<int:author_id>/', views.author_books, name='author_books'),
path('books/', views.all_books, name='all_books'),
]