比较模型B的字段django中的模型A的字段值

时间:2017-04-20 09:40:48

标签: python django django-queryset

我在两个模型中都有100k的记录' A'在模型' B'

前:

class A(models.Model):
    user_email = models.EmailField(null=True, blank=True)
    user_mobile = models.CharField(max_length=30, null=True, blank=True)
    book_id = models.CharField(max_length=255, null=True, blank=True)
    payment_gateway_response = JSONField(blank=True, null=True)

class B(models.Model):
    order = models.ForeignKey(A, null=True, blank=True)
    pay_id = models.CharField(max_length=250, null=True, blank=True)
    user_email = models.EmailField(null=True, blank=True)
    user_mobile = models.CharField(max_length=30, null=True, blank=True)
    created = models.DateTimeField(blank=True, null=True)
    total_payment = models.DecimalField(decimal_places=3, max_digits=20, blank=True, null=True)

我希望使用A的值

来获取B的对象

例如

all_a = A.objects.all()
for a in all_a:
   b = B.objects.filter(user_email=a.user_email, user_mobile=a.user_mobile)

这很好,我得到的结果。但是因为它的100k记录占用了太多时间。 for循环迭代需要时间。在django中有没有更快的方法呢?

3 个答案:

答案 0 :(得分:1)

您可以使用这些值获取a和过滤器b中每个值的列表。

a = A.objects.all()
emails = list(a.values_list('user_email', flat=True))
mobiles = list(a.values_list('user_mobile', flat=True))

b = B.objects.filter(user_email__in=emails, user_mobile__in=mobiles)

如果结果可能有一对未在A中配对的电子邮件和移动电话。但是如果您确保电子邮件和手机在A中是唯一的,并且每个B中的电子邮件和移动电话都基于A&#中的一个39;模型,然后你不会有任何问题。

答案 1 :(得分:0)

如果您对缓存A模型不感兴趣,则可能会使用iterator()提高效果(参见参考https://docs.djangoproject.com/en/1.11/ref/models/querysets/#iterator):

for a in A.objects.all().iterator():
    b = B.objects.filter(user_email=a.user_email, user_mobile=a.user_mobile)

答案 2 :(得分:0)

你可以做到

import operator
from django.db.models import Q

q = A.objects.all().values('user_email', 'user_mobile')
B.objects.filter(reduce(operator.or_, [Q(**i) for i in q]))

如果你想对每个b对象进行一些操作取决于a。这不是那种方法。