Django фильтрует записи по полю из другой таблицы

У меня есть сайт "список дел" с тремя таблицами (TDLists, Tasks, Users), и я хочу отобразить все списки дел для конкретного пользователя со всеми задачами, которые связаны с этим конкретным списком. У меня возникают проблемы с фильтрацией этих элементов в моем файле views.py. Я смог получить желаемые результаты, используя SQL, но не могу перевести это на язык django.

models.py

class Users(models.Model):
    username = models.CharField(max_length=20)
    email = models.CharField(max_length=40)
    password = models.CharField(max_length=16)
    user_id = models.AutoField(primary_key=True)

class TDLists(models.Model):
    title = models.CharField(max_length=50)
    date_created = models.DateField(auto_now_add=True)
    completed = models.BooleanField(default=False)
    deadline_date = models.DateField(null=True)
    user_id = models.ForeignKey(Users, on_delete=models.CASCADE)
    list_id = models.AutoField(primary_key=True)

class Tasks(models.Model):
    description = models.CharField(max_length=120)
    priority = models.CharField(choices=(
        ("High", "high"),
        ("Medium", "medium"),
        ("Low", "low"),
    ),max_length=10)
    list_id = models.ForeignKey(TDLists, on_delete=models.CASCADE)
    task_id = models.AutoField(primary_key=True)

SQL код, который работает:

SELECT myApp_tasks.*
FROM myApp_tasks, myApp_tdlists, myApp_users
WHERE myApp_tdlists.user_id_id = myApp_users.user_id
AND myApp_tasks.list_id_id = myApp_tdlists.list_id
AND myApp_users.user_id = 1

вывод:

enter image description here

код опробован в views.py

user_id = 1

user = Users.objects.filter(user_id=user_id)
lists = TDLists.objects.filter(user_id=user.get(user_id=user_id))
tasks = Tasks.objects.filter(list_id=lists.get(list_id=lists.list_id))

Вам не нужно использовать filter() для большей части того, что вы пытаетесь сделать.

Во-первых, вы не должны использовать filter, если хотите получить один элемент по ID, вместо этого используйте get() - хотя имейте в виду, что это вызовет исключение, если Django не найдет совпадения, и вам нужно будет обработать его (либо через try/except, либо через ярлык get_object_or_404 Django):

user = Users.objects.get(user_id=user_id)

Во-вторых, благодаря отношениям внешнего ключа, вы можете получить доступ ко всем спискам с помощью аксессора _set:

lists = user.tdlists_set.all()

К сожалению, вы не можете добавить к этому tasks_set без использования цикла for для доступа к каждому списку по отдельности. Вам придется использовать фильтр, но вы все равно можете воспользоваться аксессором, чтобы сделать запрос довольно простым:

tasks = Task.objects.filter(list_id__user_id=user) # note the double underscore

Кстати, в Django рекомендуется именовать модели в единственном числе, а не во множественном - например, Task вместо Tasks.

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