Skip to content

Instantly share code, notes, and snippets.

@idan
Created September 17, 2009 21:52
Show Gist options
  • Save idan/188747 to your computer and use it in GitHub Desktop.
Save idan/188747 to your computer and use it in GitHub Desktop.
[mmalone]: and there are a lot of things here that are pissing me off :/
[idangazit]: mmalone: can't say I've used it much, but I'm playing with it right now too
[idangazit]: what's bugging you?
[mmalone]: heh
[mmalone]: where should I start... :/
Gulopine joined the chat room.
[mmalone]: lemme dpaste my notes
[idangazit]: I'm still at the wrapping-my-brain-around-it phase, the lack of nontrivial examples is making that harder
[mmalone]: http://dpaste.com/85843/
[mmalone]: yea, and the example that ships with it is broken
[mmalone]: I've just been reading the code
[idangazit]: yeah, same here
[idangazit]: but a nice tidy larger-than-toy example would be nice
[jlilly]: so part of making a facebook app is being on facebook.
[mmalone]: idangazit: agree
[jlilly]: new favorite quote "Always go to other people's funerals, because if you don't go to theirs, they won't come to yours."
[mmalone]: maybe one of the _20 forks_ has a better example :P
[mmalone]: jlilly: I don't get it, they're dead :/
[jlilly]: mmalone: exactly my point.
•jlilly is constantly amazed at how stupid some of the people he knows are.
[mmalone]: I was just being a jerk and pretending I didn't get it :/
[jlilly]: I also played mafia wars for a moment. Stupid and simple, but mindlessly enjoyable.
[mmalone]: idangazit: also, piston doesn't seem to provide _that much_... I've written custom REST API stuff that's more sophisticated than this for individual projects
[mmalone]: I should just factor some of that code out and make my own library :P
[mmalone]: too bad I'm lazy
[idangazit]: mmalone: eh, lazy is what led me to piston
[idangazit]: I mean, I could just write views that generate XML
[mmalone]: that's a bad idea :/
[mmalone]: you need class-based views
[mmalone]: and you should be able to return resources from the view methods
[mmalone]: instead of returning HttpResponses
[mmalone]: those are good things that piston does, but they're not that hard to do yourself
[jezdez]: mmalone: stop being lazy!
[mmalone]: plus I don't like the way piston does class-based views
[jezdez]: I was of course kidding
[jlilly]: pro tip: if you're using the wrong api key.. shit tends to not work.
[idangazit]: well, so it's an abstraction of views, so instead of returning HttpResponse I return instances of models or querysets?
[idangazit]: lazy = somebody else's code doing that for me
[jezdez]: jlilly: oh, I hear yah, multiple heads against walls here because of that
[mmalone]: idangazit: yea, basically
[mmalone]: or you return a "Resource" type
[idangazit]: mmalone: I agree with your simpler 'WTF naming' notes
[mmalone]: and you create something like a ModelResource
[idangazit]: I haven't spent enough time with piston to appreciate the deeper issues you point out
[mmalone]: yea, I don't like how they're trying to rename HTTP concepts
[mmalone]: it just confuses things
[mmalone]: I really think the Handler / Resource concepts are reversed
[idangazit]: agree
[idangazit]: handler = view, resource = the thing supplying the data according to some mapping
[idangazit]: err s/mapping/logic
[jezdez]: ericflo: hm, someone sent me a pull request for django-threadedcomments, specifically the 0.5.X branch: http://github.com/garrison/django-threadedcomments/commits/0.5.X
[idangazit]: bah, I don't have time to rewrite all this now though
[robhudson]: what's HATEOAS?
[idangazit]: Hypertext as the engine of app state
[idangazit]: also, my favorite acronym
[robhudson]: wow
[mmalone]: yea, it's a horrible acronym
[idangazit]: I imagine that everybody says it "Hate: O-A-S"
[mmalone]: it basically means that if you have a representation of a resource it should have hyperlinks representing all of the transitions to new states
[mmalone]: that may be interesting
[mmalone]: so like, if you fetch a blog post
ericflo left the chat room. (Remote closed the connection)
ericflo joined the chat room.
[mmalone]: there should be hyperlinks to the blog it's on, the list of comments, the uri to create a comment, etc.
[idangazit]: mmalone: why would you want to retain state in Resource or Handler objs?
[idangazit]: (Not asking rhetorically, I'm curious)
[mmalone]: suppose you receive a conditional get
[idangazit]: seems kinda against the point of idempotency
[mmalone]: and you have an etag() method on your handler
[robhudson]: seems like a contrived acronym for the concept
[mmalone]: you may want to fetch stuff from the DB in your etag() method
[mmalone]: to calculate a hash
[ericflo]: I have one thing to say to you all right now!
[ericflo]: http://www.boingboing.net/robocop%20unicorn.png
Gulopine1 left the chat room. (Connection timed out)
[mmalone]: and save that stuff on the instance
[mmalone]: so that when your read() method is called you don't have to do the DB lookup again
[mmalone]: ericflo: that's amazing.
[robhudson]: ericflo: a robocop glittercorn would be even better
[idangazit]: ericflo: this is so going into somebody's next "I want a pony... WITH ROBOCOP" on it
[ericflo]: :D :D
[idangazit]: err, going into somebody's preso at DC
[Gulopine]: sigh
[robhudson]: oh dang, it's sparklecorn: http://data.tumblr.com/5CfCsDgoh1j3zp4n6uZsFT8k_500.gif
[robhudson]: can't even get my hornycorns straight
[mmalone]: idangazit: I've argued the "storing state on the class-based view" thing with Jacob before too... there aren't _that_ many places where it's useful, but the biggest problem is that there's nothing obviously wrong about it
[mmalone]: so people will do it
[mmalone]: and won't understand why their shit breaks in really weird and unpredictable ways
[mmalone]: and, in the places where it is useful, it's _really_ useful
[mmalone]: it's hard to hack around
[mmalone]: so, you may as well support it
[idangazit]: shrug, this might be one of those things which just need to be documented "here be dragons, don't touch if you don't know what you're about"
[idangazit]: but tbh I don't understand the use-case well enough.
Gulopine left the chat room. (Nick collision from services.)
Gulopine1 joined the chat room.
Gulopine1 is now known as Gulopine.
[mmalone]: hold on, I'll find you a use case
Gulopine left the chat room. (Client Quit)
[mmalone]: so this is a snippet from one of the RESTful apps I've built
[mmalone]: http://dpaste.com/85857/
[mmalone]: the setup() method is always called
[mmalone]: and by default does nothing
[mmalone]: it's called before get/put/post/delete
[mmalone]: and the base RestView class does conditional dispatching based on whether the ETags / Last-Modified match
[mmalone]: so if I couldn't store state on an instance I couldn't set self.event in setup()
[mmalone]: and I'd have to do a DB lookup in etag(), last_modified(), and get()
[idangazit]: Right. I get it now.
[idangazit]: mmalone: this rest app you've written, the underlying stuff is published somewhere? Or private code?
[idangazit]: Sounds like something I could learn quite a bit from.
[mmalone]: it's private code at the moment, I can share some parts of it though probably
[idangazit]: particularly the dispatching that goes on in RestView, never done that before.
[mmalone]: yea, I'll find that
[idangazit]: 1.2 pony: django.contrib.rest
[mmalone]: :)
bastih joined the chat room.
[idangazit]: actually, of all the various ponies people want to put in contrib that seems like something that would make sense (well, at least to me)
[mmalone]: http://paste.pocoo.org/show/136448/
[mmalone]: there are a couple things I'd do different if I were doing it over
[mmalone]: the biggest one though is I wouldn't have made RestView subclass HttpResponse
[mmalone]: the reason for that is to make it thread safe for storing state
[mmalone]: like I was talking about before
[mmalone]: but I found a better way... you can just make the dispatch method a class method
[mmalone]: and use that in your urls.py instead of just the class name
•idangazit is reading
[mmalone]: :)
[idangazit]: mmalone: then, where do you instantiate your subclasses of RestView?
[mmalone]: well, RestView is a subclass of HttpResponse
[mmalone]: so I don't explicitly instantiate them
[mmalone]: my urls.py just looks like (r'/blah/blah', RestViewSubclass),
[mmalone]: since the class is a callable
[mmalone]: the subclass is just instantiated
[idangazit]: right, the urldispatcher instantiates and calls
[mmalone]: and since it _is a_ HttpResponse it works :)
[mmalone]: well, it just instantiates
[mmalone]: but RestView subclasses HttpResponse
[mmalone]: it's kind of brainfuck, which is why I'd do it differently in the future
[ericflo]: I actually recently wrote an app that uses class-based generic views, for a small project...just to mess around with it. Here's how I did it if you guys are interested: http://dpaste.com/hold/85865/
[mmalone]: but at the time I wrote that code it was the best way I could think of
•mmalone looks
•idangazit feels like he fell into some advanced django-fu
[mmalone]: ha
[mmalone]: ericflo: yea, that's the way I've seen a lot of people do it
[mmalone]: so you instantiate the class in urls.py then
[mmalone]: and the dispatcher calls it, which runs __call__
[ericflo]: mmalone: yeah
[mmalone]: yea, I feel like we've had this discussion before, but the thing I don't like about that instances are globals that stick around so you can't store state on them
[mmalone]: the way I'd do it today is by using a classmethod
[ericflo]: brb
[mmalone]: idangazit: class-based views aren't really that complicated...
[mmalone]: the contract is
[mmalone]: that a "view" function is a callable that returns an HttpResponse
[mmalone]: so in Eric's example he would create an instance of his class and use that in urls.py
[idangazit]: similar to piston's resource
[mmalone]: and the urldispatcher would call it, and that would run Blah.__call__
[mmalone]: yes
[mmalone]: same thing
[idangazit]: grokking is happening slowly
[mmalone]: so, in the code I pasted my RestView actually _subclasses_ HttpResponse
[mmalone]: so when I stick a RestView in urls.py
[mmalone]: the urldispatcher just _instantiates_ the RestView
[mmalone]: but since the RestView _is a_ HttpResponse then it still works
[mmalone]: it's still just a callable that returns an HttpResponse
[ericflo]: mmalone: Oh that's interesting. What's the advantage?
[mmalone]: it's kind of dirty, and a bit of a layering violation, but it works
[mmalone]: the advantage is that a new instance is created for each request
[mmalone]: so I can store state on the instances
[idangazit]: doesn't seem dirty
[ericflo]: I see
[ericflo]: What kind of state do you want to store?
[mmalone]: ericflo: like this http://dpaste.com/85857/
[mmalone]: but, like I was saying before, if I were doing it all over again I'd probably use a classmethod
[mmalone]: so I'd have a classmethod called dispatch, for example
[ericflo]: I see
[robhudson]: too me a minute to see where ericflo's code dispatched to different methods (e.g. json, xml, html). Slick.
[ericflo]: (sorry, jumped in the middle of this conversation)
[mmalone]: and that classmethod would instantiate the RestView, then return something like RestView.get_response() or something
[mmalone]: that way RestView doesn't have to subclass HttpResponse
[ericflo]: mmalone: That would make a lot of sense too
[mmalone]: yea, it'd be a really easy change for your code... and then you'd just have to change your urls.py files to point to ClassName.dispatch
[mmalone]: and you're done
[robhudson]: so the key to thread safety is to make sure objects don't outlive requests?
[mmalone]: robhudson: that's a good rule of thumb
[mmalone]: it's more that you don't want objects to be shared amongst threads
[mmalone]: I think Jacob was talking about making the urldispatcher a threadlocal, so that would solve the thread safety issues
[mmalone]: but you still have state hanging around beyond requests, which is bad
[mmalone]: so if you serialized a big object and stuck it on your object you want that to be garbage collected ASAP, you don't want it hanging around possibly confusing things when the next requ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment