在 Django 中,一对多关系通常通过外键(ForeignKey)来实现。以下是一个完整的示例,展示如何定义模型、创建一对多关系,并使用 Django ORM 进行连表查询。
1. 定义模型
假设我们有两个模型:Author
和 Book
。一个作者可以有多本书,这就是一对多的关系。
models.py
python
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. 创建和应用迁移
在定义好模型后,需要创建和应用数据库迁移。
bash
python manage.py makemigrations
python manage.py migrate
3. 创建一些示例数据
你可以使用 Django 管理后台或 Django shell 来创建一些示例数据。
使用 Django shell
bash
python manage.py shell
python
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
python
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
python
from django.urls import path
from myapp import views
urlpatterns = [
path('author/<int:author_id>/', views.author_books, name='author_books'),
]
author_books.html
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
python
def all_books(request):
# 获取所有书籍及其对应的作者
books = Book.objects.select_related('author').all()
return render(request, 'all_books.html', {'books': books})
all_books.html
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
python
urlpatterns = [
path('author/<int:author_id>/', views.author_books, name='author_books'),
path('books/', views.all_books, name='all_books'),
]