You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django:如何从一对一关联的两个模型取数生成指定表格?

Django 跨模型数据表格实现方案

一、模型是否需要修改?

现有模型仅需修正一处笔误,无需调整关联结构:

  • Car模型中car_exterior_color字段多写了一个等号,修正后补充必要参数和示例选项;
  • CarWash的wash_date需设置允许空值,适配未洗车车辆的无日期场景。

修正后的完整模型代码:

from django.db import models

class Car(models.Model):
    model_name = models.CharField(max_length=100)
    make_name = models.CharField(max_length=100)
    # 定义颜色选项示例,可根据需求扩展
    COLOR_CHOICES = [
        ('blue', 'Blue'),
        ('white', 'White'),
        ('red', 'Red'),
        ('green', 'Green'),
        ('yellow', 'Yellow'),
        ('black', 'Black')
    ]
    car_exterior_color = models.CharField(max_length=20, choices=COLOR_CHOICES)
    
class CarWash(models.Model):
    car_washed = models.BooleanField(default=False)
    wash_date = models.DateTimeField(null=True, blank=True)
    added_wax = models.BooleanField(default=False)
    car = models.OneToOneField(Car, on_delete=models.CASCADE, verbose_name="Car washed")

二、视图层代码实现(views.py)

采用函数视图直观实现,通过select_related预加载关联数据避免N+1查询,同时整理表格所需格式化数据:

from django.shortcuts import render
from .models import Car

def car_wash_table(request):
    # 预加载关联的CarWash数据,提升查询性能
    cars = Car.objects.select_related('carwash').all()
    
    table_data = []
    for car in cars:
        # 处理无洗车记录的情况,避免属性报错
        wash_record = getattr(car, 'carwash', None)
        
        table_data.append({
            'model_name': car.model_name,
            'make_name': car.make_name,
            # 若使用choices,用get_xxx_display()显示友好名称,否则直接取字段值
            'car_ext_col': car.get_car_exterior_color_display(),
            'car_washed': 'Yes' if (wash_record and wash_record.car_washed) else 'No',
            'added_wax': 'Yes' if (wash_record and wash_record.added_wax) else 'No',
            'wash_date': wash_record.wash_date.strftime('%Y-%m-%d') if (wash_record and wash_record.wash_date) else '--'
        })
    
    return render(request, 'car_wash_table.html', {'table_data': table_data})

如果偏好类视图(ListView),可参考以下实现:

from django.views.generic import ListView
from .models import Car

class CarWashTableView(ListView):
    model = Car
    template_name = 'car_wash_table.html'
    
    def get_queryset(self):
        return Car.objects.select_related('carwash').all()
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        table_data = []
        for car in context['object_list']:
            wash_record = getattr(car, 'carwash', None)
            table_data.append({
                'model_name': car.model_name,
                'make_name': car.make_name,
                'car_ext_col': car.get_car_exterior_color_display(),
                'car_washed': 'Yes' if (wash_record and wash_record.car_washed) else 'No',
                'added_wax': 'Yes' if (wash_record and wash_record.added_wax) else 'No',
                'wash_date': wash_record.wash_date.strftime('%Y-%m-%d') if (wash_record and wash_record.wash_date) else '--'
            })
        context['table_data'] = table_data
        return context

三、模板层渲染(car_wash_table.html)

直接使用视图传递的格式化数据生成表格:

<div class="s-table-container">
    <table class="s-table">
        <thead>
            <tr>
                <th>model_name</th>
                <th>make_name</th>
                <th>car_ext_col</th>
                <th>car_washed ?</th>
                <th>added_wax ?</th>
                <th>wash date</th>
            </tr>
        </thead>
        <tbody>
            {% for item in table_data %}
            <tr>
                <td>{{ item.model_name }}</td>
                <td>{{ item.make_name }}</td>
                <td>{{ item.car_ext_col }}</td>
                <td>{{ item.car_washed }}</td>
                <td>{{ item.added_wax }}</td>
                <td>{{ item.wash_date }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</div>

四、关键注意事项

  • 反向关联名称:若CarWash的OneToOneField设置了related_name,需将select_related('carwash')替换为对应的名称;
  • 空值处理:必须通过getattr判断洗车记录是否存在,避免无关联记录时抛出AttributeError;
  • 性能优化:select_related适用于一对一/外键关联,能将两次查询合并为一次,显著提升数据加载效率。

内容的提问来源于stack exchange,提问作者PrertoQuebas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 05:05:19