top | item 5617743

Lessons learned defying Joel Spolsky with Django

138 points| benregn | 13 years ago |speakerdeck.com | reply

149 comments

order
[+] nnq|13 years ago|reply
Bumping into ORM limitations + moving to Jinja for templates --> one word: Flask

...really, what advantage does Django provide at this point in this project anymore?

[+] SoftwareMaven|13 years ago|reply
Completely replacing the template system with Jinja is silly (no idea if this is what they did) since it significantly reduces the value of the Django ecosystem. Far better it to use jinja for your work, but leave the Django templates for Django and all the other apps you integrate to use. I do with Django would reduce their stance on no expressions in the templates. Sometimes it saves a lot of work to just be able to call a function or add two numbers together without needing to build a filter or tag every time.

I've been happy with django-jinja[1] for that purpose. It replaces the context processors so it will load jinja templates if they have a .jinja extension and Django if they are .html. It also includes the django filters in jinja-land.

The ORM is more problematic. I just started a project a couple months ago and thought a lot about ditching the default ORM in favor of SqlAlchemy. I decided not to, for the reason of expedience and, as the TFA mentions, it already leaks. So, I stuck with the Django ORM and will drop to SQL directly if need be (need being defined by the ORM making the code confusing or there being performance hotspots).

1. https://github.com/niwibe/django-jinja

[+] megaman821|13 years ago|reply
There are still a lot of Django apps that work fine in this scenario. Plus I don't think the slides imply that they are just blindly replacing ORM calls with raw SQL, just that they have profiled and replaced the hot spots.

Also Flask is a micro-framework and Django is a full-stack framework. Flask can be used as the backbone of a full-stack framework but figuring out a good project structure and finding out what third-party apps to use can be daunting for a person without Flask experience. If you really want to get people to switch, package up a Flask-based framework with the features of Django.

[+] pyriku|13 years ago|reply
Middlewares, context processors, forms, (class based) views, and tons of third party applications.

The CTO of a startup where some friends are working thought the same you did, and 2 years ago rewrote everything to Flask. Now they're going back to Django.

Django is much more that an ORM and templates.

[+] Alex3917|13 years ago|reply
"what advantage does Django provide at this point in this project anymore?"

Documentation. I use Django but without any ORM and with Jinja2, so it's basically just Flask but with more stack overflow threads and more third-party software.

Is there any actual advantage that I would be getting by using Flask instead?

[+] andybak|13 years ago|reply
In addition to the other replies I have to add - the goddamn Admin. The amount of time it saves me is beyond belief.
[+] naithemilkman|13 years ago|reply
In addition to what everyone else has mentioned, the amount of libraries written for Django is staggering. You almost never need to roll your own app -- someone has already done it!

Also, geodjango.

[+] antihero|13 years ago|reply
It has an entire ecosystem and tool chain to sort building websites/webapps. When I used to use Flask, before moving to Django, I found myself essentially creating a whole bunch of stuff that Django already has, and is better written.
[+] bmelton|13 years ago|reply
To throw a completely different wrench into the mix, I mostly just use Django to provide an API anymore, and for session handling.

I love and use Django, and have built large projects where I haven't really run into any limitations with it[1], but for the most part, nowadays my workflow is to pip install django, south, tastypie, then load in a template with Backbone and Marionette, then get to town.

Templates are either Mustache or Underscore, depending.

[1] - Yeah, it could be faster, but if you have a large, confusing database schema that you inherited, the Django ORM is great for getting things stood up, and then just tune the queries after the fact. It's still a huge timesaver vs. writing every query by hand.

[+] zzzeek|13 years ago|reply
Don't use just one ORM and then declare "ORM's are stupid". The "object = None" / "object_id = None" issue illustrated here is certainly not a mistake every ORM makes.
[+] k4st|13 years ago|reply
The SQL generated appears correct, unless the underlying database can guarantee that all foreign key constraints are met. That is, I consider this a failure of the user of the ORM to appreciate that the two invocations of filter are not identical.

In the former case, the query is verifying that the object_id field cannot be used to find a foreign object--regardless of the value of object_id. This is exactly what it is asked to do.

In the latter case, the query is simply verifying that object_id is NULL, which is exactly what it's asked to do.

[+] tmarthal|13 years ago|reply
Obviously there are subtleties to things that may not be apparent, but his example makes sense to me and so does the SQL queries that are generated. The first query is operating at the "object level" and the second is operating at the "attribute level".

The first is retrieving the object and checking if it exists, and the second is just checking the parent's foreign key. Not sure that they are really the same query, if you have unenforced foreign keys.

This is not "dumb", this is analogous to checking if a pointer is null or that the contents of the pointer are null (which is a distinction that some people want to make).

[+] Aqueous|13 years ago|reply
Why not just write the SQL?
[+] InclinedPlane|13 years ago|reply
Do you have an example of an ORM which is not in some fundamental way "stupid"? I haven't found one yet, but I'd love to know one existed somewhere.
[+] avenger123|13 years ago|reply
Definitely agree.

Using an ORM should not exclude also using direct SQL. It should be both.

I believe this brings the best combination. Anytime there is major complexity just drop to normal SQL.

The best of both.

[+] Daishiman|13 years ago|reply
I think it's more of a case of the developer not having read the ORM documentation; this is a very newbie mistake (although very understandable, true).

Now obviously, some people would complain that it doesn't make sense to do the extra join, but then people would be complaining about magical or exceptional behavior. ORM behavior is very predictable about which fields are being queried

[+] macspoofing|13 years ago|reply
True, but every ORM will make that kind of mistake. You can't just build an object model without paying attention to the SQL layer.
[+] jroseattle|13 years ago|reply
I was expecting this slidedeck to be a bit more focused on defying Spolsky, and whether or not that was a good decision.

FWIW, I've never bought into Spolsky's vision that re-writing code is poor strategy. Steve Jobs never thought twice about ripping something apart and starting over. If anything, code re-write can be an advantageous position -- you often have a greater understanding of the problems you're intending to solve. When well-executed, it can take the form of heavy refactoring, even when switching languages/platforms.

[+] lstamour|13 years ago|reply
I found I could follow along with the slides, though some of the icons and messages around third-party tools were lost on me. I'd definitely appreciate a video.

Edit: 9 minutes ago, Nick posted to Twitter: "we have the recording - just need the sound cleaned up. Expect it early next week ;)"

[+] emperorcezar|13 years ago|reply
While I love seeing slides, this deck obviously could use the audio or transcript along with it.
[+] rattray|13 years ago|reply
Agreed, I for one was felt feeling rather in the dark for the last few slides especially...
[+] gingerlime|13 years ago|reply
> 20ms with Jinja2 without auto-escaping

could this performance improvement back-fire if you end up with a security issue?

I'm not saying that it definitely would. If you know what you're doing / trust your data sources or sanitize them elsewhere, you should be fine. I'd be careful turning off such a feature completely though...

[+] Daishiman|13 years ago|reply
Of course. This is merely a tradeoff between performance and developer time. 99% of projects will never have HTML autoescaping as a performance pain point. Then again, you're going to need tens of hours to review all templates to make sure you're escaping everything. If your hardware budget is greated than what it costs to audit the code, it's the proper decision.
[+] tachion|13 years ago|reply
I wonder, is there a video of the talk available? The slides, unfortunately, alone are rarely very informative.
[+] speg|13 years ago|reply
Does anyone know what tool was used to profile the django app? Looks cool.
[+] claudiusd|13 years ago|reply
I don't think Spolsky's argument applies to startups... His argument basically boils down to "You think the code in front of you is a mess, but the reality is you're just having trouble reading somebody else's code which is probably good enough". But what if you wrote the code yourself? In that case, it's probably just a mess.
[+] Uchikoma|13 years ago|reply
Iconfinder. They are profitable? They have business requirements? Joel wrote about the problems of a rewrite when you need to earn money, implement money making features, heavy competition while at the same time maintaining two plattform where one is a moving target. I don't think Iconfinder fits in any of these constraints.
[+] bsaul|13 years ago|reply
Did someone understand the last slides about the differences between transactions in tasks with and without celery ? I'm using celery, and i have been using django in the past, and I really didn't get the point.
[+] mbell|13 years ago|reply
He's trying to avoid the situation where you enqueue a background job inside a transaction and the worker gets started on that job before the transaction is committed. If the job needs to hit the database for any reason your likely to get errors as the new data hasn't been committed yet.

It looks like the work around he used is to cache the job queue locally and only flush it to the real job queue after the database commit, so your guaranteed whatever data may be needed for the job has been committed to the database.

[+] ashchristopher|13 years ago|reply
Basically if you modify data in a transaction, add a task to the queue that relies on that data, and the worker pulls the task off the queue BEFORE the transaction is committed, then the task tries to access data that doesn't exist in the database yet.
[+] spitfire|13 years ago|reply
He's trying to fix/avoid a race condition caused by data created within a transaction not being committed yet.
[+] dmishe|13 years ago|reply
Interesting point on celery and transaction, though I've never seen that happen in real life, interesting.
[+] Uchikoma|13 years ago|reply
+100 for using "leaking abstraction" in a slide deck "defying Joel Spolsky"
[+] beambot|13 years ago|reply
Is there a (publicly available) video that accompanies this slide deck?
[+] Kiro|13 years ago|reply
I didn't understand why ORMs are stupid. Can someone enlighten me?
[+] cwbrandsma|13 years ago|reply
The real issue with ORMs isn't the ORM itself, but over reliance on the ORM to do everything the right way and not validating the ORM is doing things the right way. ORMs are also often heavily leaned on by people who don't understand SQL and relational databases well enough and just want a data dumping ground (would have been better off with a document database).

But, if properly validated, and knowing when to NOT use the ORM, a good ORM can help you get a lot of work done very efficiently. But I've also seen improperly used ORMs turn into MASSIVE time sinks where devs spends days just configuring the stupid thing (hello Hibernate/nhibernate).

[+] kybernetyk|13 years ago|reply
I guess his point is that they sometimes create huge ugly and inefficient SQL queries. (Reminds me of the 90s sentiment of C compilers creating ugly assembly.)
[+] mattchew|13 years ago|reply
If you know SQL, they're often frustrating. You know what you want to do, but there's some ridiculous arcane approach to get those results via the ORM. If you can do it at all.

ORMs make it easy to do things like run queries inside a loop without realizing it. I worked on a site where the front page ran something like 200 queries every time it was accessed thanks to ORM magic.

[+] PeterisP|13 years ago|reply
All abstractions tend to be leaky.

ORM can abstract DB/SQL for you, but if you really ignore DB/SQL, then it can happily make some queries an order (or two ) of magnitude slower than they should be.

So, you must always think in explicit SQL-query-terms anyway; and then it's just a balance for ease of coding - does the ease of ORM syntactic sugar outweigh the effort for you to double-check if any ORM-built queries don't accidentally do something stupidly slow.

[+] macspoofing|13 years ago|reply
ORMs pretend to give you full abstraction, but in reality you have to be aware of the underlying SQL layer when you build your object model.