Модели Django - это хорошая практика для создания моделей, которые связывают только две таблицы? - PullRequest
0 голосов
/ 18 декабря 2018

Допустим, я хочу разработать простое приложение со списком задач.Вот так может выглядеть models.py.

PRIORITIES = ["LOW", "MEDIUM", "HIGH", "URGENT"]

class User(models.Model):
    username = models.CharField(max_length = 20)
    password = models.CharField(max_length = 100)
    email = models.EmailField()

class Task(models.Model):
    text = models.TextField()
    dueDate = models.DateField()
    priority = models.CharField(choices = PRIORITIES, default = "LOW")

class UserTask(models.Model):
    user = models.ForeignKey(User, on_delete = models.CASCADE)
    task = models.ForeignKey(Task, on_delete = models.CASCADE)

Здесь модель UserTask была создана только с целью уменьшения избыточности в базе данных.

Это хорошая практика?Я не думаю, что для этого нужно использовать модели.

1 Ответ

0 голосов
/ 18 декабря 2018

Здесь модель UserTask была создана только с целью уменьшения избыточности в базе данных.

Если я правильно понимаю, Task принадлежит single User, по крайней мере, на основе вашего комментария:

Я читал о ManyToMany, проблема в том, что это отношение на самом деле OneToMany.

В этом случае я не вижу, как вы «уменьшаете» избыточность в базе данных, фактически вы создаете дополнительное дублирование данных , поскольку теперь вам нужно сохранить Task и user = ForeignKey(..) в гармонии с UserTask, таким образом, это означает, что все создания, изменения и удаления имеют влияние, а некоторые обходят сигнальные инструменты Django, поэтому это делает его довольно сложным, если не невозможным.

Дело в том, что вам не нужно для построения таблицы для запроса отношения в обратном порядке.По умолчанию Django помещает базу данных index в ForeignKey, поэтому база данных может эффективно извлекать Task s, которые принадлежат одному (или нескольким) пользователям, таким образом, она делает JOIN стаблица user более эффективна.

Как правило, каждый определяет ForeignKey как:

class Task(models.Model):
    text = models.TextField()
    dueDate = models.DateField()
    <b>user = models.ForeignKey(User, on_delete=models.CASCADE)</b>
    priority = models.CharField(choices = PRIORITIES, default = "LOW")

На уровне Python / Django, Django также обеспечивает удобство для получения задачUser.Если вы хотите получить все Task из some_user, вы можете запросить:

some_user.<b>task_set</b>.all()

или выполнить фильтрацию по задачам, например:

some_user.<b>task_set</b>.filter(text__icontains='someword')

YouМожно также сделать имя отношения в обратном направлении более удобным, указав related_name в ForeignKey, например:

class Task(models.Model):
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        <b>related_name='tasks'</b>
    )
    text = models.TextField()
    dueDate = models.DateField()
    priority = models.CharField(choices = PRIORITIES, default = "LOW")

В этом случае вы, таким образом, запрашиваете Task sUser с:

some_user.<b>tasks</b>.all()

Однако существует сценарий, в котором Django создает неявную модель, которая связывает две модели вместе: в случае, если одна определяет ManyToManyField [Django-doc] , поскольку указание массива идентификаторов обычно сложно (или даже невозможно) для большого количества реляционных баз данных (даже если это возможно, как правило, больше нельзя гарантировать ограничения FOREIGN KEY) и т. д.

Если отношение «многие ко многим» между двумя моделями содержит дополнительные данные (например, метку времени, когда два пользователя стали друзьями), то одна даже определяет явную модель с двумя ForeignKey отношениями (и дополнительными атрибутами),и использует это как through [Django-doc] модель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...