I want to query the friends of an User but I'm struggling to get the correct query.
Models:
class User(AbstractUser, TimestampedModel, SerializeMixin):
city = models.CharField(max_length=60, blank=True)
picture = models.URLField(blank=True)
cover_picture = models.URLField(blank=True)
phone = models.CharField(max_length=20, blank=True)
access_token = models.CharField(max_length=32, blank=True, null=True, db_index=True)
facebook_token = models.CharField(max_length=1024, blank=True, null=True)
facebook_id = models.BigIntegerField(blank=True, null=True, db_index=True)
twitter_token = models.CharField(max_length=1024, blank=True, null=True)
twitter_id = models.BigIntegerField(blank=True, null=True, unique=True)
friends = models.ManyToManyField("self", through="Friendship", symmetrical=False)
class Friendship(TimestampedModel, SerializeMixin):
PENDING = "pending"
FRIEND = "friend"
FAVORITE = "favorite"
STATUS_CHOICES = (
(PENDING, "Pending"),
(FRIEND, "Friend"),
(FAVORITE, "Favorite")
)
user = models.ForeignKey(User, related_name="friendships")
friend = models.ForeignKey(User, related_name="friendships_reverse")
status = models.CharField(max_length=20, default=PENDING, choices=STATUS_CHOICES)
Query I'm trying to make
id = 32 # I want friends from this user
friends = User.objects.extra(select={"friendship_status": "status"}). \
filter(Q(friendships_reverse__user_id=id), ~Q(friendships_reverse__status=Friendship.PENDING))
But the generated query is quite weird:
SELECT (status) AS `friendship_status`,
`myapp_user`.`id`,
`myapp_user`.`password`,
`myapp_user`.`last_login`,
`myapp_user`.`is_superuser`,
`myapp_user`.`username`,
`myapp_user`.`first_name`,
`myapp_user`.`last_name`,
`myapp_user`.`email`,
`myapp_user`.`is_staff`,
`myapp_user`.`is_active`,
`myapp_user`.`date_joined`,
`myapp_user`.`created_at`,
`myapp_user`.`updated_at`,
`myapp_user`.`city`,
`myapp_user`.`picture`,
`myapp_user`.`cover_picture`,
`myapp_user`.`phone`,
`myapp_user`.`access_token`,
`myapp_user`.`facebook_token`,
`myapp_user`.`facebook_id`,
`myapp_user`.`twitter_token`,
`myapp_user`.`twitter_id`
FROM `myapp_user`
INNER JOIN `myapp_friendship` ON (`myapp_user`.`id` = `myapp_friendship`.`friend_id`)
WHERE (`myapp_friendship`.`user_id` = 32
AND NOT ((`myapp_user`.`id` IN
(SELECT U1.`friend_id`
FROM `myapp_friendship` U1
WHERE (U1.`status` = 'pending'
AND U1.`friend_id` IS NOT NULL))
AND `myapp_user`.`id` IS NOT NULL)))
Where clause should be as simple as:
`myapp_friendship`.`user_id` = 32 AND `myapp_friendship` != 'pending'
Can someone shed some light? This kind of issue is appearing all over my application.