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

如何在Django视图中访问一对一关联模型的字段值?

正确实现方案梳理

我来帮你一步步调整代码,解决访问关联密钥UUID和统计可用密钥数量的问题:

一、模型层调整(models.py)

首先咱们先把模型里的小问题修正,确保关联关系和字段完整:

  1. 优化OneToOneField的关联命名
    你当前的related_name='request'有点反直觉,改成related_name='key_instance'会更清晰——这样从KeyRequest实例访问对应的KeyInstance时,语法key_request.key_instance更符合语义。
    另外,代码里还有几处缺失字段:KeyInstance的__str__用到了self.roomkey.room_name,KeyRequest的__str__用到了date_requested和requester,这些字段必须补全,否则运行时会报错。

调整后的KeyInstance模型:

import uuid
from datetime import date
from django.db import models
from django.urls import reverse

class KeyInstance(models.Model):
    keyrequest = models.OneToOneField(
        'KeyRequest',
        verbose_name='Key requests',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='key_instance'  # 更直观的关联名
    )
    LOAN_STATUS = (
        ('a', 'Available'),
        ('o', 'On loan'),
        ('r', 'Reserved'),
    )
    status = models.CharField(
        max_length=1,
        choices=LOAN_STATUS,
        help_text='Key availability',
        verbose_name="Key status",
        blank=True,
        default='a'  # 给状态加默认值,避免空值问题
    )
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        help_text="Unique ID for this particular key"
    )
    roomkey = models.ForeignKey('RoomKey', on_delete=models.SET_NULL, null=True)  # 补全缺失字段
    due_back = models.DateField(null=True, blank=True)  # 补全is_overdue和排序用到的字段

    class Meta:
        ordering = ["due_back"]
        permissions = (("can_mark_returned", "Set key as returned"),)

    @property
    def is_overdue(self):
        if self.due_back and date.today() > self.due_back:
            return True
        return False

    def __str__(self):
        return '{1} ({0})'.format(self.id, self.roomkey.room_name)

    def get_absolute_url(self):
        return reverse('keys', args={'pk': self.id})

调整后的KeyRequest模型(补全缺失字段):

class KeyRequest(models.Model):
    """ Model that will hold the key requests """
    roomkey = models.ForeignKey('RoomKey', verbose_name="Room", on_delete=models.SET_NULL, null=True)
    requester = models.CharField(max_length=100)  # 补全请求人字段
    date_requested = models.DateField(auto_now_add=True)  # 自动记录请求时间

    def __str__(self):
        return '{2}-{0} ({1})'.format(self.roomkey.room_name, self.date_requested, self.requester)

    def get_absolute_url(self):
        return reverse('key-request-detail', args=[str(self.id)])

二、视图层优化(views.py)

你当前同时定义了KeyRequestDetailView和RequestDetail,会导致路由冲突。咱们直接用Django的通用DetailView,重写get_context_data方法把可用密钥数量加到上下文里,这是通用视图传递额外数据的标准做法:

from django.views.generic import DetailView
from .models import KeyRequest, KeyInstance

class KeyRequestDetailView(DetailView):
    model = KeyRequest
    template_name = "catalog/roomkey_request_detail.html"

    def get_context_data(self, **kwargs):
        # 先获取默认上下文(包含当前KeyRequest实例)
        context = super().get_context_data(**kwargs)
        # 添加可用密钥统计数据到上下文
        context['num_key_available'] = KeyInstance.objects.filter(status__exact='a').count()
        return context

这样就不需要单独的RequestDetail视图了,路由里直接配置KeyRequestDetailView即可。

三、模板层使用(roomkey_request_detail.html)

现在可以直接在模板里访问关联的密钥UUID,以及统计的可用数量。加个判断是因为KeyInstance和KeyRequest的关联允许为null,避免模板报错:

<!-- 显示关联密钥的UUID -->
{% if keyrequest.key_instance %}
    关联密钥UUID: {{ keyrequest.key_instance.id }}
{% else %}
    暂无关联密钥
{% endif %}

<!-- 显示可用密钥总数 -->
可用密钥数量: {{ num_key_available }}

如果你坚持用原来的related_name='request',模板里就改成{{ keyrequest.request.id }},但还是建议用更直观的命名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:08:02