Django-filter: Genera una excepción si los campos no se dan en FilterSet

Creado en 28 sept. 2016  ·  11Comentarios  ·  Fuente: carltongibson/django-filter

class BooksFilter(filters.FilterSet):
    class Meta:
        model = Books

Al omitir la opción fields en una clase de conjunto de filtros (como se indicó anteriormente), todos los campos del modelo se incluirán en el conjunto de filtros. Esto puede provocar una fuga de información cuando se usa junto con DRF, donde el formulario se representa en la API navegable.

Tanto Django como DRF requieren que los campos se especifiquen explícitamente en formularios/serializadores debido a los posibles problemas de seguridad. Esto también debería ser necesario en los conjuntos de filtros Django-filter.
http://www.django-rest-framework.org/api-guide/serializers/#specifying -what-fields-to-include
https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#selecting-the-fields-to-use

Estoy feliz de contribuir con un PR o explicar más sobre en qué situaciones esto puede conducir a la fuga de información, si es necesario.

ImprovemenFeature

Comentario más útil

por cierto, la fuga de datos se solucionó parcialmente en el n.º 451. En este momento, debería ver advertencias de desuso sobre comportamiento indefinido/cambiante. En 1.0, el nuevo comportamiento es que un Meta.fields o Meta.fields = None ausente no hace nada.

Todos 11 comentarios

@nip3o Sí. Feliz de ver esto.

También me gustaría que los campos requieran filtros declarados, según DRF, mientras estás en eso... 😉

por cierto, la fuga de datos se solucionó parcialmente en el n.º 451. En este momento, debería ver advertencias de desuso sobre comportamiento indefinido/cambiante. En 1.0, el nuevo comportamiento es que un Meta.fields o Meta.fields = None ausente no hace nada.

También me gustaría que los campos requieran filtros declarados, según DRF, mientras lo hace

No estoy seguro de cómo funcionaría esto con la sintaxis dict para Meta.fields . p.ej:

class UserFilter(filters.FilterSet):
    username = filters.CharFilter()

    class Meta:
        model = User
        fields = {
            'name': ['contains', 'startswith', 'endswith', ...'],
            ???
        }

No estoy seguro de cómo funcionaría esto con la sintaxis dict

Por supuesto.

Todavía estoy un poco :-1: en esto. No veo una forma de resolver la sintaxis de dictado Meta.fields con filtros declarados. Al menos, no de una manera que no sea incómoda:

class UserFilter(filters.FilterSet):
    username = filters.CharFilter(name='username', lookup_expr='exact')
    username_like = filters.CharFilter(name='username', lookup_expr='icontains')
    relevance = filters.CharFilter(method='filter_relevance')

    class Meta:
        model = User
        fields = {
            'name': ['contains', 'startswith', 'endswith', ...'],
            'username': ['exact'],  # match w/ the lookup_expr? 
            'username_like': ['icontains'],
            'relevance': [???]  # What about method filters?
        }

Además, este requisito se encuentra con problemas para los campos de modelos personalizados que no heredan una clase de campo que se encuentra en FilterSet.FILTER_DEFAULTS . Los campos personalizados requerirían lo siguiente:

class NetworkSettingFilter(FilterSet):
    mask = MaskFilter(...)

    class Meta:
        model = NetworkSetting
        fields = ['mask']
        filter_overrides = {
            SubnetMaskField: {'filter_class': MaskFilter},
        }

# vs.

class NetworkSettingFilter(FilterSet):
    mask = MaskFilter(...)

    class Meta:
        model = NetworkSetting

Nota al margen: este último punto es algo que _podríamos_ arreglar. Tendríamos que reescribir la generación automática para que se comporte como los serializadores de DRF en lugar de como los formularios modelo de Django. De cualquier manera, mi principal preocupación es el conflicto de sintaxis.

está bien. Dejémoslo por ahora.

Me gusta la propuesta original. Me inclino a enfocarlo en _Si fields es una lista..._ Pero necesito pensarlo un poco más.

Un poco de ida y vuelta, pero voy a volver a marcar este hito solo para el problema original .

Se debe declarar fields o exclude . fields = '__all__' debería ser el mínimo.

(No hacer cumplir que las listas coincidan es algo a lo que podemos volver).

El código DRF relevante está aquí :

        assert not (fields is None and exclude is None), (
            "Creating a ModelSerializer without either the 'fields' attribute "
            "or the 'exclude' attribute has been deprecated since 3.3.0, "
            "and is now disallowed. Add an explicit fields = '__all__' to the "
            "{serializer_class} serializer.".format(
                serializer_class=self.__class__.__name__
            ),
        )

Necesitamos una adición similar en filters_for_model :

    # Setting exclude with no fields implies all other fields.
    if exclude is not None and fields is None:
        fields = ALL_FIELDS

Tendrá que estar obsoleto para comenzar.

Se debe declarar fields o exclude . fields = '__all__' debería ser el mínimo.

Definitivamente puedo estar detrás de eso. Actualmente trabajando en un PR.

Frio.

Pensando en, no te preocupes por la depreciación. Es un pequeño cambio, en un cambio de versión importante. Solo asegúrese de mencionarlo en las notas de cambio. 👍🏽

Pensando en, no te preocupes por la depreciación. Es un pequeño cambio, en un cambio de versión importante. Solo asegúrese de mencionarlo en las notas de cambio.

La intención es ligeramente diferente, pero en realidad cubrimos esto aquí .

Además, actualmente se está refactorizando filters_for_model para no intentar generar filtros para los filtros declarados. (Esto es relevante para el ejemplo de subred/máscara donde fields = ['mask'] generaría una excepción innecesaria.

Cerrado por #550

¿Fue útil esta página
0 / 5 - 0 calificaciones