如何更正ORM语句以显示所有与Django中的用户没有关联的朋友?

2024-06-01 02:30:23 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的Django应用程序中,我有两个模型,一个是用户,一个是友情。两者之间存在多对多的关系,因为用户可以有许多朋友,而朋友可以有许多其他朋友是用户。你知道吗

如何返回所有与名为“Daniel”的用户不是朋友的朋友(名和姓)?你知道吗

你知道吗型号.py地址:

class Friendships(models.Model):
    user = models.ForeignKey('Users', models.DO_NOTHING, related_name="usersfriend")
    friend = models.ForeignKey('Users', models.DO_NOTHING, related_name ="friendsfriend")
    created_at = models.DateTimeField(blank=True, null=True)
    updated_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'friendships'


class Users(models.Model):
    first_name = models.CharField(max_length=45, blank=True, null=True)
    last_name = models.CharField(max_length=45, blank=True, null=True)
    created_at = models.DateTimeField(blank=True, null=True)
    updated_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'users'

到目前为止,这是我在控制器中尝试的(视图.py)--请注意,我理解控制器应该很瘦,但仍在学习,所以道歉。我在下面的代码片段中尝试了(在多次尝试使用更干净的方法失败之后)首先尝试抓取daniels的朋友(将他们填充到一个列表中,然后删除任何重复的id),然后根据他们的id过滤掉他们

# show first and last name of all friends who daniel is not friends with:

def index(req):

    friends_of_daniel = Friendships.objects.filter(user__first_name='Daniel')
    daniels_friends = []
    for friend_of_daniel in friends_of_daniel:
        daniels_friends.append(friend_of_daniel.friend.id)

    daniels_friends = list(set(daniels_friends))

    not_daniels_friends = Friendships.objects.exclude(id__in=daniels_friends)

    context = {
        'not_daniels_friends':not_daniels_friends,
    }

return render(req, "friendapp/index.html",context)

但是,当我在我的视图(模板)文件中尝试以下操作时,仍然会看到一些人是丹尼尔斯的朋友。知道我做错了什么吗?你知道吗

<ul>
    {% for not_daniel_friend in not_daniels_friends %}
        <li>{{ not_daniel_friend.user.first_name }} {{ not_daniel_friend.user.last_name }}</li>
    {% endfor %}
</ul>

Tags: of用户namefriendtruemodelsnot朋友
3条回答

我想这样就可以了。然后获取列表users,并获取这些用户的名字和姓氏。你知道吗

daniels = Users.objects.filter(first_name="Daniel") # There may be more than one Daniel
users = Friendships.objects.exclude(friend__in=daniels)

注意这里,而友谊。朋友是类型为Usersforeignkey您可以在friend__in中传递用户实例(即daniels列表)以排除这些用户。你知道吗

首先作为一个一般性的注释:填充id列表的一种更干净的方法是使用.value_list() method from django(Django以前版本中.values()方法的一部分)。它有一个“平面”标志,用于创建所需的列表。你知道吗

所以,不是:

friends_of_daniel = Friendships.objects.filter(user__first_name='Daniel')
    daniels_friends = []
    for friend_of_daniel in friends_of_daniel:
        daniels_friends.append(friend_of_daniel.friend.id)

    daniels_friends = list(set(daniels_friends))

你可以用一句话:

daniels_friends = Friendships.objects \
       .filter(user__first_name='Daniel') \
       .distinct('friend') \
       .values_list('friend', flat=True)

distinct与list()-set()强制转换相同(它确保列表中没有重复的元素),可以将flat=True的值\u list自定义为相关“user”表中的任何字段:.values \u list('friend \u id',flat=True)或.values \u list('friend \u first \u name',flat=True)以获取Daniel朋友的名字列表。你知道吗

回到你的一般问题,你可以用你的相关名字直接在一行中完成整个查询,因为我不确定你想要什么(一个用户实例,一个友情实例,或者只是一个名字和姓氏的列表),我会给你很多选择:

  • 如果你想要一个友谊实例(你在你的示例中尝试的是什么 代码):

    friendships_not_friends_with_daniel = Friendships.objects\
            .exclude(friend__first_name="Daniel") 
    

    这相当于@Rafael在他的回答中提出的:

    daniels = Users.objects.filter(first_name="Daniel") # There may be more than one Daniel users = Friendships.objects.exclude(friend__in=daniels)

    在这里,我通过引用 相关表中带有双下划线的字段(这是一个非常重要的 Django的强大标准)。

  • 如果需要用户实例:

    users_with_no_friendship_with_daniel = Users.objects\
            .exclude(usersfriend__friend__first_name="Daniel")
    

    这里您使用模型的相关名称从 将users表添加到friendships表,然后检查此用户的朋友是否为Daniel。这种查询方式理解起来有点复杂,但一旦你习惯了它就会变得非常强大,因为它与口语非常相似:你想要所有的用户,但不包括那些有友谊的用户,他们的朋友的名字是Daniel。根据一个用户有多少朋友或者有多少用户被称为Daniel,您可以添加一些distinct()方法或者将查询一分为二。你知道吗

    作为一个建议,也许您可以改进模型中的相关名称,因为如果您有一个用户实例并且想要获得相关的友谊,那么您将使用这个名称:user_例如,友谊而不是用户_instance.usersfriend实例和用户_instance.friendsfriendships实例而不是用户_instance.friendsfriend实例.... 不知道,我总是很难选择好相关的名字。。。

  • 如果需要用户名和姓的元组列表:

    names_of_users_with_no_friendship_with_daniel = Users.objects\
            .exclude(usersfriend__friend__first_name="Daniel")\
            .values_list('first_name', 'last_name')
    

对不起,如果有什么不清楚的地方,请询问,我会尽量解释得更好。(我对stackoverflow很陌生)

试试这个,代替你的朋友_丹尼尔.朋友.id,则应从用户模型中排除结果。你知道吗

像这样:

    def index(req):

        friends_of_daniel = Friendships.objects.filter(user__first_name='Daniel')
        daniels_friends = []
        for friend_of_daniel in friends_of_daniel:
            daniels_friends.append(friend_of_daniel.friend.id)

        daniels_friends = list(set(daniels_friends))

        not_daniels_friends = Users.objects.exclude(id__in=daniels_friends)

        context = {
            'not_daniels_friends':not_daniels_friends,
        }

    return render(req, "friendapp/index.html",context)

谢谢。你知道吗

相关问题 更多 >