12

我正在运行关于用户数据的指标,并希望排除拥有“@example.com”或“@test.com”等虚假电子邮件的用户。

我试过

emails_to_exclude = ['@example.com', '@test.com', '@mailinator.com' ....]
Users.objects.exclude(email__endswith__in=emails_to_exclude)

不幸的是,这不起作用。看起来endswithin对方玩得不太好。有任何想法吗?

4

6 回答 6

31

只需遍历 QuerySet,因为QuerySet 是惰性的

emails_to_exclude = ['@example.com', '@test.com', '@mailinator.com' ....]
users = Users.objects
for exclude_email in emails_to_exclude:
    users = users.exclude(email__endswith=exclude_email)
users = users.all()
于 2012-05-26T19:39:12.790 回答
2

您也可以在单个查询中使用正则表达式来执行此操作。

emails_to_exclude = ['@example.com', '@test.com', '@mailinator.com' ....]
User.objects.exclude(email__regex = "|".join(emails_to_exclude))

我不知道这个查询的效率。

这不适用于SQLite,因为它没有内置的正则表达式支持。

于 2012-05-29T07:07:01.687 回答
1

您可能可以遍历电子邮件并建立一个Q Object。实际上,如果你很聪明,你可能会做一个 1-liner。

User.objects.exclude(bitwise_or_function[Q(email__endswith=e) for e in emails_to_exclude])

类似的东西。我不记得按位或整个列表的功能,我的 Python 生锈了。

于 2012-05-26T19:28:30.330 回答
1

这应该适用于最新版本的 Python 和 Django。该reduce函数是一个很好的朋友。

from functools import reduce
from operator import or_
from django.db.models import Q

emails_to_exclude = ['@example.com', '@test.com', '@mailinator.com' ....]
users = ( Users.objects
    .exclude( reduce( or_, ( 
        Q(( "email__endswith", k ))
        for k in emails_to_exclude 
    ) ) )
)
于 2019-01-07T08:04:34.733 回答
0

我更改了排除输入以使其成为一个set并且没有“@”。否则,这应该做你想要的。

>>> emails = ['foo@example.com', 'spam@stackoverflow.com', 'bad@test.com']
>>> excludes = {'example.com', 'test.com', 'mailinator.com'}
>>> [email for email in emails if email.split('@')[-1] not in excludes]
['spam@stackoverflow.com']
于 2012-05-26T19:33:30.817 回答
0

实现这一目标的另一种方法:

from django.contrib.auth.models import User
from django.db.models import Q

emails_to_exclude = ['@example.com', '@test.com', '@mailinator.com']

users = User.objects.all()

filters = Q()
for ending in emails_to_exclude:
    filters |= Q(email__endswith=ending)

filtered_users = users.filter(~filters)
于 2021-07-09T12:28:31.033 回答