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

Django如何将Delivery模型属性传递至DeliveryDetails模型并在其表单展示

实现方案
  • 首先修复视图层重复查询的问题,原代码中DetailsDeliveryCreateView的get_context_data方法对同一个Delivery ID执行了2次数据库查询,改为单次查询后复用实例即可,同时修正原代码中distance属性取值的key错误(你的distance属性返回的字典key是distance不是google_distance)。
  • 可以通过重写get_initial方法给表单字段设置默认值,同时把需要展示的Delivery实例属性放到模板上下文里,直接在页面渲染即可,不需要额外查询。

修改后的视图代码如下:

class DetailsDeliveryCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
    model = DeliveryDetails
    form_class = DeliveryDetailsForm
    template_name = "deliveries/responsable/edit_deliveries_details.html"
    success_url = reverse_lazy("account:dashboard")

    def test_func(self):
        return self.request.user.is_active

    # 给表单设置初始值
    def get_initial(self):
        initial = super().get_initial()
        # 单次查询Delivery实例,存在实例属性里避免重复查询
        if not hasattr(self, 'delivery_instance'):
            self.delivery_instance = Delivery.objects.select_related('pickup_address', 'destination_address').get(id=self.kwargs["pk"])
        # 给外键delivery设置默认值
        initial['delivery'] = self.delivery_instance
        # 给distance设置默认值,注意转为float类型适配模型Decimal字段
        initial['distance'] = float(self.delivery_instance.distance['distance'])
        return initial

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 直接复用已经查询好的实例,不用再查数据库
        if not hasattr(self, 'delivery_instance'):
            self.delivery_instance = Delivery.objects.select_related('pickup_address', 'destination_address').get(id=self.kwargs["pk"])
        # 把需要展示的属性塞到上下文,模板里直接调用
        context['delivery'] = self.delivery_instance
        context['distance'] = self.delivery_instance.distance['distance']
        context['need_invoice'] = self.delivery_instance.invoice
        # 限制delivery外键的可选范围
        context["form"].fields["delivery"].queryset = Delivery.objects.filter(id=self.kwargs["pk"])
        return context
  • 额外优化建议:
    1. 可以删掉DeliveryCreateView的get_success_url中传递的distance参数,避免URL参数被恶意篡改,直接通过Delivery的ID就能拿到准确的distance值,也能缩短URL长度。
    2. CreateView本身已经继承了FormView的所有功能,不需要同时继承两个类,删除多余的父类避免逻辑冲突。
    3. 如果距离计算比较耗时,建议把计算好的距离值存到Delivery模型的字段里,创建Delivery实例的时候就计算好存起来,不用每次访问都重新计算坐标距离,能进一步提升性能。
  • 模板层展示:如果你需要把invoice和distance作为只读信息展示,直接在模板里调用上下文变量即可,示例如下:
<!-- 只展示不用提交的信息 -->
<div>
  <p>是否需要发票:{% if need_invoice %}是{% else %}否{% endif %}</p>
  <p>预估距离:{{ distance }} 公里</p>
</div>
<!-- 表单部分会自动填充你在get_initial里设置的默认值 -->
{{ form.as_p }}

内容的提问来源于stack exchange,提问作者E.Mohammed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:15:04