簡體   English   中英

如何在多對多字段(完全匹配)中通過其對象過濾django模型?

[英]How to filter django model by its objects in many-to-many field (exact match)?

我的代碼中有這個模型:

class Conversation(models.Model):
    participants = models.ManyToManyField(User, related_name="message_participants")

我需要通過“參與者”多對多字段過濾這個“對話”模型對象。 意思是:我有3個用戶對象,所以我想檢索唯一的“對話”對象,其中有3個用戶在其“參與者”字段中。

我試過這樣做:

def get_exist_conv_or_none(sender,recipients):
    conv = Conversation.objects.filter(participants=sender)
    for rec in recipients:
        conv = conv.filter(participants=rec)

其中sender是User對象,“recipients”是User對象列表。 它不會引發錯誤,但它給了我錯誤的對話對象。 謝謝。

編輯:最近的一次嘗試引導我:

def get_exist_conv_or_none(sender,recipients):
    participants=recipients
    participants.append(sender)
    conv = Conversation.objects.filter(participants__in=participants)
    return conv

這基本上有同樣的問題。 它產生的對象在列表中有一個或多個“參與者”。 但我正在尋找的是多對多對象的精確匹配。 意思是,一個具有確切“用戶”的對象是多對多關系。

編輯2:我的最后一次嘗試。 仍然,不會工作。

def get_exist_conv_or_none(sender,recipients):
    recipients.append(sender)
    recipients = list(set(recipients))
    conv = Conversation.objects.annotate(count=Count('participants')).filter(participants=recipients[0])
    for participant in recipients[1:]:
        conv.filter(participants=participant)
    conv.filter(count=len(recipients))
    return conv

好的,我找到了答案:為了完全匹配,我必須對模型進行鏈式過濾,然后確保它具有所需的確切數量的參數,以便多對多字段將具有它需要的所有物品,而不是更多。

我將使用注釋檢查對象編號:( https://docs.djangoproject.com/en/dev/topics/db/aggregation/

結束了這段代碼:

def get_exist_conv_or_none(recipients):
    conv = Conversation.objects.annotate(count=Count('participants')).filter(participants=recipients[0])
    for participant in recipients[1:]:
        conv = conv.filter(participants=participant)
    conv = conv.filter(count=len(recipients))
    return conv

對於使用數據庫索引的快速搜索,我使用以下代碼:

class YandexWordstatQueue(models.Model):
    regions = models.ManyToManyField(YandexRegion)
    regions_cached = models.CharField(max_length=10000, editable=False, db_index=True)
    phrase = models.ForeignKey(SearchPhrase, db_index=True)
    tstamp = models.DateTimeField(auto_now_add=True)

class YandexWordstatRecord(models.Model):
    regions = models.ManyToManyField(YandexRegion)
    regions_cached = models.CharField(max_length=10000, editable=False, db_index=True)
    phrase = models.ForeignKey(SearchPhrase, db_index=True)
    Shows = models.IntegerField()
    date = models.DateField(auto_now_add=True)

@receiver(m2m_changed, sender=YandexWordstatRecord.regions.through)
@receiver(m2m_changed, sender=YandexWordstatQueue.regions.through)
def yandexwordstat_regions_changed(sender, **kwargs):
    if kwargs.get('action') in ['post_add', 'post_remove']:
        instance = kwargs.get('instance')
        l = list(instance.regions.values_list('RegionID', flat=True))
        l.sort()
        instance.regions_cached = json.dumps(l)
        instance.save()

這會增加保存時的開銷,但現在我可以使用此代碼段執行快速過濾:

region_ids = [1, 2, 3] # or list(some_queryset.values_list(...))
region_ids.sort()
regions_cahed = json.dumps(region_ids)
YandexWordstatQueue.objects.filter(regions_cached=regions_cached)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM