Home > Net >  Doing polymorphic model, what's the best approach?
Doing polymorphic model, what's the best approach?

Time:10-22

I'm trying to upscale a project that originally was used by an area to assign reports to their respective departments. Those reports I want them to be tasks, to broaden the spectrum of use to all of the organization.

Originally, I was using separate models for reports, updates, report files, update files. (Those tables, had almost the same fields)

Now, I'm trying to have a polymorphic model, as shown below:

#### TASK TYPE (TASK, UPDATE) 
class TipoTarea(models.Model): 
    nombre = models.CharField(max_length=50, unique=True)

    def __str__(self):
        return self.nombre    

###### TASK CATEGORY (TOPIC AND THE AREA WHO IS BEING DIRECTED TO)
class CategoriaTarea(models.Model): 
    nombre = models.CharField(max_length=50, unique=True)
    area = models.ForeignKey(Area, on_delete=models.CASCADE)
    tiempo_atencion = models.IntegerField(default=2)
    
    def __str__(self):
        return self.nombre

##### TASK STATE (CREATED, IN PROCESS, COMPLETED, REASIGNED)
##### REASIGNED STATE, CREATES A NEW TASK WITH A DIFFERENT CATEGORY
class EstadoTarea(models.Model):
    nombre = models.CharField(max_length=50)
    
    def __str__(self):
        return self.nombre

###### TASK
###### TASK PARENT WOULD BE USED FOR UPDATES, BUT HOW CAN REASIGNMENTS BE CLASSIFIED
class Tarea(models.Model):
    tipo = models.ForeignKey(TipoTarea, on_delete=models.CASCADE, related_name = 'tarea') 
    categoria = models.ForeignKey(CategoriaTarea, on_delete=models.CASCADE, related_name = 'tarea')
    descripcion = models.CharField(max_length=500)
    fecha = models.DateField(default=datetime.date.today)
    estado = models.ForeignKey(EstadoTarea, default= 1, on_delete=models.CASCADE)
    creado_por = models.ForeignKey(User, on_delete=models.CASCADE, related_name='creador')
    creado = models.DateTimeField(auto_now_add=True)
    parent = models.ForeignKey('self', on_delete=models.CASCADE, related_name="actualizaciones", null=True, blank=True)
    modificado = models.DateTimeField(auto_now=True)
    modificado_por = models.ForeignKey(User, blank=True, null=True, default=None, on_delete=models.CASCADE, related_name='modificador')
    extras = models.JSONField(null=True)
    
    class Meta:
        ordering = ["fecha"]

    def save(self, *args, **kwargs):
        user = get_current_user()
        if user and not user.pk:
            user = None
        if not self.pk:
            self.creado_por = user
        else:
            self.modificado_por = user
        super(Tarea, self).save(*args, **kwargs)

###### TASK FILES SHOULD I USE THE EXTRAS FIELD (JSONFIELD) IN TASKS MODEL TO STORE THE PATH TO THE FILES?
class ArchivoTarea(models.Model):
    tarea = models.ForeignKey(Tarea, on_delete=models.CASCADE)       
    archivo = models.FileField(upload_to=upload_reporte_file_to)

Now, my questions are:

  1. Is this the best approach? or am I just complicating things?

  2. I'm trying to use a jsonfield, to store differentiation parameters, but I'm having trouble formatting the keys I want to store.

  3. Where should I store the files path, in a separate table or in the json field? (Each task or update, should have maximum 5 files.

Thanks in advance.

CodePudding user response:

I'd say TipoTarea and EstadoTarea should just be Charfields with defined choices on your main Tarea model. With those foreign keys you'll have to do an unnecessary join every time you query a task on both those tables just to get its state and type, and the interface is worse: tarea.tipo.nombre isn't fun to just check what type your task is.

The CategoriaTarea is debatable, not sure what it's supposed to represent really, mix of location and time? If you're going to add more to it why not.

The ArchivoTarea is good. I'm not sure what you mean by "path to the file". If you need 5 files related to a Tarea instance you just create 5 ArchivoTarea instances, one for each file which you save using the archivo FileField, all of them pointing to the same task. If you somehow want the filename store separately you can add a filename Charfield to the ArchivoTarea model. (e.g with t being a Tarea instance: t.archivotarea_set.values_list('filename', flat=True) gives you all filenames for t)

JsonFields don't really require formatting although it helps to keep the same structure of keys/values t across all your model's instances. Django will serialize and deserialize from and to python types it for you when saving/reading from the database. https://docs.djangoproject.com/en/3.2/ref/contrib/postgres/fields/#jsonfield

  • Related