将 Django LogEntry (ContentType) 与 GenericRelation 字段一起使用

Using Django LogEntry (ContentType) with a GenericRelation field

描述

我正在 Django 项目上编写一个 API,它将获取特定模型的所有 LogEntry 并按特定模型的字段过滤它们。 所以我的模型看起来像这样:

from django.contrib.admin.models import ContentType, LogEntry
from django.contrib.auth.models import Group
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.db import models


class LogEntryProxy(LogEntry):
    content_object = GenericForeignKey()

    class Meta:
        proxy = True


class HomeItem(models.Model):
    # Some Fields
    groups = models.ManyToManyField(Group, related_name="home_item_group")
    log_entry_relation = GenericRelation(LogEntryProxy, related_query_name='log_homeitem')

在视图中,我需要能够进行查询以获取引用 HomeItemLogEntryProxy 项目,并通过有权访问它的 groups 过滤它们并序列化结果。所以像这样:

log_entry_queryset = LogEntryProxy.objects.filter(log_homeitem__groups__in=user.groups.all()).distinct()

我的序列化程序看起来像这样(使用 "djangorestframework"):

from rest_framework import serializers


class LogEntryHomeItemSerializer(serializers.ModelSerializer):
    content_object = HomeItemSerializer(many=False)
    object_id = serializers.IntegerField()

    class Meta:
        model = LogEntryProxy
        fields = ('object_id', 'action_flag', 'content_object', )

而且有效!

问题

所以你可能会问什么问题!

问题是 LogEntry 创建和编辑等操作起作用了! API 会给你结果,但是当你删除一个 HomeItem 对象时,所有指向它的 LogEntry 对象也将被删除,因此不会给出删除操作api(加上所有指向该对象的创建和编辑对象也将被删除)。这都是因为 Django 的 GenericRelation 不支持 on_delete。如果我删除 GenericRelatin 字段,这不会发生,但是我必须能够通过 LogEntryProxy 查询集中的 groups 过滤 HomeItem 并且它不能没有 GenericRelation.

我想知道是否有人可以告诉我在这种情况下该怎么做?

我应该实施自定义日志记录系统吗?或者还有一个我还没见过的方法!

尝试:

homeids = HomeItem.objects.filter(groups__in=user.groups.all()).values_list('id',flat=True)
log_entry_queryset = LogEntryProxy.objects.filter(object_id__in=homeids,content_type_id=ContentType.objects.get_for_model(HomeItem).id).distinct()

如果你这样查询就不需要GenericRelation

更新: 上面的查询不会获取删除操作的日志。 可以这样做:

from django.db.models import Q 
from django.contrib.admin.models import DELETION 
log_entry_queryset = LogEntryProxy.objects.filter(Q(object_id__in=home_ids,content_type_id=ContentType.objects.get_for_model(HomeItem).id) | Q(action_flag=DELETION,content_type_id=ContentType.objects.get_for_model(HomeItem).id)).distinct()