Как ускорить транзакции запросов для больших записей в Django, если для этого мы посещаем несколько классов?

#python #django #django-models #orm #django-queryset

#питон #джанго #джанго-модели #орм #django-набор запросов

Вопрос:

Я пытаюсь показать предложения по профилям пользователей для пользователя LoggedIn на основе тегов, которым он/она следует, В моем случае мне нужно перейти в класс User_Interests_Tag, чтобы получить все теги, затем посетить класс Post_Tag, чтобы получить все сообщения для каждого тега(цикл), как только у меня будут все идентификаторы, посетите класс Post, чтобы получить каждого уникального пользователя и добавить его в профиль(список) и использовал paginator для ограничения профилей, отправленных клиенту. Как я могу добиться этого без использования циклов for для увеличения общей эффективности и времени отклика от сервера?

Модели:

 class User_Interests_Tag(models.Model): # User Suggestions Tag to User link  id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)  user = models.ForeignKey(User, null=False, on_delete=models.CASCADE)  tag = models.ForeignKey(Tag, null=False, on_delete=models.CASCADE)  priority = models.FloatField(default=0.0)     class Post_Tag(models.Model): # Post Media Link  id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)   post = models.ForeignKey(Post, on_delete=models.CASCADE)  tag = models.ForeignKey(Tag, on_delete=models.CASCADE)   class Post(models.Model):   id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)   user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)  title= models.CharField(max_length=500, default="unknown", null=True)  description = models.CharField(max_length=512 , null = True)  date_posted = models.DateTimeField(auto_now_add=True)  

вот фрагмент того, чего я хочу достичь :

 #looping through each tag  for user_interests_tag in user_interests_tags:  #user_post_tags = Post_Tag.objects.in_bulk(user_interests_tags) (used bulk but no luck)   user_post_tags.extend(list(Post_Tag.objects.filter(tag_id = user_interests_tag).values_list('post_id', flat=True)))  profiles = []  #looping through each tag id   for user_post_tag in user_post_tags:  #getting the user from post class  user = Post.objects.get(id = user_post_tag)  #checking if already follows and if already their in user profiles array  if user not in profiles and not User_Follow.objects.filter( owner_id = user_id.id, user_id = user.user_id):  profiles.append(user)  #paginating 6 per request  paginator = Paginator(profiles,6)  limited_profiles = paginator.page(page)  return limited_profiles  

Любые зацепки очень ценю, заранее спасибо 🙂

Комментарии:

1. Можете ли вы поделиться своими моделями?

2. Конечно , пожалуйста, проверьте выше, я только что отредактировал его с моделями!

Ответ №1:

Вы могли бы сделать что-то вроде этого:

 posts = Post.objects.filter(  Q(post_tag_set__tag__in=user_interests_tags)   amp; ~Q(user__in=User_Follow.objects.filter(owner_id=user_id.id).values('user')) ).distinct()  paginator = Paginator(posts, 6) limited_profiles = paginator.page(page)  return limited_profiles  

Чтобы подробнее остановиться на этом:

 Q(post_tag_set__tag__in=user_interests_tags)   

Выше будет отфильтровано все Post s, у которых есть Post_Tag s с Tag совпадением s user_interests_tags .

 ~Q(user__in=User_Follow.objects.filter(owner_id=user_id.id).values('user'))  

Вышеизложенное также будет фильтровать Post s с помощью a user , который не соответствует ни User_Follow одному объекту на основе фильтра идентификатора владельца, который у вас есть в данный момент.

Комментарии:

1. Эй , спасибо за четкое объяснение, в этой строке Q(post_tag_set__tag__in=user_interests_tags) я получаю сообщение об ошибке : Не удается разрешить ключевое слово «post_tag_set» в поле.

2. Это утверждение на самом деле отфильтровывает идентификаторы тегов, но мне нужно, чтобы идентификаторы сообщений отфильтровывались из модели сообщений, пожалуйста, дайте мне подсказку о том, как выбрать значение идентификатора записи в вышеупомянутом заявлении. Спасибо 🙂

3. Эй @BrianDestura приведенный ниже код работает для меня и значительно сократил время отклика для больших записей, пожалуйста, дайте мне знать, если у вас есть какой-либо другой способ оптимизировать его еще больше. с нетерпением ждем вашего ответа! posts = Post.objects.filter(Q(id__in = Post_Tag.objects.filter(Q(tag__in = User_Interests_Tag.objects.filter(user_id = user_id.id).values_list('tag_id', flat=True))).values_list('post_id', flat=True) ) amp; ~Q(user__in=User_Follow.objects.filter(owner_id=user_id.id).values('user'))).distinct().order_by('-id')

4. О, как здорово слышать, что это улучшилось! Вы можете post_tag_set заменить фактическим related_name , который вы используете (обратный способ доступа от поста к тегу поста) (может быть, просто попробуйте post_tag ). По сути, ваш текущий код делает то же самое с ответом, который я опубликовал.

5. Конечно, @Брайан, я попробую , большое вам спасибо, я действительно ценю ваше время и надеюсь, что у вас будет отличный день, сэр 🙂