Opened 18 years ago
Last modified 11 days ago
#8264 new New feature
Replace get_absolute_url with more sane alternative
| Reported by: | simon | Owned by: | simon |
|---|---|---|---|
| Component: | Core (URLs) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | semente@…, jdunck@…, dd+djangoproject@…, ognajd@…, Frederich Pedersen, Carlton Gibson | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Change History (14)
comment:1 by , 18 years ago
| Triage Stage: | Unreviewed → Design decision needed |
|---|
comment:2 by , 18 years ago
comment:3 by , 18 years ago
Under the two cases you mention for using a URL, you say:
- The full URL, including protocol and domain.
- The path component of the URL. This is needed for internal links - it's a waste of bytes to jam the full URL in a regular link when a path could be used instead.
The second case is for internal links, yes, but in some cases internal links might have to be full URLs. I don't have practical experience with multi-site set-ups in Django, but I think we need to allow for them.
If you accept that the requirements can be stated as
- A method for getting an absolute URL
- A method for getting an internal link (aka relative URL) that is correct for any URL within the current site but preferably as short as possible
- Resources may reside on different domains, or be linked to with a different URL scheme (eg. https://, but also webcal://, feed://)
then the corollaries are:
- (from 2, 3) the internal link may be an absolute URL
- (from 3) you have to check the scheme and domain match when converting an absolute URL to a URL path
- (from a) you have to use urlparse.urljoin to compute the absolute URL from the internal link
- (from a) get_url_path would be a misnomer as we can't constrain it to a path
There are other cases where we might want to convert a relative URL to an absolute URL too, incidentally, so that should not be exclusively tied up with models. (As an aside, one such case is in HttpResponseRedirect: according to RFC2616 §14.30 the Location: header is defined as requiring an absolute URL, though that's never been enforced by UAs).
I often wish Python had a url type equivalent to Java's java.net.URL. When I programmed in Java I found it very neatly reinforced the semantics that a link cannot be used as a URL and cannot be concatenated onto a URL. It's like Python's unicode type: it makes sure you do the right thing with character sets. Our current URL handling would be akin to trying to use UTF-8-encoded bytestrings throughout. So, if performance isn't a problem, a utility class like that would be great.
One other point: I don't want to be forced to specify a base URL for simple, self-contained sites, because that makes it annoying to move sites between domains. It would be handy if I could set the site's base URL to None and then work simply with relative URLs, but I would see an exception if ever I tried to get an absolute URL.
comment:4 by , 17 years ago
| Cc: | added |
|---|
comment:6 by , 17 years ago
| Cc: | added |
|---|
comment:7 by , 16 years ago
| Cc: | added |
|---|
comment:8 by , 15 years ago
| Severity: | → Normal |
|---|---|
| Type: | → New feature |
comment:9 by , 14 years ago
| Easy pickings: | unset |
|---|---|
| Triage Stage: | Design decision needed → Accepted |
| UI/UX: | unset |
I'm accepting this ticket because get_absolute_url could certainly be improved. If someone wants to work on this, please send a proposal to django-developers.
comment:10 by , 13 years ago
| Cc: | added |
|---|
comment:11 by , 13 years ago
| Component: | Core (Other) → Core (URLs) |
|---|
comment:12 by , 10 months ago
Is this still a feature that is considered open?
I see the problematic cases for the get_absolute_url, and why it should be changed to get_url and get_url_path.
I suggest implementing them both, and writing a deprecation warning on the get_absolute_url function.
comment:13 by , 10 months ago
| Cc: | added |
|---|
comment:14 by , 11 days ago
| Cc: | added |
|---|
I hate to take an 18 year old ticket and say let's WONTFIX it, but I think we should WONTFIX this.
There are two bits in the proposal. One is the name, get_absolute_url(). I think changing it at this point is not worth the price of admission. OK, it's not strictly a full URL because it's missing scheme and domain, but it serves for one for internal purposes, and it is absolute for the site (starting with /), rather than relative. (Would we say it's a "path-absolute relative URL"? — That's a mouthful.) Anyhow I think we should just live with it after all these years.
The second part is that missing scheme and domain.
The standard way to handle this in the request-response cycle is with HttpRequest.build_absolute_uri, like so:
def my_view(request):
bookmark = Bookmarks.objects.get(id=1)
path = bookmark.get_absolute_url() # /bookmarks/1/
full_url = request.build_absolute_uri(path)
...
Outside the request-response cycle, Django cannot know the current scheme/domain unless we provide it.
We might use the sites framework:
from django.contrib.sites.models import Site
site = Site.objects.get_current()
full_url = f"https://{site.domain}/bookmarks/1/"
Depending on the sites framework being installed and settings.SITE_ID being configured.
I think more and more people are not using the sites framework. (Us leaning into it now would likely be us going against the current.)
In reality I think most folks are declaring a setting like:
# settings.py SITE_URL = "https://example.com"
And then building a full URLs like:
from django.conf import settings
path = "/bookmarks/1/"
full_url = f"{settings.SITE_URL}{path}"
Such a setting is easily configured per-environment. It's pretty simple.
Users tend to know, in context, whether they need a full URL with scheme and domain or whether the path-absolute relative URL is sufficient. That this has sat here so long unfixed strongly implies to me that anything more complex, to automatically handle that difference, really isn't needed.
Great summary Simon!
+1 on not being forced to use the sites framework. There should be a domain setting for the easy (99% of the time!) case of a single site. The sites framework should also be an opt-in thing rather than opt-out once this works :)