es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Django: Cómo activar una función cada vez que se modifican ciertos objetos desde la interfaz de Wagtail.

Tengo una larga lista de objetos de “Cotización”.

El precio de una cotización depende de docenas de objetos hijos (y nietos). El más bajo siendo la tarifa/hora.

Cuando cambio los objetos hijos de una cotización, como la tarifa/hora, el precio de la cotización cambia.

Me gustaría recalcular el precio de cada cotización que se vea afectada por cualquier cambio que haga en sus objetos constituyentes automáticamente. Estoy utilizando Wagtail para la administración de objetos.

No estoy seguro de cómo hacer eso, ¿debería usar señales? ¿Gancho de Wagtail?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Solución para recalcular los precios de cotización en Wagtail

    Como experto en informática especializado en Django, Triggers, Wagtail, Django-Signals y Wagtail-Admin, existen varias formas de recalcular el precio de cada cotización que se vea afectada por cualquier cambio que realices en sus objetos constituyentes de forma automática. Una opción es utilizar Django-Signals, mientras que otra es utilizar Wagtail Hooks.

    Utilizando Django-Signals:

    Django-Signals proporciona una forma de notificar ciertas partes de tu aplicación cuando ocurren ciertas acciones en otro lugar de tu código. Mediante el uso de señales, puedes recalcular los precios de las cotizaciones afectadas automáticamente, sin necesidad de ninguna entrada adicional por parte del usuario.

    Para utilizar señales, tendrás que crear un archivo models.py en tu aplicación y escribir una función que calcule los nuevos precios. La función deberá aceptar el objeto Quotation y los objetos hijos modificados como argumentos, y luego calcular el nuevo precio en función de la tarifa/hora de los objetos hijos.

    Aquí tienes un ejemplo de fragmento de código que muestra la lógica de cálculo:

    from django.db.models.signals import m2m_changed
    from django.dispatch import receiver
    from .models import Quotation, Children
    
    @receiver(m2m_changed, sender=Quotation.children.through)
    def calculate_quotation_price(sender, instance, **kwargs):
        if kwargs.get('action', '') == 'post_add':
            children = instance.children.all()
            rate = min([child.rate for child in children])
            instance.price = instance.quantity * instance.duration * rate
            instance.save()
    

    Este código escucha la señal m2m_changed que se envía cuando se añade un objeto a la relación Quotation.children, y luego calcula el nuevo precio en función de la tarifa/hora actualizada.

    Utilizando Wagtail Hooks:

    Los hooks de Wagtail proporcionan una forma de modificar el comportamiento de ciertas partes de la interfaz de administración de Wagtail. Mediante el uso de hooks, puedes recalcular los precios de las cotizaciones afectadas automáticamente cada vez que un usuario cambie la tarifa/hora de un objeto hijo.

    Para utilizar hooks, tendrás que crear un archivo wagtail_hooks.py en tu aplicación y escribir una función que calcule los nuevos precios. La función deberá aceptar el objeto Quotation y los objetos hijos modificados como argumentos, y luego calcular el nuevo precio en función de la tarifa/hora de los objetos hijos.

    Aquí tienes un ejemplo de fragmento de código que muestra la lógica de cálculo:

    from django.urls import reverse
    from wagtail.admin.edit_handlers import ObjectList
    from wagtail.admin.widgets import Button
    from wagtail.core import hooks
    from .models import Quotation, Children
    
    class RecalculateQuotationsButton(Button):
        label = "Recalcular Cotizaciones"
        icon_name = 'cogs'
        classname = 'button-small'
        attrs = {'title': 'Recalcular los precios de todas las cotizaciones afectadas'}
    
        def render(self, *args, **kwargs):
            url = reverse('recalculate_quotations')
            return super().render(url=url, *args, **kwargs)
    
    @hooks.register('register_page_listing_buttons')
    def register_recalculate_quotations_button(page, page_perms, is_parent=False):
        if page.__class__ is Quotation:
            return RecalculateQuotationsButton()
        return []
    
    @hooks.register('construct_page_listing_buttons')
    def construct_recalculate_quotations_button(buttons, page, page_perms, is_parent=False):
        if page.__class__ is Quotation:
            if 'Recalculate Quotations' in buttons:
                url = reverse('recalculate_quotations')
                buttons.replace_button('Recalculate Quotations', RecalculateQuotationsButton().render(url=url))
        return buttons
    
    @hooks.register('register_admin_urls')
    def register_recalculate_quotations_url():
        return [
            path('recalculate_quotations/', recalculate_quotations_view, name='recalculate_quotations')
        ]
    
    def recalculate_quotations_view(request):
        quotations = Quotation.objects.all()
        for quotation in quotations:
            children = quotation.children.all()
            rate = min([child.rate for child in children])
            quotation.price = quotation.quantity * quotation.duration * rate
            quotation.save()
        return redirect('wagtailadmin_explore', 'app_label=your_app&model_name=Quotation')
    
    

    Este código añade un botón “Recalcular Cotizaciones” a la página de administración de objetos Quotation. Cuando se hace clic, se activa una vista que recalcula los precios de todas las cotizaciones afectadas.

    Estos son solo algunos ejemplos de las muchas formas en las que puedes recalcular los precios de las cotizaciones afectadas automáticamente en Wagtail. En última instancia, la mejor solución dependerá de tu caso de uso específico, así que no dudes en experimentar con enfoques diferentes hasta encontrar el que mejor funcione para ti.

Comments are closed.