Django是复杂的选择查询可能吗?

时间:2019-08-11 08:53:12

标签: django django-models

我有以下模型用于存储两个用户之间的双向关系。记录总是插入在较小的用户标识为user_a而较大的用户标识为user_b的位置。

是否有一种方法可以根据参考用户ID大于还是小于另一个用户ID来检索属于参考用户的所有记录和状态的正确值(如果为user_a,则将否定转换应用于Relationship_type)? / p>

也许有两个单独的查询,一个查询中的参考用户= user_a,另一个查询中的参考用户= user_b,然后进行联接?

class Relationship(models.Model):
    RELATIONSHIP_CHOICES = (
        (0, 'Blocked'),
        (1, 'Allowed'),
        (-2, 'Pending_A'),
        (2, 'Pending_B'),
        (-3, 'Blocked_A'),
        (3, 'Blocked_B'),
    )
    user_a = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name='user_a',null=True)
    user_b = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name='user_b',null=True)
    relationship_type = models.SmallIntegerField(choices=RELATIONSHIP_CHOICES, default=0)

我要实现的SQL查询:

(SELECT user_b as user_select, -relationship_type as type_select WHERE user_a='reference_user') UNION (SELECT user_a as user_select, relationship_type as type_select WHERE user_b='reference_user')

2 个答案:

答案 0 :(得分:2)

鉴于您拥有用户user_id的ID,可以使用以下过滤条件:

from django.db.models import Q

Relationship.objects.filter(Q(user_a_id=user_id) | Q(user_b_id=user_id))

如果您有一个CustomUser对象user,则几乎相同:

from django.db.models import Q

Relationship.objects.filter(Q(user_a=user) | Q(user_b=user))

如果您要获取给定类型的Relationship,我们可以执行以下操作:

from django.db.models import Q

rel_type = 2  # example rel_type

Relationship.objects.filter(
    Q(user_a=user, relationship_type=rel_type) |
    Q(user_b=user, relationship_type=-rel_type)
)

因此,我们在此处检索给定用户Relationshipuser_a的{​​{1}}个对象,或给定用户relationship_type=2和{{1}的Relationship对象}}。

我们可以注释查询集,然后进行合并,例如:

user_b

尽管我不知道这是否是一个好主意:注释不是“可写的”(因此您无法更新它们)。

最好实现某种“代理对象”,它可以交换relationship_type=-2qs1 = Relationship.objects.filter( user_a=user, relationship_type=rel_type ).annotate( user_select=F('user_b'), rel_type=F('relationship_type') ) qs2 = Relationship.objects.filter( user_a=user, relationship_type=rel_type ).annotate( user_select=F('user_a'), rel_type=-F('relationship_type') ) qs = qs1.union(qs2),并取反user_a类型,从而能够像是真实的user_b对象。

答案 1 :(得分:1)

正如您所说,number_format中的id总是小于user_a。因此,如果您使用user_b查询,则应该始终获取引用,其中引用中的user_b=user总是比其他user_id高。因此,我认为您可以使用以下查询集:

user_id
相关问题