I'm working on an app where the user will fill a first form of a model, and he will be redirected to the next form where I want to get a value from property of the first model to be passed to the seconde model and display it in it's form.
***Models***
class Delivery(models.Model):
user = models.ForeignKey(
Client, on_delete=models.CASCADE, verbose_name=_("Client"), related_name=_("delivery_user")
)
pickup_address = models.ForeignKey(Address, on_delete=models.CASCADE, related_name=_("pickup_address"))
destination_address = models.ForeignKey(Address, on_delete=models.CASCADE, related_name=_("destination_address"))
operation_date = models.DateField(
_("desired pickup date"), auto_now=False, auto_now_add=False, blank=False, null=False
)
invoice = models.BooleanField(_("check if you want an invoice"), default=False)
created_at = models.DateTimeField(_("Created at"), auto_now_add=True, editable=False)
updated_at = models.DateTimeField(_("Updated at"), auto_now=True)
delivery_key = models.CharField(max_length=200)
@property
def distance(self):
distance = Distance(
m=self.pickup_address.address_point.transform(32148, clone=True).distance(
self.destination_address.address_point.transform(32148, clone=True)
)
)
context = {}
context["distance"] = f"{round(distance.m / 1000, 2)}"
print(context)
return context
def __str__(self):
return str(self.delivery_key)
class DeliveryDetails(models.Model):
delivery = models.ForeignKey(Delivery, on_delete=models.CASCADE, related_name=_("delivery"))
distance = models.DecimalField(_("Distance Approximative "), max_digits=7, decimal_places=2)
delivery_price = models.DecimalField(max_digits=7, decimal_places=2)
created_at = models.DateTimeField(_("Created at"), auto_now_add=True, editable=False)
updated_at = models.DateTimeField(_("Updated at"), auto_now=True)
def __str__(self):
return str(self.created_at)
***Views***
class DeliveryCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView, FormView):
model = Delivery
form_class = UserDeliveryForm
template_name = "deliveries/customer/edit_deliveries.html"
def get_success_url(self):
return reverse(
"delivery:delivery-details",
kwargs={"pk": self.object.pk, "distance": self.object.distance},
)
def test_func(self):
return self.request.user.is_active
class DetailsDeliveryCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView, FormView):
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_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
delivery = Delivery.objects.filter(id=self.kwargs["pk"])
context["form"].fields["delivery"].queryset = delivery
distance = Delivery.objects.get(id=self.kwargs["pk"]).distance["google_distance"]
return context
Is there a way to get the Delivery instance in the DetailleDelivery (invoice key and the distance ) and display them to the user when he is filling the DeliveryDetailsForm ? I want to avoid hitting the DB many times to get the same data if it's possible.
CodePudding user response:
You can just pass the delivery into the context, like so:
context ['delivery'] = delivery
Then in your template you can use {{delivery.distance}} and whatever else you need. You'll have the entire object.
Obviously this is only for a create view where the related parent object does not exist yet. In a detail view you have access to the parent through the child.
Also you may want to use get_object_or_404 instead of filter to get your Delivery instance, in case someone tries a pk that doesn't exist.
Furthermore, instead of inserting your delivery in the form, just leave it off entirely and override your form_valid() to insert the delivery relationship prior to saving, if that makes sense.
CodePudding user response:
In your DetailsDeliveryCreateView
set the form initial values:
def get_initial(self):
initial = super(DetailsDeliveryCreateView, self).get_initial()
initial = initial.copy()
delivery = Delivery.objects.get(id=self.kwargs["pk"])
distance = delivery.distance["google_distance"]
initial['distance'] = delivery
initial['distance'] = distance
return initial