My reading of this discussion boils down to "if we get rid of is_ajax (a buy-in 
convention nobody can rely on), how do people decide if it's an AJAX call or 
not?". To my mind, the "content negotiation" advocates have it right: HTTP has 
a mechanism for determining what response format is desired.

If Django were to provide a solid API for parsing Accept headers [not as easy 
as it sounds] and selecting a preferred response type [based on accept 
preference weights] ... would that take care of the bulk of "content 
negotiation"?

I could imagine a view progressing past the boiler plate [verifying the target 
object exists, etc], doing its "work", then checking what response form to use, 
and branching there.

--
Curtis


On Wed, 20 Nov 2019, at 21:04, Jure Erznožnik wrote:
> Agree. 

> I understood that the discussion already turned to *"**If it is deprecated, 
> then the question that arises naturally is "What would be the proper/new way 
> of doing it?"**"*. 

> Also, to clarify:

> What I wrote wasn't trying to impose a particular solution. I was just hoping 
> to point out the challenges involved.


> LP,
>  Jure

> On 20/11/2019 02:17, Matemática A3K wrote:
>> 
>> 
>> On Tue, Nov 19, 2019 at 9:20 PM Matemática A3K <matematica....@gmail.com> 
>> wrote:
>>> 
>>> 
>>> On Tue, Nov 19, 2019 at 1:29 PM Jure Erznožnik <jure.erznoz...@gmail.com> 
>>> wrote:
>>>> Sorry for barging in like this, but this is actually a problem I have been 
>>>> dealing with quite a bit lately, so:

>>>> In my work I very often have to decide, depending on what's calling, what 
>>>> the rendered output might be. Ultimately I went with DRF and its content 
>>>> negotiation, though even that one - as implemented - sometimes isn't 
>>>> sufficient.

>>>> See, the problem sometimes isn't that you request JSON and then get JSON, 
>>>> request HTML and get HTML.

>>> I think content negotiation is about giving the option to request the 
>>> content in different formats, not rendering different content based on 
>>> which format is requested.
>>>> You also have to cater for exceptions. Maybe a 4xx would return additional 
>>>> objects to insert into the DOM while a 200 would be fine with a JSON or 
>>>> even without data. What about 500?

>>> This (and below) is about how to design a particular API for your needs, I 
>>> think it is out of the scope of the problem discussed. The problem 
>>> discussed is that is_ajax is not a reliable way to determine the origin of 
>>> a request (and then format the content of a response)
>> 
>> (let me try to expand myself a bit so we can refocus)
>> 
>> If it is deprecated, then the question that arises naturally is "What would 
>> be the proper/new way of doing it?" because it is a pattern that have been 
>> applied previously (i.e. 
>> https://docs.djangoproject.com/en/2.2/topics/class-based-views/generic-editing/#ajax-example),
>>  then decorators have been proposed and refactors.
>> 
>> It seems to me that if there is no reliable way of determining it from the 
>> back-end side, then in the end it will be a convention between the front and 
>> the back. This could be a GET parameter, a "ClientWants: JSONOrNothing" 
>> header, or whatever convention you like to make, but not rely on a 
>> convention which seems to be fading out.
>> 
>> You can ensure the actual convention by setting the header manually (as 
>> stated in the is_ajax doc) - as you do with the CSRF token. Another 
>> convention could be better (i.e. "accepts json")
>> 
>> So far, is what the discussion went through to my understanding :)
>>>> 

>>>> I'm currently handling this with custom headers and the caller (the 
>>>> browser) tells the server what kind of outputs it can handle in different 
>>>> types of output.

>>>> The server then performs the branching at certain code points, 
>>>> specifically the ones mentioned above. DRF allows me to choose the 
>>>> appropriate renderer. Though I should mention here, that the data is 
>>>> already serialised at that point: sometimes this creates issues for 
>>>> renderers that might desire more information to do their work. Just 
>>>> mentioning that render stages need to be accounted for too. This may not 
>>>> be a problem for core Django as it doesn't have stages.

>>>> Again, sorry, but still hoping this helped in some way.

>>>> 


>>>> LP,
>>>>  Jure

>>>> 

>>>> On 19/11/2019 01:06, Matemática A3K wrote:
>>>>> 
>>>>> I agree with Adam that it should be deprecated with no replacement.
>>>>> 
>>>>> The content negotiation is something that should be in but not as a 
>>>>> replacement of it, as a general improvement.
>>>>> 
>>>>> I think there shouldn't be a replacement because "is_ajax" asks whether 
>>>>> it came from a ""regular"" browser instead of jQuery and with the content 
>>>>> negotiation you ask if the requester accepts a type - which can also lead 
>>>>> to errors because the client may also accept other types (no example 
>>>>> coming to my mind), and if so, it will lead to undesired behavior.
>>>>> 
>>>>> The right approach would be making AJAX requests request JSON output 
>>>>> explicitly, by using a dedicated endpoint or by appending something that 
>>>>> manifests their intention - like in 
>>>>> https://docs.djangoproject.com/en/2.2/topics/class-based-views/mixins/#more-than-just-html
>>>>>  is done with a get parameter. Not decide the response type by where it 
>>>>> came from as it is unreliable as stated before, it provides convenience 
>>>>> in some use cases but can lead to errors.
>>>>> 
>>>>> Seems better to me to refactor the view code so you can write a different 
>>>>> view for Ajax requests that returns a JSON without code duplication.
>>>>> 
>>>>> As a shortcut, something like "For simple AJAX endpoints wrap your view 
>>>>> with (something like) a "jsonview" decorator which will check the accept 
>>>>> header (with something like Claude's code), return the appropriate error 
>>>>> code if not, set the response type accordingly, and you should return a 
>>>>> dict of strings (you have to take care of the serialization, i.e with 
>>>>> https://docs.djangoproject.com/en/2.2/topics/serialization/#serialization-formats-json).
>>>>> 
>>>>> On Mon, Nov 18, 2019 at 3:28 PM Tom Forbes <t...@tomforb.es> wrote:
>>>>>> What I meant by that is it’s not an approach that scales well to lots of 
>>>>>> views. It might be better to have separate endpoints to return JSON (e.g 
>>>>>> adding a /json suffix), and in the past this has made services I’ve 
>>>>>> worked on a lot more maintainable and easy to understand. But it’s not 
>>>>>> as quick to do as `if request.is_ajax()` and requires a bit more upfront 
>>>>>> work. If you find you need to do this a lot then maybe something more 
>>>>>> structured like Django Rest Framework will be a better choice, which 
>>>>>> also handles content negotiation really well (it can produce XML, CSV, 
>>>>>> JSON, etc etc). 
>>>>>> 
>>>>>>> On 18 Nov 2019, at 15:18, Matthew Pava <matthew.p...@iss.com> wrote:
>>>>>>> 
>>>>>>> “In my opinion there are not many good reasons to have to change 
>>>>>>> behaviour if a request is made via XHR. I think the most common usage 
>>>>>>> is to have a single view that returns a JSON response or a HTML 
>>>>>>> response depending on if XHR is used 
>>>>>>> (https://github.com/search?l=Python&q=request.is_ajax&type=Code), which 
>>>>>>> isn’t great and isn’t reliable.”
>>>>>>> 
>>>>>>> I do this. What would the best way to handle this? Perhaps the proper 
>>>>>>> practice should be documented when it is deprecated?
>>>>>>> 
>>>>>>> *From:* django-developers@googlegroups.com 
>>>>>>> [mailto:django-developers@googlegroups.com] *On Behalf Of *Tom Forbes
>>>>>>> *Sent:* Saturday, November 16, 2019 10:16 AM
>>>>>>> *To:* django-developers@googlegroups.com
>>>>>>> *Subject:* Re: Deprecate HttpRequest.is_ajax
>>>>>>> 
>>>>>>> I would agree. Flask has done the same:
>>>>>>> 
>>>>>>> `DeprecationWarning: Request.is_xhr is deprecated. Given that the 
>>>>>>> X-Requested-With header is not a part of any spec, it is not reliable`
>>>>>>> 
>>>>>>> In my opinion there are not many good reasons to have to change 
>>>>>>> behaviour if a request is made via XHR. I think the most common usage 
>>>>>>> is to have a single view that returns a JSON response or a HTML 
>>>>>>> response depending on if XHR is used 
>>>>>>> (https://github.com/search?l=Python&q=request.is_ajax&type=Code), which 
>>>>>>> isn’t great and isn’t reliable.
>>>>>>> 
>>>>>>> 
>>>>>>> On 16 Nov 2019, at 16:08, Adam Johnson <m...@adamj.eu> wrote:
>>>>>>> 
>>>>>>> Django's HttpRequest.is_ajax method determines whether the request was 
>>>>>>> made with the JS API XMLHttpRequest 
>>>>>>> https://docs.djangoproject.com/en/2.2/ref/request-response/#django.http.HttpRequest.is_ajax
>>>>>>>  . It does so by checking the X-Requested-With header.
>>>>>>> 
>>>>>>> The new way of making "AJAX" requests from the browser is the 
>>>>>>> JavaScript fetch() API : 
>>>>>>> https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API .
>>>>>>> 
>>>>>>> I think the is_ajax() documentation is at least a little misleading in 
>>>>>>> pretending XMLHttpRequest is the only JS API. There also aren't any 
>>>>>>> special headers set by fetch() so it's not possible to detect its 
>>>>>>> requests.
>>>>>>> 
>>>>>>> I propose deprecating is_ajax() with no replacement.
>>>>>>> 
>>>>>>> Thoughts?
>>>>>>> 
>>>>>>> -- 
>>>>>>> Adam
>>>>>>> 
>>>>>>> -- 
>>>>>>>  You received this message because you are subscribed to the Google 
>>>>>>> Groups "Django developers (Contributions to Django itself)" group.
>>>>>>>  To unsubscribe from this group and stop receiving emails from it, send 
>>>>>>> an email to django-developers+unsubscr...@googlegroups.com.
>>>>>>>  To view this discussion on the web visit 
>>>>>>> https://groups.google.com/d/msgid/django-developers/CAMyDDM0i-p0ZxBj-fSheGs-2pMXH7K7Oka%3DCjy1YXx-emBu3mw%40mail.gmail.com
>>>>>>>  
>>>>>>> <https://groups.google.com/d/msgid/django-developers/CAMyDDM0i-p0ZxBj-fSheGs-2pMXH7K7Oka%3DCjy1YXx-emBu3mw%40mail.gmail.com?utm_medium=email&utm_source=footer>.
>>>>>>> 
>>>>>>> -- 
>>>>>>>  You received this message because you are subscribed to the Google 
>>>>>>> Groups "Django developers (Contributions to Django itself)" group.
>>>>>>>  To unsubscribe from this group and stop receiving emails from it, send 
>>>>>>> an email to django-developers+unsubscr...@googlegroups.com.
>>>>>>>  To view this discussion on the web visit 
>>>>>>> https://groups.google.com/d/msgid/django-developers/84DCD242-69A8-4B8D-9EB6-243312B5F77F%40tomforb.es
>>>>>>>  
>>>>>>> <https://groups.google.com/d/msgid/django-developers/84DCD242-69A8-4B8D-9EB6-243312B5F77F%40tomforb.es?utm_medium=email&utm_source=footer>.
>>>>>>> 
>>>>>>> -- 
>>>>>>> You received this message because you are subscribed to the Google 
>>>>>>> Groups "Django developers (Contributions to Django itself)" group.
>>>>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>>>>> an email to django-developers+unsubscr...@googlegroups.com.
>>>>>>> To view this discussion on the web visit 
>>>>>>> https://groups.google.com/d/msgid/django-developers/cb12b0005c5e4191be3a97d0d2c44cc5%40iss2.ISS.LOCAL
>>>>>>>  
>>>>>>> <https://groups.google.com/d/msgid/django-developers/cb12b0005c5e4191be3a97d0d2c44cc5%40iss2.ISS.LOCAL?utm_medium=email&utm_source=footer>.
>>>>>> 
>>>>>> --
>>>>>>  You received this message because you are subscribed to the Google 
>>>>>> Groups "Django developers (Contributions to Django itself)" group.
>>>>>>  To unsubscribe from this group and stop receiving emails from it, send 
>>>>>> an email to django-developers+unsubscr...@googlegroups.com.
>>>>>>  To view this discussion on the web visit 
>>>>>> https://groups.google.com/d/msgid/django-developers/DA72EC9C-AE24-4C04-854A-A6E19DD64132%40tomforb.es
>>>>>>  
>>>>>> <https://groups.google.com/d/msgid/django-developers/DA72EC9C-AE24-4C04-854A-A6E19DD64132%40tomforb.es?utm_medium=email&utm_source=footer>.
>>>>> --
>>>>>  You received this message because you are subscribed to the Google 
>>>>> Groups "Django developers (Contributions to Django itself)" group.
>>>>>  To unsubscribe from this group and stop receiving emails from it, send 
>>>>> an email to django-developers+unsubscr...@googlegroups.com.
>>>>>  To view this discussion on the web visit 
>>>>> https://groups.google.com/d/msgid/django-developers/CA%2BFDnh%2B5xr1fWteL6bh2NhF0yJV%3DPwyvhkiLYyPmGO23q0sZ9w%40mail.gmail.com
>>>>>  
>>>>> <https://groups.google.com/d/msgid/django-developers/CA%2BFDnh%2B5xr1fWteL6bh2NhF0yJV%3DPwyvhkiLYyPmGO23q0sZ9w%40mail.gmail.com?utm_medium=email&utm_source=footer>.
>>>> --
>>>>  You received this message because you are subscribed to the Google Groups 
>>>> "Django developers (Contributions to Django itself)" group.
>>>>  To unsubscribe from this group and stop receiving emails from it, send an 
>>>> email to django-developers+unsubscr...@googlegroups.com.
>>>>  To view this discussion on the web visit 
>>>> https://groups.google.com/d/msgid/django-developers/0174a0b6-3a32-5339-9ae9-31050d2d2aaf%40gmail.com
>>>>  
>>>> <https://groups.google.com/d/msgid/django-developers/0174a0b6-3a32-5339-9ae9-31050d2d2aaf%40gmail.com?utm_medium=email&utm_source=footer>.
>> --
>>  You received this message because you are subscribed to the Google Groups 
>> "Django developers (Contributions to Django itself)" group.
>>  To unsubscribe from this group and stop receiving emails from it, send an 
>> email to django-developers+unsubscr...@googlegroups.com.
>>  To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/django-developers/CA%2BFDnhKT0ST76G5T6qFz7NWuhnuwoQvqQ3RRHZcFWhyV1jO1sQ%40mail.gmail.com
>>  
>> <https://groups.google.com/d/msgid/django-developers/CA%2BFDnhKT0ST76G5T6qFz7NWuhnuwoQvqQ3RRHZcFWhyV1jO1sQ%40mail.gmail.com?utm_medium=email&utm_source=footer>.
> 

> --
>  You received this message because you are subscribed to the Google Groups 
> "Django developers (Contributions to Django itself)" group.
>  To unsubscribe from this group and stop receiving emails from it, send an 
> email to django-developers+unsubscr...@googlegroups.com.
>  To view this discussion on the web visit 
> https://groups.google.com/d/msgid/django-developers/260544c2-1dcd-c38f-c267-e4941d1f5088%40gmail.com
>  
> <https://groups.google.com/d/msgid/django-developers/260544c2-1dcd-c38f-c267-e4941d1f5088%40gmail.com?utm_medium=email&utm_source=footer>.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/827feb18-49c0-44cd-81c6-d2fd6e83c3da%40www.fastmail.com.

Reply via email to