Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将查询合并为一个查询,然后按日期排序_Python_Django - Fatal编程技术网

Python 将查询合并为一个查询,然后按日期排序

Python 将查询合并为一个查询,然后按日期排序,python,django,Python,Django,我有三张桌子。用户、发布和共享。Post是包含所有Post的表。Post与共享具有一对多关系。这就是说,共享表是一个表,它指示用户共享了哪些帖子。以下是表格的结构: class Post(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) status = models.CharField(max_length=200) share_count = mod

我有三张桌子。用户、发布和共享。Post是包含所有Post的表。Post与共享具有一对多关系。这就是说,共享表是一个表,它指示用户共享了哪些帖子。以下是表格的结构:

class Post(models.Model):
    user        = models.ForeignKey(User, on_delete=models.CASCADE)
    status      = models.CharField(max_length=200)

    share_count = models.IntegerField(default=0)

    created_at  = models.DateTimeField(auto_now_add=True)
    url         = models.CharField(max_length=150)

class Share(models.Model):
    post        = models.ForeignKey(Post, on_delete=models.CASCADE)
    user        = models.ForeignKey(User, on_delete=models.CASCADE)
    shared_at   = models.DateTimeField(auto_now_add=True)
我特别想要的是一个查询,它获取用户共享的帖子和用户创建的帖子。例如,假设我们有相同的数据:

Post表

id    user    status    share_count    created_at    url
1      1       hello         32         2017-06-01   hello
2      2       What's up     22         2017-07-01   whats-up
post    user   shared_at
2       2      2017-07-02
共享表

id    user    status    share_count    created_at    url
1      1       hello         32         2017-06-01   hello
2      2       What's up     22         2017-07-01   whats-up
post    user   shared_at
2       2      2017-07-02
我想要一个查询,将获得用户的共享帖子+他们的帖子。假设我想为用户1这样做。结果应该是post 1和post 2,因为用户发布了post 1,也共享了用户2的post 2。以下是我目前掌握的情况: 来自itertools进口链

user = User.objects.get(pk=1) # pick a user

own_posts = user.post_set.order_by('-created_at')
shared_posts = user.share_set.order_by('-shared_at')

combined = itertools.chain(own_posts, shared_posts)

def get_ts(obj):
   try:
     return obj.created_at
   except AttributeError:
     return obj.shared_at

last_5 = sorted(combined, key=get_ts, reverse=True)[:5]
在执行最后一行操作后出现此错误:


TypeError:“您得到此错误是因为在最后一行中,您试图根据键
get\ts
进行排序,但是(至少)组合的
的两个元素的
None
作为
get\ts
的值,因此无法进行比较。

我认为您使其变得相当复杂。这里的核心问题是,您的集合包含两种类型的元素
Post
s和
share
s。我真的建议你不要这样做,因为这只会使它更难处理

但是,我们可以构造一个queryset,它将返回由用户发布或由该用户共享的帖子。例如:

from django.db.models import Q
from django.db.models.functions import Coalesce

Post.objects.filter(
    Q(user=some_user) | 
    Q(share__user=some_user)
).annotate(
    shared_or_created=Coalesce('share__shared_at', 'created_at')
).order_by('-shared_or_created')
从django.db.models导入Q
从django.db.models.functions导入合并
Post.objects.filter(
Q(用户=某些用户)|
Q(共享用户=某些用户)
).注释(
shared_或created=合并('share_uShared_at'、'created_at')
).order_by('-shared_或_created')
现在我们有了一个帖子列表,这些帖子要么是由
某个用户创建的,要么是由
某个用户共享的。接下来,我们用
shared\u或\u created
字段对每篇文章进行注释,该字段要么包含文章被共享的时间,要么包含文章未被共享(由用户创建)的时间。最后,我们按降序对该属性进行排序


将其编码到查询中的优点是,它是在数据库级别处理的。此外,它仍然是一个查询集,因此您可以在其上添加额外的过滤器、切片等。

是否有解决方案?@user2896120您需要检查
get\u ts
是否正确获取时间戳。如果是,则问题在于某些时间戳(即在
处创建的
或在
处共享的)的值为
None
。这似乎是一个不需要的值,因此您应该检查这些条目是如何创建的,以了解这是如何发生的。这对我来说没有多大意义,因为您将int
Post
s与
Share
s组合在一起,通常您需要一个相同类型的元素集合。当我执行
annotate
行时,我得到一个错误,上面写着:
文件“C:\python3.6.3\lib\site packages\django\utils\dateparse.py”,第94行,在parse\u datetime match=datetime\u re.match(value)TypeError:expected string或bytes-like-object
看来这不相关,解析时间戳时有问题。但是很难说,因为你没有发布完整的回溯。对不起,我搞错了。这确实管用,这是我的错。当您说“我真的建议您不要这样做”时,因为我的集合包含两种类型的元素,您建议我如何这样做?你是说我分发桌子的方式吗?或者你是在谈论我在问题中提出的原始查询吗?通常情况下,一个查询更好地避免不同类型的集合,因此我将(像这里)构造一个
Post
s的查询集。或者,您可以对它进行注释,以查看它是构造的还是喜欢的帖子(尽管在Python中检查也很容易)。我明白了,现在当您说“将其编码到查询中的优点是在数据库级别处理它”时,这是否意味着在我们对它进行某种评估之前它不会被处理?换句话说,它是懒惰的?