This question exists because it has historical significance, but it is not considered a good, on-topic question for this site, so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. More info: help center.

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
If this question can be reworded to fit the rules in the help center, please edit the question.

@flossfan I think SO is really missing the boat on this stuff. In the explanation of the closed reason. "We expect answers to be supported by facts, references, or specific expertise, but this question will likely solicit debate, arguments, polling, or extended discussion." What's wrong with polling and asking the opinions from people that have "specific expertise" with a topic. I mean, if they don't want polling, then take away the up and down votes. That's for polling! It's to let developer say which answer they prefer or thing is best (that's a poll).
–
David SOct 6 '12 at 18:25

37

I'm trying to research Python, I've opened 3 stackoverflow links in a row that are 150+ scored and "closed as not constructive by casperOne"... all three were very constructive.
–
Ben LeshJan 14 '13 at 16:48

2

I have almost the same experience that blesh is writing about, but actually I can't remember when I've NOT seen the "closed as not constructive", but they've ALL been extremely helpful! I'm all for using the best tool for the job, but SO sounds like a hammer that refuses to be used for anything else than nails ... ONLY nails!
–
RobbieGeeNov 22 '13 at 20:40

16 Answers
16

Something to be careful about when designing a RESTful API is the conflation of GET and POST, as if they were the same thing. It's easy to make this mistake with Django's function-based views and CherryPy's default dispatcher, although both frameworks now provide a way around this problem (class-based views and MethodDispatcher, respectively).

This is incorrect, Django has full support for recognizing POST vs GET and limiting views to only certain methods.
–
aehlkeJul 23 '09 at 14:18

20

I meant that, by default, Django treats POST and GET as if they were the same thing, which is very inconvenient when you are doing RESTful services as it forces you to do: if request.method == 'GET': do_something() elif request.method == 'POST': do_something_else() web.py doesn't have that problem
–
Martin BlechAug 4 '09 at 11:48

19

@Wahnfrieden: If there is native support in Django for handling different HTTP verbs separately (by "native" I mean not needing "if request.method==X"), could you please point me to some documentation?
–
Martin BlechAug 4 '09 at 15:34

3

The conflation of POST and GET does not apply to Django's Class Based Views (added in 1.3), but I believe is valid for the earlier releases.
–
ncoghlanOct 11 '11 at 8:21

Note that -- out of the box -- Django did not have fine-grained enough authentication for our needs. We used the Django-REST interface, which helped a lot. [We've since rolled our own because we'd made so many extensions that it had become a maintenance nightmare.]

We have two kinds of URL's: "html" URL's which implement the human-oriented HTML pages, and "json" URL's which implement the web-services oriented processing. Our view functions often look like this.

The point being that the useful functionality is factored out of the two presentations. The JSON presentation is usually just one object that was requested. The HTML presentation often includes all kinds of navigation aids and other contextual clues that help people be productive.

The jsonView functions are all very similar, which can be a bit annoying. But it's Python, so make them part of a callable class or write decorators if it helps.

@temoto: If y = someUsefulThing(...) is an "Awful repetition", then all references to all functions and methods is "awful". I fail to understand how to avoid referencing a function more than once.
–
S.LottJul 12 '10 at 2:07

5

@temoto: "When you need to change arguments passed to someUsefulThing, there's a chance that one forgets to do so in all calls"? What? How is that "awful"? That's a trivial consequence of referencing a function more than once. I'm failing to understand what you're talking about and how function reference is "awful" since it's inescapable.
–
S.LottJul 12 '10 at 9:58

4

See the accepted answer. The result expression {'message': 'Hello, ' + name + '!'} is written once for all presentations.
–
temotoJul 12 '10 at 11:54

3

Your htmlView and jsonView functions serve different representations for same data, right? So someUsefulThing(request, object_id) is a data retrieval expression. Now you have two copies of same expression in different points in your program. In the accepted answer, the data expression is written once. Replace your someUsefulThing call with a long string, like paginate(request, Post.objects.filter(deleted=False, owner=request.user).order_by('comment_count')) and look at the code. I hope it will illustrate my point.
–
temotoJul 13 '10 at 18:32

This emphasizes what I really like about CherryPy; this is a completely working example that's very understandable even to someone who doesn't know the framework. If you run this code, then you can immediately see the results in your web browser; e.g. visiting http://localhost:8080/celc_to_fahr?degrees=50 will display 122.0 in your web browser.

@Wahnfrieden: Could you help the rest of us out by clarifying why you do not think the above is RESTful? From my point of view, it looks like a classic example of REST and doesn't appear to break any of the rules or constraints of a RESTful system.
–
lilbyrdieAug 11 '09 at 0:34

42

In simple terms, what the CherryPy example above is doing is exposing methods as "HTTP callable" remote procedures. That's RPC. It's entirely "verb" oriented. RESTful architectures focus on the resources managed by a server and then offer a very limited set of operations on those resources: specifically, POST (create), GET (read), PUT (update) and DELETE (delete). The manipulation of these resources, in particular changing their state via PUT, is the key pathway whereby "stuff happens".
–
verveguySep 11 '09 at 14:26

I don't see any reason to use Django just to expose a REST api, there are lighter and more flexible solutions. Django carries a lot of other things to the table, that are not always needed. For sure not needed if you only want to expose some code as a REST service.

My personal experience, fwiw, is that once you have a one-size-fits-all framework, you'll start to use its ORM, its plugins, etc. just because it's easy, and in no time you end up having a dependency that is very hard to get rid of.

Choosing a web framework is a tough decision, and I would avoid picking a full stack solution just to expose a REST api.

Now, if you really need/want to use Django, then Piston is a nice REST framework for django apps.

That being said, CherryPy looks really nice too, but seems more RPC than REST.

Looking at the samples (I never used it), probably web.py is the best and cleanest if you only need REST.

In 2010, the Pylons and repoze.bfg communities "joined forces" to create Pyramid, a web framework based most heavily on repoze.bfg. It retains the philosophies of its parent frameworks, and can be used for RESTful services. It's worth a look.

Especially the browesable interface is saving a lot of time while developing! Many other advantages, so everyone starting rest implementation should have a look. I started with tastypie, but switched completely to django-rest-framework
–
michel.iamitAug 16 '12 at 14:22

web2py includes support for easily building RESTful API's, described here and here (video). In particular, look at parse_as_rest, which lets you define URL patterns that map request args to database queries; and smart_query, which enables you to pass arbitrary natural language queries in the URL.