piston.utils.validate(), POST and FILES

Issue #124 duplicate
Alexander Pugachev
created an issue

Hi, Jesper, you're cool.

validate() has second argument 'operation', name of request's attribute passed by to form constructor.

Multipart/form-data requires to pass 2 arguments to form - request.POST and request.FILES. Currently validate() does not do this.

Please consider to change validate() according to code below: {{{


def smarter_validate(v_form, operation='POST'): @Николай def wrap(f, self, request, a, kwa): if type(operation) in [list, tuple]: form = v_form([getattr(request, x) for x in operation]) else: form = v_form(getattr(request, operation))

    if form.is_valid():
        setattr(request, 'form', form)
        return f(self, request, *a, **kwa)
        raise FormValidationError(form)
return wrap


This version of validate() is backward-compatible and can handle upload forms like this: {{{


... @validate(TheForm, ['POST', 'FILES']) def create(self): ...


Comments (8)

  1. Alberto Donato

    There's another issure related to the "operation" behaviour, in @validate.

    The Mimer.translate() method explicitly removes request.POST and request.PUT, leaving data only in request.data.

    This brakes @validate when data is not uploaded as a form data (I tried json format). With a PUT with an associated form you would use

    @validate(AForm, "PUT")
    def update(...):

    but request.PUT is empty.


    @validate(AForm. "data")
    def update(...):

    works, but I guess this is not the desired behavour.

    I think it would be possible either to leave request.POST/request.PUT or to have validate() look also to request.data as a fallback. Is there any downside I'm missing?

  2. Alberto Donato

    Another consideration on @validate (maybe this should go in a separate report).

    Currently, handler methods decorated with @validate need to explicitly access request.form.cleaned_data to take advantage of validated form data, while normal methods use request.data.

    I think the @validate decorator should also override request.data whith the form cleaned data, allowing a greater reuse of handlers code.

    As an example, to allow only some fields of a model to be updated with a PUT request, would be matter of simply declare a custom form to wrap an update() method which simply calls the superclass update() as in

    def update(self, request, ...):
         return super(MyHandler, self).update(request, ...)

    I know PUT should only upload a complete representation of the object, and PATCH should be used instead for partial update, but this method is not yet widely used

  3. Alberto Donato

    Hi Jesper,

    for form data, the Resource class copies request.POST or request.PUT into request.data, so this is a QueryDict and it works fine with form validation.

    I tried validation with PUT/POST both in JSON and form data format, and it's ok with both formats.

    The only difference between form data and other formats is that in the first case request.data is a QueryDict, while in other formats is a simple dict.

  4. Log in to comment