Как скрыть поле, являющееся правящим ключом, в сериализаторе на основе утверждения

Это мой сериализатор

class SparkleTemplateSerializer(serializers.ModelSerializer):
    
    notifications = NotificationTemplateSerializer(source='notificationtemplate_set', many=True)
    rules = RuleTemplateSerializer(source='ruletemplate_set', many=True)   
    class Meta:
        model = SparkleTemplate
        fields = ['id', 'name', 'description', 'enabled', 'run_schedule', 'notifications', 'rules']

Мне нужно показывать и скрывать поле "notifications", которое является внешним ключом, как вы можете видеть, но это должно происходить, если некоторая переменная является true или false.

Вот как я пытался сделать это, добавив приведенный ниже код в сериализатор, но я думаю, что это не работает из-за свойства fields в Meta

def to_representation(self, obj):
        show = NotificationTemplate._meta.get_field('show')
        rep = super(SparkleTemplateSerializer, self).to_representation(obj)
        if show is False:
         rep.pop('notifications', None)
        return rep    

Я также пробовал исключить "notifications" и создать другой сериализатор, но это не работает, так как "notifications" должен быть там, поэтому я получал ошибки. Спасибо

Мы можем удалить элементы в полученном словаре из to_representation(), обратившись к атрибуту show каждого элемента в notifications.

В зависимости от того, как вы хотите, чтобы отображались уведомления, вот 2 варианта:

  • Вариант-1: Если вы хотите удалить все notifications, если хотя бы 1 show является False
  • .
  • Вариант-2: Если вы хотите удалить только notifications, где show является False
def to_representation(self, obj):
    rep = super().to_representation(obj)

    # Option 1: If you want to remove all notifications if at least 1 show is False
    # if any(notif["show"] is False for notif in rep["notifications"]):
    #     del rep['notifications']  # Or rep.pop('notifications')

    # Option 2: If you only want to remove the notifications where show is False
    rep["notifications"] = list(filter(lambda notif: notif["show"], rep["notifications"]))

    return rep

Вы можете использовать prefetch_related метод с Prefetch объектом , обычно это используется для решения N + 1 проблемы, но другая вещь позволяет предоставить queryset для префетчированного объекта.

Следовательно, вы можете изменить свой вид следующим образом:

from django.db.models import Prefetch


class SparkleTemplateView(ListAPIView):

    serializer_class = SparkleTemplateSerializer

    def get_queryset(self):
        user = self.request.user
        shown_notifications = NotificationTemplate.objects.filter(show=True)
        queryset = SparkleTemplate.objects.filter(
            branch_owner=user.branch
        ).prefetch_related(
            Prefetch('notificationtemplate_set', queryset=shown_notifications)
        )
        return queryset

Теперь вы можете не модифицировать сериализаторы to_representation, поскольку вы уже отфильтровали их, чтобы показывать только необходимые NotificationTemplate объекты.

Вернуться на верх