1
votes

limiter les champs django interrogés dans l'appel SQL à la base de données par jeu de requêtes

J'ai une table avec un objet blob et je voudrais l'exclure de l'appel SQL à la base de données, sauf si cela est spécifiquement demandé. Prêt à l'emploi, django inclut tout dans le jeu de requêtes. Jusqu'à présent, le seul moyen que j'ai trouvé pour limiter le champ est d'ajouter une fonction à la vue get_queryset ()

class DynamicFieldsMixin(object):
    def __init__(self, *args, **kwargs):
        super(DynamicFieldsMixin, self).__init__(*args, **kwargs)
        if "request" in self.context and self.context['request'] is not None:
            fields = self.context['request'].query_params.get('fields')
            if fields:
                fields = fields.split(',')
                # Drop any fields that are not specified in the `fields` argument.
                allowed = set(fields)
                existing = set(self.fields.keys())
                for field_name in existing - allowed:
                    self.fields.pop(field_name)


class TestSerializer(DynamicFieldsMixin,     rest_serializers.ModelSerializer):
    class Meta:
        model = models.TestData
        fields = '__all__'

et de mélanger au sérialiseur pour limiter les champs qu'il vérifie

XXX

cela semble être beaucoup de code pour ce qu'il fait. Existe-t-il un moyen plus simple?


3 Réponses :


0
votes

Django l'a déjà tout de suite sorti de la boîte. Utilisez simplement différer ou uniquement

Defer vous permettra d'exclure un ensemble de champs à partir de l'ensemble de requêtes:

MyModel.objects.only('field_i_want1', 'field_i_want2')

While vous permet uniquement de dire quels champs vous voulez sur l'ensemble de requêtes:

MyModel.objects.defer('field_i_want_to_exclude')


6 commentaires

Ce n'est pas correct. Le "seul" chargera immédiatement les colonnes que vous dites et reportera les autres.


Defer ignorera les champs et ne les récupérera pas de la base de données. C'est sur la documentation.


Relisez mon commentaire.


Je l'ai fait, et cela n'a pas beaucoup de sens. Pardon. Si cela ne vous dérange pas de clarifier.


ah, reporter est ce que je cherchais. Merci!


Vous pouvez mesurer les performances de la seule et différer les valeurs. Les valeurs sont plus rapides.



-1
votes

Utilisez les valeurs () :

MyModel.objects.values('column1', 'column2')


2 commentaires

Ce n'est pas idéal pour ce que op essaie de faire, car les valeurs excluent l'identifiant, sauf si vous le passez explicitement.


C'est la réponse la plus optimale.



0
votes

Id faire quelque chose comme ça pour les objets uniques NON imbriqués. Pour les propriétés imbriquées, vous aurez besoin de plus de logique.

class DynamicFieldListSerializer(serializers.ListSerializer):

    def to_representation(self, data):
        """
        Code is a copy of the original, with a modification between the
        iterable and the for-loop.
        """
        # Dealing with nested relationships, data can be a Manager,
        # so, first get a queryset from the Manager if needed
        iterable = data.all() if isinstance(data, models.Manager) else data

        fields = list(self.child.get_fields().keys())
        iterable = iterable.only(*fields)

        return [
            self.child.to_representation(item) for item in iterable
        ]


class DynamicSerializerFieldsMixin:

    def get_fields(self):
        fields = super().get_fields()
        raw_fields = set(self.context['request'].GET.get('fields', '').split(','))
        # If querysparams ?fields= doesn't evaluate to anything, default to original
        validated_fields = set(raw_fields) & set(fields.keys()) or set(fields.keys())
        return {key: value for key, value in fields.items() if key in validated_fields}

    @classmethod
    def many_init(cls, *args, **kwargs):
        meta = getattr(cls, 'Meta', None)
        if not hasattr(meta, 'list_serializer_class'):
            meta.list_serializer_class = DynamicFieldListSerializer
        return super().many_init(*args, **kwargs)

Pour des exemples, voir:

https://gist.github.com/kingbuzzman/d7859d9734b590e52fad787d19c34b52#file-20-djp>


0 commentaires