Ответ
Для реализации механизма подписок используется классический паттерн "многие-ко-многим" (Many-to-Many) через промежуточную (связующую) таблицу.
Эта таблица хранит пары идентификаторов: кто подписался (subscriber) и на кого подписались (target).
Пример реализации на Django ORM
Модель Subscription выступает в роли связующей таблицы между пользователями (User).
from django.db import models
from django.contrib.auth.models import User
class Subscription(models.Model):
"""Модель для хранения подписок пользователей друг на друга."""
# Пользователь, который подписывается
subscriber = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='following' # user.following -> на кого он подписан
)
# Пользователь, на которого подписываются
target = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='followers' # user.followers -> кто на него подписан
)
created_at = models.DateTimeField(
auto_now_add=True,
verbose_name="Дата подписки"
)
class Meta:
# Гарантирует, что пользователь не может подписаться на другого дважды
unique_together = ('subscriber', 'target')
ordering = ['-created_at']
def __str__(self):
return f"{self.subscriber} follows {self.target}"
Ключевые аспекты этой архитектуры:
- Промежуточная таблица:
Subscriptionсвязывает двух пользователей. - Внешние ключи:
subscriberиtargetссылаются на одну и ту же модельUser. related_name: Позволяет удобно получать связанные объекты. Например,user.followers.all()вернет всех подписчиков пользователя.- Ограничение уникальности:
unique_togetherпредотвращает дублирование записей о подписке. - Масштабируемость: Этот подход легко расширяется, например, добавлением поля для уведомлений.