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
- 额外优化建议:
- 可以删掉
DeliveryCreateView的get_success_url中传递的distance参数,避免URL参数被恶意篡改,直接通过Delivery的ID就能拿到准确的distance值,也能缩短URL长度。 CreateView本身已经继承了FormView的所有功能,不需要同时继承两个类,删除多余的父类避免逻辑冲突。- 如果距离计算比较耗时,建议把计算好的距离值存到
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
相关产品推荐
相关产品推荐

