Один ко Многим
Эта статья — продолжение статьи о моделях данных.
У нас есть блог с постами:
class Post(models.Model):
text = models.TextField()
title = models.CharField(max_length=200)
...
Теперь вы хотите пригласить других авторов и зовёте их зарегистрироваться на сайте. У каждого поста теперь свой автор. Как сделать так, чтобы пост помнил, кто его написал? Самое простое решение — хранить логин автора в таблице поста:
class Post(models.Model):
author_login = models.CharField(max_length=200)
...
Но вообще, хорошо бы хранить где-то почту автора, его день рождения и аватарку. Кажется, понадобится новая таблица и модель данных к ней:
class User(models.Model):
login = models.CharField(max_length=200)
email = models.EmailField()
birthday = models.DateField()
avatar = models.ImageField()
...
Теперь, зная логин автора поста, можно найти всю информацию о нём:
author_login = post.author_login
author = User.objects.filter(login=author_login)[0]
А как сделать нормально?
Всё работает куда проще, когда вместо логина мы храним ссылку на пользователя:
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.SET_NULL)
...
ForeignKey
— это особый вид поля. Он говорит о том, что здесь мы храним ссылку на другую таблицу. Теперь можно быстро добраться до автора поста, который на самом деле хранится в другой таблице:
author = post.author
print("Логин автора:", author.login)
print("Почта автора:", author.email)
print("День рождения автора:", author.birthday)
ForeignKey
представляет собой связь “один ко многим”. Один автор может написать много статей, но у статьи может быть только один автор:
Как этим пользоваться?
Например, мы хотим найти все статьи автора с логином voron434
:
author = User.objects.filter(login="voron434")[0]
posts_by_this_author = Post.objects.filter(author=author)
По-хорошему, этот код следует упаковывать в один-единственный вызов filter
, но как это делать читайте в статье про связанные объекты.
Что читать
В этой статье мы используем filter(...)[0]
. Вместо этого лучше использовать get()
, как делается в статье про CRUD.
Также мы не уделяли внимание странному on_delete.
Попробуйте бесплатные уроки по Python
Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.
Переходите на страницу учебных модулей «Девмана» и выбирайте тему.