Django объединить 2 QuerySets - PullRequest
       17

Django объединить 2 QuerySets

0 голосов
/ 09 января 2020

У меня есть 2 QuerySets, которые нацелены на разные таблицы в одной и той же базе данных.

Я пытаюсь добиться фильтрации results по created_at, а затем по hit_count.

Я использую django -hitcount для hit_count

Вот модель

class Post(models.Model):
    STATUS_CHOICES = (
        (1, 'Technology'),
        (2, 'Security'),
        (3, 'Android|iOS'),
    )
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, unique=True, editable=False)
    title = models.CharField(max_length=250)
    body = models.TextField()
    main_image = models.ImageField(null=False, upload_to=save_image)
    second_image = models.ImageField(blank=True, default="")
    third_image = models.ImageField(blank=True, default="")
    fourth_image = models.ImageField(blank=True, default="")
    fifth_image = models.ImageField(blank=True, default="")
    slug = models.SlugField(blank=True, default="", editable=True)
    created_at = models.DateField(default=date.today)
    category = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, default=1)
    custom = managers.PostManager()

Вот Manager

class PostManager(models.Manager):

    def get_queryset(self):
        return super(PostManager, self).get_queryset()

    def get_tech(self):
        return self.get_queryset().filter(category=1)

    def get_security(self):
        return self.get_queryset().filter(category=2)

    def get_mobile(self):
        return self.get_queryset().filter(category=3)

    def get_category_count(self):
        return self.get_tech().count(), self.get_security().count(), self.get_mobile().count()

    def get_top_stories_of_month(self):
        s_date = datetime.strftime(datetime.now() - timedelta(days=25), '%Y-%m-%d')
        e_date = datetime.strftime(datetime.now() - timedelta(days=32), '%Y-%m-%d')
        qs1 = self.get_queryset().filter(Q(created_at__lte=s_date) | Q(created_at__gte=e_date))
        qs2 = HitCount.objects.order_by('hits')

Как видите, я сохранил результаты в qs1 и qs2, но не знаю, как их объединить.

Я также поиграл в оболочке, чтобы попытаться отфильтровать объекты в query_set по объектным_пкам, которые у них общие. Результат очень странный, хотя, сравнивая pk, он почему-то возвращает False.

Код от Shell

>>> p = Post.custom.get_top_stories_of_month()
>>> h = HitCount.objects.order_by('hits')
>>> p
<QuerySet [<Post: dddddddddddddddddd>, <Post: kljlkjlkj>, <Post: asdasdad>, <Post: aasdfasdf>, <Post: zvzxv>]>
>>> h
<QuerySet [<HitCount: asdasdad>, <HitCount: zvzxv>, <HitCount: aasdfasdf>, <HitCount: kljlkjlkj>, <HitCount: dddddddddddddddddd>]>
>>> for i in h:
...     print(i.object_pk)
...     for j in p:
...             print(j.pk)
...             print(i.object_pk == j.pk)
... 
868ca0d9-f324-4845-b34b-38a1203eacb3
72b2104f-2cb6-49b3-80fd-fd0e80fab5b1
False
889d895b-f73c-48ca-9a96-064cbe6292c1
False
868ca0d9-f324-4845-b34b-38a1203eacb3
False
762f1c29-6ba5-4aaf-99a3-833c8c60d126
False
4b6427b1-4dab-4705-b5de-d39ccccec119
False
4b6427b1-4dab-4705-b5de-d39ccccec119
72b2104f-2cb6-49b3-80fd-fd0e80fab5b1
False
889d895b-f73c-48ca-9a96-064cbe6292c1
False
868ca0d9-f324-4845-b34b-38a1203eacb3
False
762f1c29-6ba5-4aaf-99a3-833c8c60d126
False
4b6427b1-4dab-4705-b5de-d39ccccec119
False
762f1c29-6ba5-4aaf-99a3-833c8c60d126
72b2104f-2cb6-49b3-80fd-fd0e80fab5b1
False
889d895b-f73c-48ca-9a96-064cbe6292c1
False
868ca0d9-f324-4845-b34b-38a1203eacb3
False
762f1c29-6ba5-4aaf-99a3-833c8c60d126
False
4b6427b1-4dab-4705-b5de-d39ccccec119
False
889d895b-f73c-48ca-9a96-064cbe6292c1
72b2104f-2cb6-49b3-80fd-fd0e80fab5b1
False
889d895b-f73c-48ca-9a96-064cbe6292c1
False
868ca0d9-f324-4845-b34b-38a1203eacb3
False
762f1c29-6ba5-4aaf-99a3-833c8c60d126
False
4b6427b1-4dab-4705-b5de-d39ccccec119
False
72b2104f-2cb6-49b3-80fd-fd0e80fab5b1
72b2104f-2cb6-49b3-80fd-fd0e80fab5b1
False
889d895b-f73c-48ca-9a96-064cbe6292c1
False
868ca0d9-f324-4845-b34b-38a1203eacb3
False
762f1c29-6ba5-4aaf-99a3-833c8c60d126
False
4b6427b1-4dab-4705-b5de-d39ccccec119
False

Ответы [ 2 ]

3 голосов
/ 09 января 2020

Документы для django -hitcount описывают здесь , как добавить поле к одной из ваших моделей (Post), которое будет относиться к модели HitCount.

После добавления атрибута hit_count к вашей модели Post, которая соответствует примеру, приведенному в документации, вы можете упорядочить и / или отфильтровать по совпадениям, а также по дате публикации в своем запросе. Ваш запрос будет выглядеть примерно так:

top_posts = Post.objects.order_by("hit_count__hits").filter(Q(created_at__lte=s_date) | Q(created_at__gte=e_date))
0 голосов
/ 10 января 2020

К сожалению, я не смог сделать запрос настолько элегантным, как он должен был получить ошибку отношения, когда order_by('hit_count.hits')

Решил сделать это так:

s_date = datetime.strftime(datetime.now() - timedelta(days=25), '%Y-%m-%d')
        e_date = datetime.strftime(datetime.now() - timedelta(days=32), '%Y-%m-%d')
        qs1 = self.get_queryset().filter(Q(created_at__lte=s_date) |
                                         Q(created_at__gte=e_date))
        mlist = sorted(list(qs1), key=lambda obj: obj.hit_count.hits, reverse=True)
        return mlist[:2]

This возвращает 2 самых просматриваемых сообщения.

...