将 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')
在视图中,我需要能够进行查询以获取引用 HomeItem
的 LogEntryProxy
项目,并通过有权访问它的 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()
描述
我正在 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')
在视图中,我需要能够进行查询以获取引用 HomeItem
的 LogEntryProxy
项目,并通过有权访问它的 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()