在文章MySQL数据库入门(4)——自关联中,我们初步接触了自关联,而在【Django入门】——模型类的关联关系简介中我们知道数据表之间的关系中有一种是一对多。
实际上,自关联就是一种特殊的一对多关系。本文就将通过Django框架,通过自关联实现这样一个需求:
127.0.0.1:8000/areas
时显示合肥市的上级地区和下级地区,如下所示:当前地区
合肥市父级地区
安徽省子级地区
- 市辖区
- 长丰县
- 肥东县
- 肥西县
- 庐江县
- 巢湖市
为简便起见,此处依然使用【Django入门】——通过模型类查询MySQL数据库基本操作中用到的test3
项目和MySQL数据库db4_test3
。
为生成与MySQL数据库入门(4)——自关联中的案例相同结构的数据表,可以首先定义一个模型类AreaInfo
。
# models.py
......
class AreaInfo(models.Model):
"""地区模型类"""
# 地区名称
area_title = models.CharField(max_length=20)
# 关系属性,当前地区的父级地区
area_parent = models.ForeignKey('self', models.CASCADE, null=True, blank=True)
需要注意的是:
AreaInfo
类中也应该有一个ForeignKey
创建的类属性,名为area_parent
;area_parent
对应的关联关系字段和AreaInfo
生成的数据表发生关联,则ForeignKey
的第一个参数应该为'self'
。迁移生成表的流程在此不做赘述,下面是成功生成数据表后查看的表结构。
mysql> show tables;
+----------------------------+
| Tables_in_db4_test3 |
+----------------------------+
......
| booktest_areainfo |
| booktest_bookinfo |
| booktest_heroinfo |
......
+----------------------------+
13 rows in set (0.00 sec)
mysql> desc booktest_areainfo;
+----------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| area_title | varchar(20) | NO | | NULL | |
| area_parent_id | int(11) | YES | MUL | NULL | |
+----------------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
为了后续演示,需要向上述生成的数据表booktest_areainfo
中插入示例数据。
mysql> source areas.sql;
插入数据的语句可从此处获取,且需要注意的是,当使用上述批量插入的文件时,需要保证文件存放的路径和在终端连接MySQL的路径一致。
# views.py
from django.shortcuts import render
from booktest.models import AreaInfo
# Create your views here.
def areas(request):
"""获取合肥市的上下级地区"""
# 1.获取合肥市的信息
area = AreaInfo.objects.get(area_title='合肥市')
# 2.查询合肥市的上级地区
parent_area = area.area_parent
# 3.查询合肥市的下级地区
child_area = area.areainfo_set.all()
# 4.使用模板
return render(request=request,
template_name='booktest/areas.html',
context={
'area': area,
'parent_area': parent_area,
'child_area': child_area
})
首先,在和应用booktest
同级的路径下新建目录templates
,然后在templates
下新建目录booktest
,最后在booktest
下新建areas.html
文件。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自关联案例title>
head>
<body>
<h1>当前地区h1>
{{area.area_title}}<br/>
<h1>父级地区h1>
{{parent_area.area_title}}
<h1>子级地区h1>
<ul>
{%for child in child_area%}
<li>{{child.area_title}}li>
{%endfor%}
ul>
body>
html>
需要注意的是,为了让Django框架能在运行时找到templates
目录下的模板文件,需要在项目的settings.py
文件中作如下修改:
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
......
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 设置模板目录,
......
},
]
urls.py
文件# 项目的urls.py文件
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^', include('booktest.urls')), # 包含booktest的urls文件
]
urls.py
文件from django.conf.urls import url
from booktest import views
urlpatterns = [
url(r'^areas$', views.areas), # 关联url和视图函数areas
]
至此,需求实现。