Делаем полиморфную модель, какой подход лучше?
Я пытаюсь расширить проект, который изначально использовался областью для назначения отчетов соответствующим отделам. Эти отчеты я хочу сделать задачами, чтобы расширить спектр использования для всей организации.
Изначально я использовал отдельные модели для отчетов, обновлений, файлов отчетов, файлов обновлений. (Эти таблицы имели почти одинаковые поля)
Теперь я пытаюсь иметь полиморфную модель, как показано ниже:
#### 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)
Теперь, мои вопросы следующие:
Является ли это лучшим подходом? Или я просто усложняю ситуацию?
Я пытаюсь использовать jsonfield для хранения параметров дифференциации, но у меня возникают проблемы с форматированием ключей, которые я хочу сохранить.
Где я должен хранить путь к файлам, в отдельной таблице или в 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