Есть следующие модели:
class Chat(models.Model):
participants = models.ManyToManyField(Contact, related_name='chats')
messages = models.ManyToManyField(Message, blank=True)
def __str__(self):
return f'{self.pk}'
class Meta:
verbose_name = 'Чат'
verbose_name_plural = 'Чаты'
Это модель чата, с определенным обратным именем для участников чата
Есть модель контакта:
class Contact(AbstractBaseUser, PermissionsMixin):
'''Кастомная модель пользователя'''
email = models.EmailField(verbose_name='email', max_length = 60, unique = True)
slug = models.SlugField(default='')
first_name = models.CharField(max_length=30, default = '')
last_name = models.CharField(max_length=30, default = '')
phone_number = models.CharField(max_length=11)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add = True)
last_login = models.DateTimeField(verbose_name='last login', auto_now = True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
avatar = models.ImageField(upload_to='user_avatars/%Y/%m/%d', blank=True)
is_active = models.BooleanField(default=False)
status = models.CharField(max_length=100, default='', blank=True)
friends = models.ManyToManyField('self', blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'phone_number', 'slug']
objects = ContactManager()
def __str__(self):
return self.email
def get_url(self):
try:
return self.avatar.url
except ValueError:
return None
class Meta:
verbose_name = 'Контакт'
verbose_name_plural = 'Контакты'
ordering = ['-date_joined']
Также написан менеджер:
class ContactManager(BaseUserManager):
'''Мэнэджер кастомного пользователя'''
def create_user(
self,
email,
first_name,
last_name,
phone_number,
slug,
password = None
):
user = self.model(
email=self.normalize_email(email),
first_name=first_name.capitalize(),
last_name=last_name.capitalize(),
phone_number=phone_number,
slug=slug
)
user.set_password(password)
user.save(using = self._db)
return user
def create_superuser(
self,
email,
first_name,
last_name,
phone_number,
slug,
password = None
):
user = self.model(
email=self.normalize_email(email),
first_name=first_name,
last_name=last_name,
phone_number=phone_number,
slug=slug
)
user.set_password(password)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.is_active = True
user.save(using = self._db)
return user
Есть вью для вывода определенного контакта:
class ContactCustomViewSet(RetrieveUpdateDestroyPermissionViewset):
'''Обзор, обновление и удаление контакта'''
serializer_class = ContactDetailSerializer
permission_classes = [permissions.IsAuthenticated, IsCurrentUser, ]
permission_classes_by_action = {
'retrieve': [permissions.IsAuthenticated, ]
}
def get_queryset(self):
pk = self.kwargs['pk']
contact = get_object_or_404(Contact, id=pk)
queryset = Contact.objects.filter(id=pk).annotate(
is_friend=Count('friends', filter=Q(friends=self.request.user))
).annotate(
num_friends=Count('friends')
).annotate(
current_user=Count('slug', filter=Q(slug=self.request.user.slug))
).annotate(
is_sent=Exists(
AddRequest.objects.filter(
sender=self.request.user,
receiver=contact,
)
)
).annotate(
is_sent_to_you=Exists(
AddRequest.objects.filter(
sender=contact,
receiver=self.request.user
)
)
).annotate(
chat_id=Sum('chats__id', filter=Q(chats__participants=self.request.user))
)
return queryset
В последней аннотации я пытаюсь вывести айди чата текущего пользователя с пользователем, на чью страницу он зашел, но возникает непредвиденная проблема
Это я зашел на свой собственный контакт, под которым я залогинен, забавно здесь то, что друга у меня всего 3, а чата с айди 30 вообще не существует
Далее, если я привожу вью к следующему виду:
class ContactCustomViewSet(RetrieveUpdateDestroyPermissionViewset):
'''Обзор, обновление и удаление контакта'''
serializer_class = ContactDetailSerializer
permission_classes = [permissions.IsAuthenticated, IsCurrentUser, ]
permission_classes_by_action = {
'retrieve': [permissions.IsAuthenticated, ]
}
def get_queryset(self):
pk = self.kwargs['pk']
contact = get_object_or_404(Contact, id=pk)
queryset = Contact.objects.filter(id=pk).annotate(
is_friend=Count('friends', filter=Q(friends=self.request.user))
).annotate(
num_friends=Count('friends')
).annotate(
current_user=Count('slug', filter=Q(slug=self.request.user.slug))
).annotate(
is_sent=Exists(
AddRequest.objects.filter(
sender=self.request.user,
receiver=contact,
)
)
).annotate(
is_sent_to_you=Exists(
AddRequest.objects.filter(
sender=contact,
receiver=self.request.user
)
)
)
# .annotate(
# chat_id=Sum('chats__id', filter=Q(chats__participants=self.request.user))
# )
return queryset
То результат следующий:
Друзья перестают шалить, что логично, но не понимаю я одного. Почему последняя аннотация вообще влияет на какую-либо другую, а также: как правильно все-таки построить запрос к базе для получения желаемого результата, а именно: как вывести айди чата с пользователем, на чью страницу я захожу. Мой фронт вытягивает айди чата из ответа, чтобы потом обратиться к правильному адресу с правильным айди чата, чтобы соответственно сделать соединение с правильным чатом
Буду очень благодарен за любую помощь