I would agree that `response.headers` *is* by far clearer especially to those not familiar with Django or coming from other frameworks. As Tom says, we only visually know that setting a key on a response object is for headers because of the key name itself, e.g. "Content-Type". I also think that having `response.headers` brings a symmetry with `request.headers` that makes it easier for developers to remember how this all works. I am all for being concise, but I don't hold to the argument that the something isn't to be preferred just because it is more verbose and you "know" Django. The addition of ".headers" is hardly excessively verbose.
I think there has to be a balance struck between making things more accessible for developers that are new to Django and those that are long-time developers who need to maintain their existing code. There is always going to be some contention between satisfying both camps. I understand that there are the concerns raised referencing the API stability policy that there should be "one way to do it", but it does come with various provisos, e.g. "(eventually)" and "very high priority" (which *also* does not equal "the only priority" - it isn't absolute). In addition, I can highlight places with multiple ways of doing things, e.g. `Field.choices` with the ability to use enumeration classes or not, `Meta.indexes` or the not-yet-deprecated and only lightly discouraged `index_together` and `unique_together`, etc. While I think that "one way to do it" is an admirable goal, I don't think that we need to be quite so militant at adhering to that principle. Maybe this has originated from the Zen of Python, but even that states "There should be one-- and preferably only one --obvious way to do it." I see that as meaning "it is preferable to have one obvious way to do it" but not discounting multiple ways if that cannot be achieved or is undesirable. If we're going to be driven forcibly by these principles it comes down to a tussle between Python's "obvious" - undisputedly `response.headers` - and Django's "superior" - well, arguably, neither, unless we choose clarity (`response.headers`) or Python's data model as what makes something "superior". In that regard we have a contradiction if we were to choose Python's data model as the "superior" solution as Python - or at least the "Zen of Python" - commends what is "obvious". I honestly thought the approach Carlton mentioned in https://github.com/django/django/pull/13186#discussion_r454956921 struck the correct balance and we could even, if desired, highlight in the release notes for the new `response.headers` that the old approach has not gone away such that developers do not need to rush to update their code. As highlighted by the examples above, it feels like there is precedent for that. Also if the data model approach is plumbed in to use `.headers` as in the proposed implementation, I don't see this as being a burden to maintain. Please let's be pragmatic about this stuff and not be driven to adhering to "one way to do it" as an extremist ideology rather than a laudable preference. On Thursday, 16 July 2020 at 14:58:39 UTC+1 carlton...@gmail.com wrote: > The concern is the backwards incompatibility. > > I do see the reasons for the new approach. I accept that it’s easier to > grok if you don’t know Django already — “principal of least astonishment” I > think you opened with. > > I just can’t balance those gains against forcing a change on the entire > community. It just doesn’t balance. (And being negative, as soon as you do > know Django the new proposal is more verbose, so not to be preferred.) > > I had thought that it would be additive but the API stability policy is > quite clear on the “one way of doing things”. > > Thus, as much as I do like the idea, I don’t think we can do this. > > On Thu, 16 Jul 2020 at 15:39, Tom Carrick <t...@carrick.eu> wrote: > >> Hmm. I do think that Python's data model is a Good Thing. Where we might >> disagree is that I don't think this is an appropriate use of it.I'll try to >> illustrate with an example. Consider this code: >> >> response = HttpResponse() >> response['foo'] = 'bar' >> >> Now, if I try to look at this code without context, putting my Django >> knowledge to the back of my head, intuitively, this doesn't look like I'm >> setting a header. To me it actually looks more like my response is JSON >> (increasingly common these days) and I'm setting the 'foo' key on it to >> 'bar'. Now, is this likely to happen and cause confusion? Probably not, >> since we tend to spell out our headers such as Content-Type rather than >> content-type, and custom headers tend to be prefixed with 'X-'. But I do >> think there is potential confusion, especially to beginners or perhaps >> people who know a little frontend development and expect any request to >> return JSON, and perhaps haven't had to interact with headers as their >> libraries take care of them. >> >> However, the reason I bring this up isn't so much this potential for >> confusion, but more this: When I think about a HTTP request, 99% of the >> time, I'm thinking about the response content. Only rarely am I ever >> thinking about the headers. Usually interacting with headers is abstracted >> away in middleware or some other place. So why should setting a key on the >> response set something on the headers? It seems unintuitive to me. >> >> Personally, I think that is enough to meet the bar of "clearly superior", >> but I'm aware I don't have the only opinion. >> >> Another thing this is useful for is that it's actually possible (in a >> documented, public way) to see all the response headers. Of course the >> server could modify this, but it's still useful when debugging to see what >> Django is setting, and right now the only way I can think to do this is to >> look at `response._headers`, and I'd rather not be using undocumented APIs. >> >> If the concern is primarily about the diff size, it's quite trivial (if >> we decide to keep the existing API as-is forever and just add the new >> interface on top) to drop the commits changing those and just add tests for >> the new interface. It is then purely additive in the sense that the old API >> works just the same and isn't going anywhere. >> >> Regardless, I'm happy to go wherever the consensus is. >> >> Cheers, >> Tom >> >> On Thu, 16 Jul 2020 at 14:25, Carlton Gibson <carlton...@gmail.com> >> wrote: >> >>> Some concerns were expressed privately to me privately in the week about >>> the change here. >>> >>> I was thinking about it, and re-reading the API Stability document >>> https://docs.djangoproject.com/en/3.0/misc/api-stability/. >>> >>> The more I look at it, the less convinced I am that the proposal here >>> meets the "when we discover clearly superior ways to do things" criterion. >>> >>> Yes, I think, if we were starting from scratch, we'd probably put >>> headers in a mapping attached to the response, so the request.headers here >>> proposed. >>> >>> I think that probably is (definitely is?) easier for a beginner to grok. >>> But looking at the diff — where all the changes are just from: >>> >>> response['Content-Disposition'] = 'attachment; >>> filename="somefilename.csv"' >>> >>> to: >>> >>> response.headers['Content-Disposition'] = 'attachment; >>> filename="somefilename.csv"' >>> >>> I can't see that this is clearly superior, to just having the response >>> itself act as said mapping. >>> >>> I learnt Python through Django. This exact case was my first expose to >>> the Python Data Model. Oh, objects can act like dictionaries. Cool. >>> Didn't think about it again for half a dozen years. But it wasn't so >>> difficult. >>> >>> The s/response/response.headers/g (from one POV) just looks like more >>> code, despite the initial "Yeah, sounds good." >>> >>> Then I come to the “one way to do it. OK, I get that. >>> >>> But I look at the prospect of forcing every project that ever set an >>> HTTP header to have to update. I look again at the "clearly superior", and >>> I have to conclude that the change isn't justfied. >>> That's too bigger cost for too small a gain. >>> >>> So, despite earlier enthusiasm, I have to lean towards a -1 here. >>> Like request.headers, I initially took this as a purely additive gain, >>> but that's not compatible with the goals expressed in the API Stability >>> policy. >>> So I think we should pass. >>> Not easy. >>> >>> >>> >>> Django is in a good place: we're at the point where it's easy to update, >>> and that's the expectation. The API Stability policy (and it's >>> enforcement) is largely responsible for that. >>> It's important not to forget. We on this list see a *little* change as >>> a nothing. Across the massive install base it's anything but. >>> David's mention of url() is a good one — for each complaint we see >>> here, and we saw a few, there will be a thousand we don't — people just do >>> the work, but that's not something we should impose lightly. >>> >>> >>> >>> The are a couple of good additions to take: >>> >>> * Setting headers via an init kwarg would be cool. >>> * Maybe the CaseInsenstiveMapping is worth using too. (Not so sure what >>> the benefits are here.) >>> >>> >>> Kind Regards, >>> >>> Carlton >>> >>> -- >>> 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-develop...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/django-developers/98cba197-d079-4f7d-84e5-18308509a99ao%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/django-developers/98cba197-d079-4f7d-84e5-18308509a99ao%40googlegroups.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-develop...@googlegroups.com. >> > To view this discussion on the web visit >> https://groups.google.com/d/msgid/django-developers/CAHoz%3DMaBbPUw7dcTeH2M-PmLgwUb4oaLsdQi%2Bz8hCVMpCgtbYQ%40mail.gmail.com >> >> <https://groups.google.com/d/msgid/django-developers/CAHoz%3DMaBbPUw7dcTeH2M-PmLgwUb4oaLsdQi%2Bz8hCVMpCgtbYQ%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/2ff47202-94a9-4254-9cfa-c0fe102ad47an%40googlegroups.com.