Home > Back-end >  Send model property value to other model and display it in it's form
Send model property value to other model and display it in it's form

Time:11-11

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
  • Related