Django ORM 验证数据库中的一行

Posted

技术标签:

【中文标题】Django ORM 验证数据库中的一行【英文标题】:Django ORM verification of a row in the database 【发布时间】:2018-11-20 05:41:04 【问题描述】:

在我的网站中,买家搜索产品,一旦找到,他可以通过按联系按钮联系卖家。如果两者之间存在有关此产品的对话,则应将他重定向到现有对话,否则,我们将创建一个新对话。 因此,对话由两个用户和一个列表定义。 当我尝试实现逻辑时,我无法验证对话存在的两个条件,如果列表存在或用户存在 Django 返回对话存在。这是我的代码:

def create_conversation(request, user_pk1, user_pk2, results_pk):
    user1 = get_object_or_404(get_user_model(), pk=user_pk1)
    user2 = get_object_or_404(get_user_model(), pk=user_pk2)
    results= get_object_or_404(Listing, pk=results_pk)
    existing_conversation = Conversation.objects.filter(users__in=[user1, user2]).filter(listing=results).values_list('id', flat=True)


    if existing_conversation.exists():

        return HttpResponseRedirect(reverse('conversation:conversation_update', kwargs='pk':existing_conversation[0]))
    else:
        conv=Conversation()
        conv.save()
        conv.listing = results
        conv.save()
        conv.users.add(*[user1,user2])
        return HttpResponseRedirect(reverse('conversation:conversation_update', kwargs='pk': conv.pk))

这是对话的模型:

class Conversation(models.Model):
    """
    Model to contain different messages between one or more users.

    :users: Users participating in this conversation.
    :archived_by: List of participants, who archived this conversation.
    :notified: List of participants, who have received an email notification.
    :unread_by: List of participants, who haven't read this conversation.]\['
    listing: the listing the conversation is about.
    read_by_all: Date all participants have marked this conversation as read.

    """
    users = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        verbose_name=_('Users'),
        related_name='conversations',
    )
# review the listing before going online, because it is necessary to have a conversation listing
    listing = models.ForeignKey (
        Listing,
        verbose_name=_('Listing'),
        related_name='listing',
        default= 1,
    )

以及上市的型号:

类列表(models.Model):

seller = models.ForeignKey(Profile, related_name='seller_listing', verbose_name='sellr', limit_choices_to='is_seller': True)
    location_Country = models.CharField(max_length=45, verbose_name=_('from_Country'))
    location_State = models.CharField(max_length=45, verbose_name=_('from_State'), null=True, blank=True)
    location_City = models.CharField(max_length=45, verbose_name=_('from_City'))

我还尝试了一种将其分为两个条件的方法:a = conversation.objects.filter(users) 和 b= conversation.objects.filter(listing),然后使用 if a 和 b then the conversation exists but got the同样的问题。

and existing_conversation = Conversation.objects.filter(Q(users__in=[user1, user2]) & Q(listing=results)).values_list('id', flat=True) 但遇到了同样的问题。提前感谢您的帮助。

【问题讨论】:

【参考方案1】:

您可以使用 django 的intersection() 方法,从 Django 1.11 开始添加,运算符返回两个或多个 QuerySet 的共享元素或按位运算 AND 与符号 `& 一起使用获得相同的行为。

所以在你的情况下,检查两个用户之间是否有&intersection() 的交集

existing_conversation = (user1.conversations.all() & user2.conversations.all()).filter(listing=results)

# or with django intersection

existing_conversation = (user1.conversations.all().intersection(user2.conversations.all())).filter(listing=results)

if existing_conversation.exists():
    return HttpResponseRedirect(reverse('conversation:conversation_update', 
       kwargs='pk':existing_conversation.first().pk))

 else:
    # rest of the code

奖励,我在您的代码中看到一个错字,您没有将 pk 作为参数发送:

kwargs='pk':<s>existing_conversation[0]</s>

使用first() 获取第一个实例并获取pk

kwargs='pk':<b>existing_conversation.first().pk</b>

kwargs='pk':<b>existing_conversation[0].pk</b>

【讨论】:

感谢您提供的方法,但我怎样才能包括清单?我应该使用现有的对话 user1.conversation.all() & user2.conversations.all() &listing 吗? 什么是列表?是同一个查询集吗? 你只能在同一个模型查询集之间使用交集,如果我们使用来自不同模型的不同查询集,它应该如何找到共享实例 抱歉列表是结果中的 result.pk 我有用户应该谈论的列表。 你能做的是:使用filter(),让我更新我的答案

以上是关于Django ORM 验证数据库中的一行的主要内容,如果未能解决你的问题,请参考以下文章

Django--ORM

python-django的ORM

Django学习--ORM机制详解

Django ORM和SQLAlchemy类比

Django models ORM基础操作--白话聊Django系列

Django中的ORM