path to object + function + args
class Articles(...):
def edit(id=None):
.......
I'm unable to make a choice between 1 and 2, definitely not the third
option.
>
> the advantage to the first one is that it makes view look like this:
> http://yoursite/articles/10
for the second it will look like this:
http://yoursite/articles/show/10
right?
For what is worth RoR scaffolding uses the second one (just checked it
from the screencast ;-)).
Ciao
Michele
I am still new to cherrypy.
I was under the impression that you built an object tree, and it
automatically mapped
the URI to the object tree, passing in args to the function
http://yoursite/articles/edit?id=10
wouldn't this map to
class Article(.....):
def edit(self, id=None):
""" function to edit article""""
with cherry py dispatching the uri to
article.edit(id="10")
------------------------------------------------
would you go to partial matches for the other URL (like the CherryPy
docs below),
or is there a trick that directly mapps to a function?
Just trying to learn the options,
Thanks
Mike
--------- From CherryPy Tutorial ---------------------
Partial matches and the default method
Partial matches can happen when a URL contains components that do not
map to the cpg.root object tree. This can happen for a number of
reasons. For example, it may be an error; the user just typed the wrong
URL. But it also can mean that the URL contains extra arguments.
When a partial match happens, CherryPy calls a default method. The
default method is similar to the index method; however, it is only
called as a last resort method, and it's recommended for two
applications:
* Error handling, to be called when the user types the wrong URL;
* Support for positional arguments.
Support for positional arguments when handling partial URL matches is
one of the new features provided by CherryPy. For example, assume that
you have a blog-like application written in CherryPy that takes the
year, month and day as part of the URL:
http://localhost/blog/2005/01/17
This URL can be handled by the following code:
class Blog:
def default(self, year, month, day):
...
default.exposed = True
...
cpg.root.blog = Blog()
So the URL above will be mapped as a call to:
cpg.root.blog.default('2005', '1', '17')
In this case, there is a partial match up to the blog component. The
rest of the URL can't be found in the published object tree. In this
case, the default() method will be called, and the positional
parameters will receive the remaining path components as arguments. The
values are passed as strings; in the above mentioned example, the
arguments would still need to be converted back into numbers, but the
idea is correctly presented.
Ok, the first seems the best.
If I read the second it seems like I'm going to edit (or show) 10
articles not the article number 10.
So +1 for the first.
Ciao
Michele
http://en.wikipedia.org/wiki/Representational_State_Transfer
Thus I give my 2 cents ;-).
I prefer to use 1).
But you should look at Quixote ExtDirectory:
http://quixote.ca/qx/ExtDirectory
This give full flexibility (like proposed by Jorge).
Does this is implementable into CP2.1 ????
AFAIK, such flexible URL would available in CP2.2.
William
With CherryPy 2.1 you can also use a PositionalParametersAware class.
I think that probably 0.9 will use positional parameters by default
since they will be the default in CherryPy 2.2 if I'm right, but we
should really ask Kevin about this.
See also ticket 73: http://trac.turbogears.org/turbogears/ticket/73
Ciao
Michele
I think Routes provides the maximum flexibility one could ever need and
it seems that it will be easily integrable with CherryPy 2.2:
http://www.groovie.org/articles/2005/11/21/routes-1-0-released
Ciao
Michele
>> 2) http://yoursite/articles/edit/10
class Article(...):
def edit(self, articleId=None):
if(articleId == None):
# redirect to select article to edit page
......
def delete(self, articleId=None):
......
def create(self):
......
> http://www.groovie.org/articles/2005/11/21/routes-1-0-released
I like this url (haven't actually *clicked* on it yet) - the format
site/articles/year/month/day/title_of_article is nice and human
readable.
So I guess my vote is for number 1, but I'd probably replace the "id"
number with either an article title (provided it will be unique) or a
date and article title, or even a category and a title (sticking an
'edit' at the end of the url for editing, etc). Since I think the point
Kevin is trying to make is that we have complete flexability with the
URL, I'd prefer to go with "average-joe" readability over
programming-grammer logic.
If I had my way, we'd have the entire article in the URL (no, not
really; that's a joke).
- Jason
(notice the above url :D)
Ciao
Michele
For an ecommerce project i'm currently using the following URL scheme:
catagoryname/subcatagoryname
catagoryname/subcatagoryname/edit
catagoryname/subcatagoryname/.../productname
catagoryname/subcatagoryname/.../productname/edit
Editing the product and catagory 'pages' directly feels verry natural.
1) http://yoursite/articles/10/edit
2) http://yoursite/articles/edit/10
3) http://yoursite/articles/edit?id=10
1) http://yoursite/articles/10/edit
2) http://yoursite/articles/10/delete
3) http://yoursite/articles/10/create
The main reason that I am liking 2, then 3 is that I can see how
cherrypy easily maps the urls to functions edit, delete and create.
I am having a mind blank here, how would you code #1 without using
if clauses and one function?
Sorry for my confusion,
Mike
I'm certain some will suggest this is unpythonic
On 12/6/05, Jeff Watkins <je...@newburyportion.com> wrote:I'm certain some will suggest this is unpythonic
Why?
--
Jeff Watkins
Getting an education was a bit like a communicable sexual disease. It made you unsuitable for a lot of jobs and then you had the urge to pass it on.
-- (Terry Pratchett, Hogfather)
For me the natural one is the 3 one. Could be that it is because i was programming
over 8 years php, but for the first 2 possibillities how would you build a form like this:
<form action="http://yoursite/articles/edit" method="GET">
<input type="text" name="id" value="">
<input type="submit" name="edit">
</form>
Also for the first two it is not really clear how the application is styled. As example:
articles/10/edit could be:
object.object.object.index or
objext.object.method or
object.method.parameter or
method.parameter.parameter
Kim
2005/12/5, Kevin Dangoor <dan...@gmail.com>:
So, in a generic CRUD feature, what would you want your URLs to look like:
1) http://yoursite/articles/10/edit
x = Article(id="10")
x.edit("...")
But my chief hope is that TurboGears' BDFL makes some decision before
we get into an argument about what pythonic means. :)
As far as "/articles/10" not being meaningful -- I don't think that's a
fault in the structure of the URI of the resource, it's a problem in
the representation of the resource. "/articles/My_new_car" or
"/articles/10/10/2005/The_next_trivial_thing" would fit URI #1, and
they are meaningful.
I like to use query strings for "flavors" -- user options that change
the representation, like "?_detail=_verbose&_dataformat=_json." I.e.,
the query string is for user preferences about the representation that
they receive of the resource with URI
"http://yoursite/articles/My_new_car."
I think that's RESTful, but that's just me. How about asking at the
REST Yahoo group? Kind of a second opinion? Some of the heavyweights
that don't hang around here, hang around there.
Ron
I've heard about that group, and I'm afraid we just don't have that
kind of time to wait for a conclusive answer :)
Enough of this thread seems to be in favor of choice #1, so that's
what I'm going to do for starters.
Django's slugs are basically implemented on the client side via the
admin screen (from what I can tell), they aren't particularly tied to
the model. They are mostly like alternateID=true. So there's nothing
special SQLObject has to do to support that. But CatWalk would have to
pay attention to populate_from.
For slugs to be generated automatically when an instance was created
requires the events (or hardcoding slug functionality, but that'd be silly).
As you say, Ian, can just use alternateId = True from the model perspective.
What makes a slug field interesting is the validation/auto text processing.
Hmm... Now that I am thinking of it, a slug could be viewed simply as a
regexp text processing of another given field. As such, a generic
function could slugify any given text. (Perhaps chopping it off after a
certain upper limit.)
That function is something that TG could provide and it would be generic
enough to be applied to any StringCol field in any model.
e.g.:
my_model_instance.my_field =
turbogears.util.slugify(some_other_text_field_data)
... or something like that, anyway.
A validator could even be provided that would validate a given field to
ensure that it is slugifiable, though ideally, any text should be
slugifiable.
Anyway, I'm just typing as I'm thinking. I don't have the time to
implement this idea, so I am throwing it out there for anyone to run with.
Krys
> What makes a slug field interesting is the validation/auto text processing.
I didn't get why you want to validate this.
> Hmm... Now that I am thinking of it, a slug could be viewed simply as a
> regexp text processing of another given field. As such, a generic
> function could slugify any given text. (Perhaps chopping it off after a
> certain upper limit.)
How about an MD5 or SHA1 or some other hash from any one or two fields (one
can be a date, for example)?
> That function is something that TG could provide and it would be generic
> enough to be applied to any StringCol field in any model.
Just StringCols? Why not UnicodeCol, IntCol, etc.?
> Anyway, I'm just typing as I'm thinking. I don't have the time to
> implement this idea, so I am throwing it out there for anyone to run with.
myinstance.mySlug = md5.md5(myinstance.myCol).hexdigest() ?
>>> import md5
>>> slug = md5.md5('this is a test').hexdigest()
>>> slug
'54b0c58c7ce9f2a8b551351102ee0938'
>>> slug = md5.md5('1').hexdigest()
>>> slug
'c4ca4238a0b923820dcc509a6f75849b'
>>> slug = md5.md5('áéíóúçã').hexdigest()
>>> slug
'a88a39ed784a18cccc9d87fd0e7f48d9'
>>> import datetime
>>> slug = md5.md5(str(datetime.datetime.now())).hexdigest()
>>> slug
'684a0195179447705f07fc205f32f74c'
>>>
Be seeing you,
--
Jorge Godoy <jgo...@gmail.com>
IMHO, what you're suggesting isn't a slug. A slug is normally human
readable afaik... generating MD5 hashes for content wouldn't make for
easy URL's. :)
Lee
> IMHO, what you're suggesting isn't a slug. A slug is normally human
> readable afaik... generating MD5 hashes for content wouldn't make for
> easy URL's. :)
Ah! Then it is a column with a unique value containing only ascii
alphanumerical characters (sans some special chars). I see now.
I believe this is so application dependent that I don't see where I would use
that in one of the last 5 apps that I wrote with TG. But then, if I had that,
maybe I thought different. :-)
--
Jorge Godoy <jgo...@gmail.com>
Here are a few examples:
A blog: title="My Article", slug="my_article"
http://yoursite/blog/my_article
An address book: name="Kevin Dangoor", slug="kevin_dangoor"
http://yoursite/addresses/kevin_dangoor
The idea is just a human-readable ID that is generally automatically
created as much as possible.
> On 12/6/05, paron <rphi...@engineer.co.summit.oh.us> wrote:
>> I think that's RESTful, but that's just me. How about asking at the
>> REST Yahoo group? Kind of a second opinion? Some of the heavyweights
>> that don't hang around here, hang around there.
>
> I've heard about that group, and I'm afraid we just don't have that
> kind of time to wait for a conclusive answer :)
>
> Enough of this thread seems to be in favor of choice #1, so that's
> what I'm going to do for starters.
POST /link_styles/1/vote HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
support=true
200 OK
> my_model_instance.my_field =
> turbogears.util.slugify(some_other_text_field_data)
>
> ... or something like that, anyway.
this is what i use on thraxil.org:
def make_slug(title="no title"):
title = title.strip()
slug = re.sub(r"[\W\-]+","-",title)
slug = re.sub(r"^\-+","",slug)
slug = re.sub(r"\-+$","",slug)
return slug
not very sophisticated, but it works for my purposes. i also have a
modified version that does some rough conversion of unicode down to
ascii that i wrote for the 'Wicked' product for Plone.
one general purpose slugification routine may not be the best solution
though. some applications will have specific requirements. i've worked
with the journalism school here and they sometimes require a slug to be
in a specific format like 'authorlastname-oneworddescriptionofstory'.
other times autogenerated ones would be ok.
one other bit of advice is to prefer '-' over '_'. both are about
equally readable but search engines are smarter about '-'. if you have
/foo-bar/ in the url of a page, google will index it and relate 'foo'
and 'bar' to the page but if it's /foo_bar/, it doesn't recognize the
underscore as a word seperator so it will relate it to 'foo_bar'.
Here's a script for generally deunicodifying*:
http://www.crummy.com/cgi-bin/msm/map.cgi/ASCII,+Dammit
I'd say that it's bad to deunicodify, but in this case it seems like a
good idea.
[*] invented word
Hi Anders,
I agree that a generic slug field would not fit all situations, I also
think that a simple generic slug field with consistent rules might be a
simple and convenient addition to TG. Since they are also not hard to
write, then for those that have special needs, they can just whip one up
themselves.
On the other hand, I don't think it would be too hard to tell the slug
field to slug a list of other columns instead of just one. Also a
custom s regexp could be provided to change the rules. This might make
it more useful for special needs. But the default should be very simple.
If I get a chance, I will try to work on this. I generally don't have
time to contribute must to projects, but this may be something that I
can put a bit of time into.
Good thinking about generalizing it more.
Thanks,
Krys
Krys