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
вывод:
код опробован в 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
.