In REST framework, we expose the accepted renderer as an 
`request.accepted_renderer` property.
This allows you to switch based on the media type when needed by either 
doing something like:

    if request.accepted_renderer.format == 'yaml':
        # do something specific

or like this:

    if request.accepted_renderer.media_type == 'application/json':
        # do something specific

That allows you to do media type specific stuff if needed, but generally 
you'll just access `request.DATA`, and not need to be concerned about 
exactly what media type was decoded for you.  (Of course the API specifics 
could be open to bike shedding.)  In response to Jonathan's particular 
query, REST framework supports a YAML parser, and there's never any need to 
do specific branching to detect it, because it just returns native python 
datatypes: lists, dicts, etc... exactly the same as the JSON parser does.

And yes, different media types can and do have different capabilities (eg. 
form data decodes into QueryDict objects, rather than regular dicts) but 
you're able to switch on that if specifically needed.

I'm not at all keen on the idea of injecting differing attribute names on 
the request based on the media type that is decoded, partly because it just 
feels like an odd API to me, but more concretely because it unnecessarily 
ties your view logic to your parser classes, and doesn't allow you to 
easily support views that accept multiple content types.  (The combination 
of either form data or json being the most common.) 

> what else do you have in DRF's Request that you would need

The bits of API we'd need to support something like this:

* `request.DATA` / `request.data` for accessing the parsed data.
* `request.parsers` or similar for modifying the parsers prior to parsing 
on a per-view basis.  (Note the parallel to request.upload_handlers)
* `request.accepted_parser` or similar for branching on media type if 
needed.
* A setting that controls the default set of installed parsers.

There are a couple of other bits of behaviour/API, but they're not related 
to request parsing.  I wouldn't mind discussing those as well at some 
point, but I don't want to go off on a tangent just yet.

The other core thing would be the question of if dealing with request 
parsing also means we should necessarily also tackle response rendering 
(and ideally, content negotiation) at the same time.  I don't really mind 
whether that'd be seen as a requirement or not, but it is important that we 
have a consistent design between both parsing and rendering.

Cheers all,

  Tom

On Thursday, 5 September 2013 00:31:43 UTC+1, Curtis Maloney wrote:

To weight in from an author of a different API tool....
>
> In django-nap there's a simple "get_request_data" method which, 
> essentially, determines how to parse the request according to the content 
> type.  However, currently each API only supports a single serialiser format 
> [and HTTP Form encoding] so there's little guessing involved.
>
> However, I wouldn't want to see the same on Request, unless there was also 
> a direct way to imply the type you want.  For instance, if I get a request 
> that's in XML, and I ask for request.JSON, I'd like it to either yield 
> empty or raise an error.  Whereas when I didn't case, accessing 
> request.DATA would make a best guess.
>
> So I see two paths... either you use a "Decode it for me according to 
> content-type" interface, or a "Treat is as this type, and fail predictably 
> if it's not" one.
>
> The current GET/POST is, of course, the latter.  And there's no reason we 
> can't have both :)
>
> --
> Curtis
>
>
>
> On 5 September 2013 04:06, Jonathan Slenders 
> <jonathan...@gmail.com<javascript:>
> > wrote:
>
>> Would that mean that the object returned by request.DATA/POST/whatever 
>> could be a different type, depending on what the user posted?
>>
>> I don't want to see code like:
>>
>> if isinstance(request.DATA, YamlObject): ...
>> elif isinstance(request.DATA, dict): ...
>>
>> although, I'm not sure how any view could handle any random 
>> content-type...
>>
>>
>>
>> Le mercredi 4 septembre 2013 13:57:29 UTC+2, Marc Tamlyn a écrit :
>>>
>>> The thing with request.POST is that it's kinda unintuitive when extended 
>>> to other HTTP methods (e.g. PUT). This is why the old request.raw_post_data 
>>> was renamed request.body.
>>>
>>> request.POST would behave in the expected traditional web way of picking 
>>> up form encoded POST data, which would also be available in request.DATA as 
>>> well, but request.DATA is the "new" way of doing it. Personally, I'd 
>>> lowercase it though, to remove confusion with the PHP $POST $GET $REQUEST 
>>> which we mimic on the request object. The generally have different use 
>>> cases anyway - one for complex web things and the other for standard web 
>>> browsers.
>>>
>>> (the above is what tom said...)
>>>
>>> Tom - what else do you have in DRF's Request that you would need?
>>>
>>>
>>> On 4 September 2013 12:56, Tom Christie <christ...@gmail.com> wrote:
>>>
>>>> > Creating a request.DATA attribute would break compatibility with old 
>>>> code and seem to me less intuitive.
>>>>
>>>> The implementation would ensure `request.POST` would still be populated 
>>>> for form data.
>>>>
>>>> There wouldn't have to be any backwards incompatible changes, and usage 
>>>> of `request.DATA` (or whatever better name there might be, perhaps simply 
>>>> `request.data`) would be entirely optional for using with generic request 
>>>> parsing, instead of form data only.
>>>>
>>>>
>>>> > Where should request.FILE go in that case
>>>>
>>>> request.FILES would be populated by form data as normal, and would be 
>>>> empty on JSON or other submissions.  In order to support multipart parsing 
>>>> the request parsing API would need to provide for parsers that support 
>>>> file 
>>>> upload, in a similar way that REST framework currently does.
>>>>
>>>> > Would request.POST just be a call to request.DATA?
>>>>
>>>> That's an open question, but I'd probably expect it to only return data 
>>>> if the request contains multipart or url-encoded form data.  (Ie. the 
>>>> behaviour wouldn't change.)
>>>>
>>>> Cheers,
>>>>
>>>>   Tom
>>>>
>>>> On Wednesday, 4 September 2013 12:33:00 UTC+1, Stefan Berder wrote:
>>>>>
>>>>> Tom,
>>>>> I agree that the middleware solution is not the best and in my mind 
>>>>> creates fragmentation of the same type of request handling.
>>>>>
>>>>> A generic content-type framework would make the request parsing more 
>>>>> flexible, stronger to change in the future and open the door to any type.
>>>>>
>>>>> I'm curious about the choice of request.DATA though, when doing a POST 
>>>>> request, I expect the data to be in the POST dictionary and nowhere else. 
>>>>> Creating a request.DATA attribute would break compatibility with old code 
>>>>> and seem to me less intuitive. Where should request.FILE go in that case? 
>>>>> Would request.POST just be a call to request.DATA?
>>>>>
>>>>> Stefan
>>>>>
>>>>> On Wednesday, 4 September 2013 18:13:12 UTC+8, Tom Christie wrote:
>>>>>>
>>>>>> Hi Stefan,
>>>>>>
>>>>>> Sure, I'd be interested in seeing us improve how we deal with JSON 
>>>>>> requests and responses.
>>>>>>
>>>>>> My preference would be to introduce a request parsing and response 
>>>>>> rendering API that allows us to support not just JSON, but any media 
>>>>>> type 
>>>>>> that has a parser installed for it.  (I've commented on some of this 
>>>>>> before, 
>>>>>> here<https://groups.google.com/forum/#!searchin/django-developers/tomchristie%7Csort:date/django-developers/Qr0EorpgYKk/6qyCrVqZwmMJ>,
>>>>>>  
>>>>>> although I think I'm warming towards the idea that it's probably about 
>>>>>> time 
>>>>>> we started addressing at least some of this in core.)
>>>>>>
>>>>>> Unsurprisingly I'd suggest the same general approach that is used in 
>>>>>> REST framework - A lazy `request.DATA` attribute (or similar) that when 
>>>>>> accessed, inspects the media type on the request, and parses the request 
>>>>>> stream with an appropriate parser if possible.  The installed parsers 
>>>>>> can 
>>>>>> be configured globally, or on a per-request basis.  The existing 
>>>>>> multipart 
>>>>>> and form-encoded parsing behaviour would no longer be a special case 
>>>>>> baked 
>>>>>> directly into the request object, but instead be the default installed 
>>>>>> parsers.
>>>>>>
>>>>>> Taking this approach makes it trivial to write views that can handle 
>>>>>> both JSON and form data, and providing a proper parser API makes it easy 
>>>>>> for developers to package up and share their own parser implementation, 
>>>>>> such as YAML, XML and MsgPack.  (And, looking forwards, JSON-based media 
>>>>>> types such as hypermedia types.)
>>>>>>
>>>>>> In REST framework this behaviour is (by necessity) implemented in a 
>>>>>> Request object that wraps the underlying HttpRequest, but the same basic 
>>>>>> implementation can be applied to implementing it directly in the Request 
>>>>>> object, and would be somewhat easier.
>>>>>>
>>>>>> I'm interested to see Marc suggesting middleware specifically for 
>>>>>> handling JSON requests.  That'd work, and would be a simple approach.  
>>>>>> My 
>>>>>> reservations with that would be:
>>>>>>
>>>>>> * We'd not be making it any easier for users to deal with request 
>>>>>> parsing generally.
>>>>>> * There's no way to write views that deal with request data in an 
>>>>>> agonistic way, and dealing with differing media types would require 
>>>>>> switching based on the media type in the view itself.  For example, the 
>>>>>> generic views would still only support form data.  As another example, 
>>>>>> if 
>>>>>> you wanted to add, say, MsgPack support to your application, you'd need 
>>>>>> to 
>>>>>> re-write all your views.
>>>>>>
>>>>>> From my point of view this is already a solved problem, and I'd 
>>>>>> really like to see a generic approach to handling request data, and a 
>>>>>> corresponding approach to rendering responses into an appropriate media 
>>>>>> type.
>>>>>>
>>>>>>  All the best,
>>>>>>
>>>>>>   Tom
>>>>>>
>>>>>> On Tuesday, 3 September 2013 06:30:04 UTC+1, Stefan Berder wrote:
>>>>>>>
>>>>>>> Hi,
>>>>>>> I looked around the list and couldn't find any mention of this 
>>>>>>> subject.
>>>>>>>
>>>>>>> In `django.http.request.**HttpReque**st._load_post_and_**files()` 
>>>>>>> there is explicit mention of two content type ('multipart/form-data' 
>>>>>>> and 
>>>>>>> 'application/x-www-form-**urlenc**oded'), any other content type 
>>>>>>> will get empty values for self._post.
>>>>>>>
>>>>>>> Given that a lot of user form interaction is now happening through 
>>>>>>> 'XMLHttpRequest', I think that the 'application/json' content type 
>>>>>>> should 
>>>>>>> be supported. A lot of javascript libraries will use json as the 
>>>>>>> default 
>>>>>>> format:
>>>>>>> * angularjs: 
>>>>>>> http://docs.angularjs.org/api/****ng.$http<http://docs.angularjs.org/api/ng.$http>,
>>>>>>>  
>>>>>>> see "Setting HTTP Headers"
>>>>>>> * emberjs: https://github.com/emberjs/**dat**a/blob/master/packages/
>>>>>>> **ember-**data/lib/adapters/rest_**adapter**.js#L974<https://github.com/emberjs/data/blob/master/packages/ember-data/lib/adapters/rest_adapter.js#L974>
>>>>>>> * backbone: http://backbonejs.org/#Sync
>>>>>>> * jquery: 
>>>>>>> http://api.jquery.com/jQuery.**a**jax/<http://api.jquery.com/jQuery.ajax/>(the
>>>>>>>  only one using 'application/x-www-form-
>>>>>>> **urlenc**oded' by default)
>>>>>>>
>>>>>>> I'm trying primarily to create a discussion on the subject and am 
>>>>>>> ready to provide the code for it as I had to write it. This would help 
>>>>>>> avoid hacks to handle the request object in my view. 
>>>>>>>
>>>>>>> I know there are some apps to handle API construction 
>>>>>>> (django-tastypie, django-rest, django-piston and certainly others) they 
>>>>>>> use 
>>>>>>> either request wrappers or request handling in their views.
>>>>>>>
>>>>>>> Stefan
>>>>>>>
>>>>>>  -- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "Django developers" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to django-develop...@**googlegroups.com.
>>>> To post to this group, send email to django-d...@**googlegroups.com.
>>>>
>>>> Visit this group at 
>>>> http://groups.google.com/**group/django-developers<http://groups.google.com/group/django-developers>
>>>> .
>>>> For more options, visit 
>>>> https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
>>>> .
>>>>
>>>
>>>  -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Django developers" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to django-develop...@googlegroups.com <javascript:>.
>> To post to this group, send email to 
>> django-d...@googlegroups.com<javascript:>
>> .
>> Visit this group at http://groups.google.com/group/django-developers.
>> For more options, visit https://groups.google.com/groups/opt_out.
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to