Python 在不相关的Django模型上执行SQL联接?

Python 在不相关的Django模型上执行SQL联接?,python,django,orm,Python,Django,Orm,我有两个模型,User(django.contrib.auth.Models.User)和一个名为Log的模型。两者都包含一个“电子邮件”字段。日志没有指向用户模型的ForeignKey。我试图弄清楚如何使用email字段作为公共项在这两个表上执行连接 基本上,我希望能够执行两个查询。用于筛选的基本联接 #Get all the User objects that have related Log objects with the level parameter set to 3. User.o

我有两个模型,User(django.contrib.auth.Models.User)和一个名为Log的模型。两者都包含一个“电子邮件”字段。日志没有指向用户模型的ForeignKey。我试图弄清楚如何使用email字段作为公共项在这两个表上执行连接

基本上,我希望能够执行两个查询。用于筛选的基本联接

#Get all the User objects that have related Log objects with the level parameter set to 3.
User.objects.filter(log__level=3)
我还想做一些总结

User.objects.all().anotate(Count('log'))
当然,也能做相反的事情会很好

log = Log.objects.get(pk=3)
log.user...
有没有办法用ORM做到这一点?也许我可以在模型的元类中添加一些东西来“激活”关系

谢谢

为什么不使用

示例(未测试):

对于
User.objects.filter(log\u level=3)
部分,这里与额外(未测试)部分等效:


Log.email值是否始终与用户对应?如果是这样,那么只向日志对象添加一个ForeignKey(用户)怎么样

class Log(models.Model):
    # ...
    user = models.ForeignKey(User)
有了FK to User,找到您想要的东西变得相当简单:

User.objects.filter(log__level=3)
User.objects.all().anotate(Count('log'))

user.log_set.all()
user.log_set.count()

log.user
如果Log.email值不必属于某个用户,则可以尝试将方法添加到

然后像这样使用它:

user = User.objects.get(pk=1)
logs_for_user = Log.objects.for_user(user)

您可以使用MonkeyPatching/DuckPunching在用户类中添加一个额外的方法:

def logs(user):
    return Log.objects.filter(email=user.email)

from django.contrib.auth.models import User
User.logs = property(logs)
现在,您可以查询用户,并请求附加的日志(例如,在视图中):

这种类型的进程在Ruby世界中很常见,但在Python中似乎不受欢迎


(前几天我遇到了DuckPunching这个词。它是基于Duck类型的,我们不关心什么是类:如果它像鸭子一样嘎嘎叫,那么就我们而言,它就是鸭子。如果你打它的时候它不嘎嘎叫,那么继续打直到它嘎嘎叫为止)。

这适用于anotate用例。但对于我提到的另一个用户案例,情况并非如此。我正试图找到一种方法,通过ORM中的一个查询来实现这一点(如果可能的话,我宁愿不使用原始SQL)?查看单独查询是否足够快,如果不够快,则查看优化。您可以根据您添加的内容进行筛选。extra()日志实际上是第三方应用程序的一部分。因此,添加一个新字段并不理想。我认为,结合注释,这应该涵盖您的两个用例。因此,要“获取所有具有级别参数设置为3的相关日志对象的用户对象”,您应该为每个用户调用logs函数。好像有很多疑问。Extra允许在一个查询中执行此操作。
class LogManager(models.Manager):
    def for_user(self, user):
        return super(LobManager, self).get_query_set().filter(email=user.email)

class Log(models.Model):
    # ...
    objects = LogManager()
user = User.objects.get(pk=1)
logs_for_user = Log.objects.for_user(user)
def logs(user):
    return Log.objects.filter(email=user.email)

from django.contrib.auth.models import User
User.logs = property(logs)
user = request.user
logs = user.logs