Django: Comment cascade une mise à jour par le biais de multiples modèles?

0

La question

Je suis en train d'écrire un Django en fonction de l'application pour garder une trace de l'objet (Objekt) et de leurs tâches de maintenance. Objekts peut être lié à un lieu.

Emplacement (0/1) --- (n) Objet (1) --- (n) la Tâche

Emplacement, de l'Objet et de la Tâche tous ont un champ d'état avec les valeurs suivantes:

    RED = "red"
    YELLOW = "yellow"
    GREEN = "green"
    STATUS = [
        (RED, "Overdue tasks"),
        (YELLOW, "Pending tasks"),
        (GREEN, "All good"),
    ]

Je veux que la carte de Localisation du marqueur de sa couleur change en fonction de l'état des Objekts et ultimatelly Tâches.

J'ai essayé de suivre django meilleures pratiques et de créer un modèle de graisse.

from django.db import models
from locationapp.models import Location
from taskapp.models import Task
from rules.contrib.models import RulesModel

class Objekt(RulesModel):
    RED = "red"
    YELLOW = "yellow"
    GREEN = "green"
    STATUS = [
        (RED, "Overdue tasks"),
        (YELLOW, "Pending tasks"),
        (GREEN, "All good"),
    ]
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True)
    location = models.ForeignKey(
        Location, on_delete=models.SET_NULL, null=True, blank=True
    )
    status = models.CharField(max_length=6, choices=STATUS, default=GREEN)

    def set_status(self):
        if Task.objects.filter(objekt=self.id).filter(status=Task.RED).exists():
            self.status = Objekt.RED
        elif Task.objects.filter(objekt=self.id).filter(status=Task.YELLOW).exists():
            self.status = Objekt.YELLOW
        else:
            self.status = Objekt.GREEN

Mais de toute façon je ne suis pas sûr de mon concept ici... Comment une mise à jour sur la Tâche de déclencher une mise à jour sur l'Objet. Et comment serait l'Objet de plus amples déclencher la mise à jour sur l'Emplacement - si nécessaire, à tous?

django model python
2021-11-22 21:49:18
1

La meilleure réponse

1

Une solution possible consiste à utiliser des signaux. J'ai mis en œuvre comme suit, sans céleri pour l'instant:

# objektapp/apps.py
from django.apps import AppConfig


class ObjektappConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'objektapp'

    def ready(self):
        import objektapp.signals
# objektapp/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.db import transaction
from taskapp.models import Task
from objektapp.models import Objekt

@receiver(post_save, sender=Task)
def set_status(sender, instance, created, **kwargs):
    # TODO: Use celery for async operation: https://docs.djangoproject.com/en/3.2/topics/db/transactions/
    transaction.on_commit(lambda: objekt_update_status(instance))

def objekt_update_status(task_instance):
    objekt = Objekt.objects.get(id=task_instance.objekt.id)

    new_objekt_status = Objekt.GREEN
    if Task.objects.filter(objekt=task_instance.objekt.id, status=Task.RED).exists():
        new_objekt_status = Objekt.RED
    elif Task.objects.filter(objekt=task_instance.objekt.id, status=Task.YELLOW).exists():
        new_objekt_status = Objekt.YELLOW

    if objekt.status != new_objekt_status:
        objekt.status = new_objekt_status
        objekt.save()

Une semblable installation que j'ai fait sur l'Emplacement de modèle, qui a également réagit sur un post_save signal de l'Objet. Je ne suis pas sûr si c'est le meilleur endroit pour stocker les objekt_update_status() dans l'signals.py fichier, mais en essayant de le mettre dans le models.py fini avec la circulaire d'erreur d'importation.

2021-11-24 11:19:32

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................