Saltar al contenido

¿Cómo se filtra un serializador anidado en Django Rest Framework?

Solución:

Puede crear una subclase de ListSerializer y sobrescribir el to_representation método.

Por defecto el to_representation llamadas a métodos data.all() en el conjunto de consultas anidado. Entonces, efectivamente necesitas hacer data = data.filter(**your_filters) antes de que se llame al método. Luego, debe agregar su ListSerializer subclasificado como list_serializer_class en el meta del serializador anidado.

  1. subclase ListSerializer, sobrescribiendo to_representation y luego llamar super
  2. agregar ListSerializer subclasificado como meta list_serializer_class en el serializador anidado

Aquí está el código relevante para su muestra.

class FilteredListSerializer(serializers.ListSerializer):

    def to_representation(self, data):
        data = data.filter(user=self.context['request'].user, edition__hide=False)
        return super(FilteredListSerializer, self).to_representation(data)


class EditionSerializer(serializers.ModelSerializer):

    class Meta:
        list_serializer_class = FilteredListSerializer
        model = Edition


class QuestionnaireSerializer(serializers.ModelSerializer):
    edition = EditionSerializer(read_only=True)
    company = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = Questionnaire

Probé muchas soluciones de SO y otros lugares.

Encontré solo una solución funcional para Django 2.0 + DRF 3.7.7.

Defina un método en el modelo que tenga una clase anidada. Elabore un filtro que se adapte a sus necesidades.

class Channel(models.Model):
    name = models.CharField(max_length=40)
    number = models.IntegerField(unique=True)
    active = models.BooleanField(default=True)

    def current_epg(self):
        return Epg.objects.filter(channel=self, end__gt=datetime.now()).order_by("end")[:6]


class Epg(models.Model):
    start = models.DateTimeField()
    end = models.DateTimeField(db_index=True)
    title = models.CharField(max_length=300)
    description = models.CharField(max_length=800)
    channel = models.ForeignKey(Channel, related_name="onair", on_delete=models.CASCADE)

.

class EpgSerializer(serializers.ModelSerializer):
    class Meta:
        model = Epg
        fields = ('channel', 'start', 'end', 'title', 'description',)


class ChannelSerializer(serializers.ModelSerializer):
    onair = EpgSerializer(many=True, read_only=True, source="current_epg")

    class Meta:
        model = Channel
        fields = ('number', 'name', 'onair',)

Presta atencion a source="current_epg" y entenderás el punto.

Si bien todas las respuestas anteriores funcionan, encuentro el uso de Django’s Prefetch objetar la forma más fácil de todas.

Di un Restaurant obj tiene una gran cantidad de MenuItems, algunos de los cuales son is_remove == True, y solo desea los que no se eliminan.

En RestaurantViewSet, haz algo como

from django.db.models import Prefetch

queryset = Restaurant.objects.prefetch_related(
    Prefetch('menu_items', queryset=MenuItem.objects.filter(is_removed=False), to_attr="filtered_menu_items")
)

En RestaurantSerializer, haz algo como

class RestaurantSerializer(serializers.ModelSerializer):
    menu_items = MenuItemSerializer(source="filtered_menu_items", many=True, read_only=True)

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *