Easy, get_url returns the entire url while get_url_path returns only
the "path" portion of a url. One could imagine feature creep resulting
in 'get_url_protocol', 'get_url_domain' etc. I wouldn't actually
recommend those be added, but by thinking about it that way, it trains
my brain how to parse the proposed function names.
> If it is going to be done I propose adding another function, and thus
> have two possible functions on the model:
> get_relative_url
> get_absolute_url
That seems like the obvious solution except that get_absolute_url
currently returns a url path. Oops! With the change, everyone's
existing code will suddenly break. The only way to fix it is to
depreciate get_absolute_url and create new names for the replacements.
Oh, and this reference to relative urls. Relative to what? The site
root? The app root? The currently viewed page? "get_relative_url" is
probably not what you actually want. "get_url_path" is.
Of course, this all really a bikeshed issue. Generally, 'he who builds
the shed gets to paint it.'
--
----
\X/ /-\ `/ |_ /-\ |\|
Waylan Limberg
get_relative_url is rather misleading. The proper meaning of "relative"
is a url relative to current url: "./some/hierarchy", "some/", ".". Put
simply it's a path that doesn't start with a slash. The problem is that
on the model layer no notion of a current url exists so this makes
get_relative_url even more weird.
Out of curiosity, has anyone looked at the possibility of modeling this type of
URL-handling in a similar way that we do for db.models.FieldField with respect
to the name, path and url properties?
In essence we could add only one new method to the API that returns a
URL-object that provides access to the data:
url = obj.get_url()
print url.absolute
print url.relative
print url.protocol
print url.domain
...
If reverse() and {% url %} methods are updated to use such an URL-object
backwards-compatibility can probably be persevered through a proper __str__
method on the URL-object.
IMO it feels more right to have single method that needs to know about this
stuff instead of having separate methods for all this data which in essence
is all part of the same URL complete.
I have not double checked if all the issues mentioned in
http://code.djangoproject.com/wiki/ReplacingGetAbsoluteUrl can be solved with
such a scheme, but if there is interest in such a solution I'm willing to look
into this and trying out the idea either as an external project or as a patch
proposal.
--
Thomas Kongevold Adamcik
I like this idea a lot. It solves most of the problems I have with
get_absolute_url:
* I dislike the name -- far too verbose. Why not just `obj.url()`?
* I wish there was a better mechanism for getting host-relative URLs,
schema-relative URLs, etc. The `<a href="//...">` trick is annoyingly
obscure.
* The mismatch between `@models.permalink` and `get_absolute_url` is
very counter-intuitive.
* The fact that the returned URL is a string often means I end up
doing something like `obj.get_absolute_url().split('/')`. Objects are
better.
> If reverse() and {% url %} methods are updated to use such an URL-object
> backwards-compatibility can probably be persevered through a proper __str__
> method on the URL-object.
Python's already got such an object; it's `urlparse.ParseResult` (the
object returned by `urlparse.urlparse`. We'd need a tiny subclass with
a backwards-compatible `__str__`, but that's about it.
> I have not double checked if all the issues mentioned in
> http://code.djangoproject.com/wiki/ReplacingGetAbsoluteUrl can be solved with
> such a scheme, but if there is interest in such a solution I'm willing to look
> into this and trying out the idea either as an external project or as a patch
> proposal.
I'm +1 on this proposal; please ping me if you work up a patch and
I'll take a look.
Jacob
I kind of disagree with the last sentence here. An object in place of a
well-known native type (here, str) adds another abstraction to grok for
a newbie. It's like when you read WinAPI docs and see a function
accepting structs of structs of structs and changing some memory buffer
but you only have a string and want to get an int. I mean it boils down
to it anyway, just not obvious from the start...
In the rare cases when I do need to split a URL into parts I just use
urlsplit:
schema, domain, path, query, fragment = urlsplit(obj.url())
I believe it's a well-known pattern for an experienced pythoneer.
So I'm against of introducing a new Django-specific way of doing
urlsplit that has chances to confuse both newbies and gurus for
different reasons.
Oh... And for template authors we could just make 5 filters returning
those parts:
{{ obj.url|domain }}
That's not in any way intitutive for a new user in the way that
`obj.url().schema` is.
> Oh... And for template authors we could just make 5 filters returning
> those parts:
>
> {{ obj.url|domain }}
So we need *five* new built-in filters instead of `{{ obj.url.domain
}}`? Why? What if I want to access the username or password? Do we
"just" add two more filters?
Ugh.
Jacob
After thinking of it a bit more I agree about new users. My main concern
though was about not using an established pattern.
>> Oh... And for template authors we could just make 5 filters returning
>> those parts:
>>
>> {{ obj.url|domain }}
>
> So we need *five* new built-in filters instead of `{{ obj.url.domain
> }}`? Why? What if I want to access the username or password? Do we
> "just" add two more filters?
Looks like I shouldn't have posted that follow-up :-). It was only an
afterthought. Actually I think we don't need even those 5 filters
because there are no clear use cases for all of them. If we need schema-
and host-relative URLs then we need exactly two filters:
{{ obj.url|schema-relative }} (or better "protocol-relative")
{{ obj.url|host-relative }}
I think it's better than, say:
//{{ obj.url.domain }}{{ obj.url.path }}?{{ obj.url.query }}
The filter is also useful for {% url %}-generated URLs using {% filter
%}. Which I believe is not doable with url-as-an-object thing.
Thoughts?
Beware! Using the word "magic" too loosely may infuriate certain core
devs and they will start hunting you all over the globe, or worse,
strike you out of a Christmas present list for this year!
Honestly, having an object that looks like unicode but at the same time
able to be /-ed or |-ed with another unicode in my dictionary *is*
called "magic".
I still fail to see why this clever micro-DSL is needed when all this
can be done with normal Python and be more clear.
> All the things you are concerned with can be created using urls+views
> so you shouldn't even need to worry about get_absolute_url.
I don't worry, unless anyone will make (3rd party) module with
get_absolute_url in one way and someone else to make another module
with another usage of get_absolute_url.
Unless some 3rd-party module creator will expect any specific behavior
from other modules.
Just get_absolute_url doesn't play well with django-plugin-federation.
It takes also 3 pages in docs, that promote this bad method usage
among the django beginners.
Say, imagine django.contrib.comments will use get_absolute_url to
promote current site and blog post, which has current comment, but not
taking care that user needs content in his chosen language, not any
fixed one, and that language is a part of an url.
I.e. say you are rendering "last comments" block.
This link shouldn't be neither rendered with Comment.get_absolute_url
nor Post.get_absolute_url nor Site.get_absolute_url cause of i18n and
multisite issues (let's imagine user is looking at
german-language-flavoured version of the page):
http://tag.blogsite.com/intl/de/2009/08/get-absolute-url-is-bad-practice/#comment241
(though see http://docs.djangoproject.com/en/dev/ref/settings/#absolute-url-overrides
for this bad practice documented)
P.S. yes, if comments were paginated, situation was even more dramatic!
> I think you guys took it overboard with all the URL-class stuff. Like
> the case for Yuri shows, once you start creating URL class you will
> have to make all sorts of exceptions and additions for stuff that
> people need.
--
Ya know, this conversation is going in circles, and arguing over
increasingly trivial details. As always, our policy is that the person
who builds the bikeshed gets to decide which color it is, so I'd
suggest we all stop writing email and start writing Python now. Work
up a patch, and then let's discuss from there.
Jacob
how about my kind of patch -- deprecation and removal of the feature? :)
--
I am with you.
I am new to Django and am deep in the middle of my first major project
using Django. When I encountered get_absolute_url, my reaction was,
"What were they thinking!". Why does the model have any knowledge about
it's presentation? What if that very same model object is used for two
completely separate purposes in two different applications?
Then I realized that this method is mainly used by the Admin application
as a convenience method for creating that nice little "View on site"
link. Now that finally made some sense in terms of what they were
thinking. get_absolute_url is a nice little parlor trick for the Admin
application, that then got subverted for inappropriate uses.
In our main application, it has been mandated not to use
get_absolute_url ever. We have in place a mechanism to allow the view
layers to generate a url for a given object.
+1 for deprecating.
Pat McNerthney
ClearPoint Metrics, Inc.
Then you'd want something more complicated to handle that. But,
really, "where does this object live" is a question the object itself
ought to be able to answer. One can argue endlessly about the name,
API, return values, etc., etc., but the fact remains that there's a
valid problem whose valid solution is "ask the object". And so, like
Jacob, I'd really like to start seeing actual *code* to try to improve
the way that gets done, rather than the endless bikeshedding this
thread seems to be headed for.
--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."
>
> On Sat, Sep 12, 2009 at 8:42 AM, Thomas K. Adamcik
> <tada...@gmail.com> wrote:
>> In essence we could add only one new method to the API that returns a
>> URL-object that provides access to the data:
>
> I like this idea a lot. It solves most of the problems I have with
> get_absolute_url:
>
> * I dislike the name -- far too verbose. Why not just `obj.url()`?
Note this option will break a lot of models with an existing url field
(that's just a warning, as a devil's advocate, I'm not fond of the
current name too...).
Regards,
David
Just like urlresolvers right now has a "reverse" method that can take in
a view name, a similar method should be exposed that takes in a object.
Something like:
urlresolvers.reverse_for_object(object)
In addition, most, if not all, of the current optional reverse arguments
probably should be supported.
Obviously, there are a few details to work out with regards to how to
nicely configure the url resolvers sub-system to support this, but I
believe that is where the bike shed belongs.
Pat McNerthney
ClearPoint Metrics, Inc.
It is having models know about what URLs that is a circular dependency
that is both unneeded and problematic. Models should stand alone and be
usable by any number of applications within the same project. Having
the models be responsible for knowing how they are being presented does
not allow for unanticipated uses of those models.
I'll leave it at that for now if you still think it is merely the
repainting of the bike shed.
Except I can't help thinking this is an awfully arbitrary distinction
to draw. In effect you're saying that nearly every question about an
object should be answerable by interrogating it directly, *except* for
"what's a URL I can use for you?"
That's such a common question that I really think it needs to have an
answer which doesn't involve hunting over multiple layers of the
stack.
> It is having models know about what URLs that is a circular dependency
> that is both unneeded and problematic. Models should stand alone and be
> usable by any number of applications within the same project. Having
> the models be responsible for knowing how they are being presented does
> not allow for unanticipated uses of those models.
Keep in mind that the recommended practice is for get_absolute_url()
to work with reverse() and friends, rather than hard-code information
directly. Having it supply a pattern name and some arguments offers
quite a lot of flexibility with no need to monkeypatch anything, and
is why I've consistently harped on this technique in various talks on
effective reuse of Django applications.
May be I can explain this distinction with an example.
We once had two different web sites about "events". They both had a
"core" set of models but each one had their own set of views & urls. So
for a core Event model a question "what's your URL" just didn't make
sense. It had two different URLs depending on the project it was
imported in.
That said, I do see a value in having a default URL (and a default
__unicode__ for that matter) simply because it's useful in many (or even
majority?) of real-world cases.
So Yuri, Patrick, this method is optional so there's not technical need
to deprecate it. This discussion really is about how it should be done,
not if.
On Thu, Sep 10, 2009 at 11:58:00AM -0400, Waylan Limberg wrote:
>
> Easy, get_url returns the entire url while get_url_path returns only
> the "path" portion of a url. One could imagine feature creep resulting
> in 'get_url_protocol', 'get_url_domain' etc. I wouldn't actually
> recommend those be added, but by thinking about it that way, it trains
> my brain how to parse the proposed function names.Out of curiosity, has anyone looked at the possibility of modeling this type of
URL-handling in a similar way that we do for db.models.FieldField with respect
to the name, path and url properties?
In essence we could add only one new method to the API that returns a
URL-object that provides access to the data:
url = obj.get_url()
print url.absolute
print url.relative
print url.protocol
print url.domain
...If reverse() and {% url %} methods are updated to use such an URL-object
backwards-compatibility can probably be persevered through a proper __str__
method on the URL-object.IMO it feels more right to have single method that needs to know about this
stuff instead of having separate methods for all this data which in essence
is all part of the same URL complete.I have not double checked if all the issues mentioned in
http://code.djangoproject.com/wiki/ReplacingGetAbsoluteUrl can be solved with
such a scheme, but if there is interest in such a solution I'm willing to look
into this and trying out the idea either as an external project or as a patch
proposal.--
Thomas Kongevold Adamcik
Would anyone know if there is still any momentum behind this? I like Adamcik's approach.