2015-11-06 2 views
-1

описанииИспользование Django LogEntry (ContentType) с полем GenericRelation

Я пишу API на проект Django, который получит все 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') 

По мнению мне нужно, чтобы иметь возможность делать запросы, извлекающие LogEntryProxy элементов, относящиеся к HomeItem и фильтровать их по 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, все объекты, указывающие на него, также будут удалены, поэтому api не будет удалять действие по удалению (плюс все созданные и редактируемые, указывающие на это объект также будет удален). и все потому, что Django's GenericRelation не поддерживает on_delete. Если я удалю поле GenericRelatin, этого не произойдет, но я должен уметь фильтровать HomeItem на groups в запросе LogEntryProxy, и это невозможно сделать без GenericRelation.

Мне было интересно, может ли кто-нибудь сказать мне, что делать в этой ситуации?

Должен ли я использовать пользовательскую систему регистрации? или есть другой способ, которого я еще не видел!

ответ

0

попробовать:

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

Update: Этот запрос не закачает logentries от удаления действия. Это может быть сделано как:

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() 
+0

Я предполагаю, что это нуждается в этом тоже 'LogEntryProxy.objects.filter (object_id__in = homeids, content_type_id = ContentType.objects.get_for_model (HomeItem) .id) .distinct()', чтобы получить объект HomeItem не объекты других моделей с теми же идентификаторами, что и те, которые были переданы в вашем ответе – Behzad

+0

@BehzadMokhtarei oh, да, я пропустил это. Я отредактирую свой ответ. –

+0

Это неловко, но я думаю, что мы пропустили большую картину здесь, удаленный объект не будет в запросе HomeItem, который мы сделали в первую очередь. поэтому снова действие удаления не будет показано, поэтому я предполагаю, что этот код получит нас там лучше 'от django.db.models import Q; из django.contrib.admin.models import DELETION; ct_id = ContentType.objects.get_for_model (HomeItem) .id; log_entry_queryset = LogEntryProxy.objects.filter (Q (object_id__in = home_ids, content_type_id = ct_id) | Q (action_flag = DELETION, content_type_id = ct_id)). distinct() ' – Behzad

Смежные вопросы