Tips for a new Django developer
zeroandone.posterous.com
zeroandone.posterous.com
Of-course, be careful while doing so though 'cause the stuff that isn't documented can change at anytime, and may break your code.
The point about schema evolution is important.
I've taken to using a pickled python object in a text field in every model. That flexibility to store arbitrary data in a hash is amazing. I've used it to, for example, represent twitter accounts that are oauthed, with password, following the business account, or just nothing special. 4 kinds of accounts, with logic in the model to deal with it properly, all without evolving the schema. I only started with the first 2, and added the latter two without a problem.
I'm pushing this a bit further now, and transitioning away from models altogether, and experimenting with a non-relational database like couchdb. I'm debating moving to google app engine too, but found some details (like getting on your own domain) to be pretty annoying.
Someone else may be able to shed more light on this and correct me (please do!) but thats my concern and would love to hear if it was a valid one or not.
Can you just do the same thing with JSON, Yaml, or your favorite serialization method of choice that does not have catastrophic consequences if parsing gets subverted?
Sure. You can even extend the `json` module to serialize custom data types not defined in the JSON spec.
This snippet is really helpful: http://www.djangosnippets.org/snippets/513/
One may think that if only the internal model of the user input is pickled, and the user only gets to update this internal model through web requests in defined ways, thus never getting to upload pickles or construct arbitrary complicated python objects, it should be relatively safe.
However, what remains is that if someone manages to blindly inject SQL, he can inject executable code into your application, instead of just injecting data.
When you upvote and need to sign in, the code to execute the upvote is stored to be executed once you sign in.
I love it
That's basically what App Engine does right there. It stores by an id, then the value is your object serialized as a protocol buffer.
The App Engine datastore allows you to look up by other properties than id because it indexes every field of your object in the background without you having to deal with it. You can query by pair-wise or more-wise indexes too, but you have to create those manually.
On a semi-related topic - I have an old 0.96 Django app that was using an old database migration framework that isn't supported in the newer versions of Django. For that framework I wrote the Django migrations in manually generated SQL. Anyone know how I could update to django-evolution or South with this hand coded SQL and still preserve my existing data?
The documentation for django-evolution says:
> Django Evolution imposes one important restriction on your development process: If you intend to make a change to your database, you must do it through Django Evolution. If you modify the database outside of Django and the Django Evolution framework, you're on your own.
Which makes me think I can't use that.
another thing worth mention is that use generic view, it will save lots typing:)
I disagree with #4, the suggestion to not include business logic in views. What Django calls 'views' are what other frameworks call 'controllers' (MTV=MVC), and the business logic should reside there. I'm totally for separating the code into helper functions in other files, but putting business logic into models definitely violates the idea of MVC.
For #5, I would recommend the second approach of having a separate settings.py for production vs development. Or at least code it where DEBUG=False is only overridden if socket confirms you are on a development machine - not the other way around. Debug contains too much info to risk exposing in production, but maybe my fear of socket screwing up is unfounded.
I like to think of the view functions as controlling state in an app and deciding what do show on a page (handing input or sticking stuff in the request). Something in between the presentation logic (in templates) or "business logic".
I think the django docs suggest that business (or domain) logic should go in the model (in an extra method) if it pertains to a particular instance of the model - or row in the db. Class level logic should go in a Manager for the model - like doing special queries, for example.
As an aside, I think that this approach makes my code pretty easy to test, I can whip up a test case that uses data in fixtures without having to worry about the view. Using something like the command_extensions makes it pretty easy to prototype model/manager code in the python shell against real data in my dev env. This is probably my favorite thing about working with python/django over java.