Делаем полиморфную модель, какой подход лучше?

Я пытаюсь расширить проект, который изначально использовался областью для назначения отчетов соответствующим отделам. Эти отчеты я хочу сделать задачами, чтобы расширить спектр использования для всей организации.

Изначально я использовал отдельные модели для отчетов, обновлений, файлов отчетов, файлов обновлений. (Эти таблицы имели почти одинаковые поля)

Теперь я пытаюсь иметь полиморфную модель, как показано ниже:

#### 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)

Теперь, мои вопросы следующие:

  1. Является ли это лучшим подходом? Или я просто усложняю ситуацию?

  2. Я пытаюсь использовать jsonfield для хранения параметров дифференциации, но у меня возникают проблемы с форматированием ключей, которые я хочу сохранить.

  3. Где я должен хранить путь к файлам, в отдельной таблице или в json-поле? (Каждая задача или обновление, должны иметь максимум 5 файлов.

    .

Заранее спасибо.

Я бы сказал, что TipoTarea и EstadoTarea должны быть просто Charfields с определенными choices на вашей основной Tarea модели. С этими внешними ключами вам придется делать ненужное соединение каждый раз, когда вы запрашиваете задачу в обеих этих таблицах, чтобы получить ее состояние и тип, и интерфейс будет хуже: tarea.tipo.nombre не интересно просто проверить, какого типа ваша задача.

CategoriaTarea спорный вопрос, не уверен, что он должен представлять на самом деле, смесь местоположения и времени? Если вы собираетесь добавить к нему больше, то почему бы и нет.

ArchivoTarea - это хорошо. Я не уверен, что вы подразумеваете под "путем к файлу". Если вам нужно 5 файлов, связанных с экземпляром Tarea, вы просто создаете 5 экземпляров ArchivoTarea, по одному для каждого файла, который вы сохраняете с помощью поля archivo FileField, и все они указывают на одну и ту же задачу. Если вы хотите, чтобы имя файла хранилось отдельно, вы можете добавить к модели filename Charfield в ArchivoTarea. (например, когда t является экземпляром Tarea: t.archivotarea_set.values_list('filename', flat=True) дает вам все имена файлов для t)

JsonFields не требуют форматирования, хотя это помогает сохранить одинаковую структуру ключей/значений во всех экземплярах вашей модели. Django будет сериализовать и десериализовывать из и в python типы для вас при сохранении/чтении из базы данных. https://docs.djangoproject.com/en/3.2/ref/contrib/postgres/fields/#jsonfield

Вернуться на верх