

Dropping Django - snprbob86
http://blog.brandonbloom.name/2009/08/dropping-django.html

======
far33d
This seems like exactly the right way to use a framework -

* start by using it as it is intended. Save lots of time by being up and running quickly.

* find a flaw.

* realize that the workaround is more work than rewriting a piece of the framework.

* stop using that part of the framework, but continue to use the rest of the code that you still haven't had to write.

~~~
mrshoe
Exactly right. This is not an argument to not use Django.

I think a lot of us have come to the same conclusion as this author: the
abstractions frameworks provide are often too high level. Very quickly the
needs of your project cannot be served by their generalizations. Especially in
a language like Python, it's often easier just to roll your own systems.

However, starting off with a framework is a great way to get off the ground
quickly. If you were to write everything from scratch from the beginning, you
might burn out before you even produce anything usable.

Personally, I think CherryPy is the way to go. You're probably not going to
need to rewrite HTTP [1], so that's an abstraction layer with which I'm
comfortable. Everything else will need to be easily customizable for your
project.

[1] Unless the threaded model doesn't work for you, like it doesn't for our
chat backend.

~~~
jamesbritt
"Exactly right. This is not an argument to not use Django."

No, but it might be an argument to consider frameworks that make it easier to
replace parts as they become more trouble than they are worth.

~~~
ubernostrum
From what I read, it didn't sound like he had much trouble. And, honestly, the
various "swappable components" frameworks are basically in the same boat as
far as I know: the ability to mix and match decreases dramatically once you've
written application code, because their emphasis is on the _up-front_ choices,
not on swapping things later on.

~~~
snprbob86
It certainly wasn't easy. Although the vast majority of the difficulty can be
attributed to porting application code, some difficulty can be attributed to
Django. I would have preferred a framework which makes it easier to swap out
components, but it is unclear how much it would have really mattered except
for in terms of psychology.

~~~
ubernostrum
Well, this is something I've been quietly agitating about for a while, because
I have a feeling that your case is one where "swappability" doesn't help much
-- once you've written your application code around a particular component,
switching to another component is going to involve rewriting. How much
rewriting may vary, but AFAIK there's nothing that can automagically port
code, say, between popular Python ORMs.

------
viraptor
It's bizarre... I started writing a project in django 2 weeks ago and had to
think about some of those elements in the first week. But I'm still running
"clean" django!

Here are my solutions for anyone interested:

* URL Routing: They mention only breadcrumbs functionality here. I created breadcrumbs by template inheritance instead. There are url routers split by application and by modules. Template inheritance tree resembles the url routing levels, so that each template has: "{% block breadcrumbs %}{{ block.super }} &middot; current-level-text{% endblock %}" Simple, but works so far :)

* Authorization: My views are decorated with @require_auth() if they require authorisation, @require_auth('group name') if they require special privileges and @require_auth(redir_to='...') if user should be redirected to a special place after authorisation. (by default they come back to the same place) Simple and works.

* Authentication: I simply didn't use the standard user classes. I used my own model. I don't consider it dropping Django - it's more like not using standard helpers.

* Templating: So far I'm happy with the whole logic in the view. Not sure how complex their application is... I'd really like to see some samples that required programming in the template...

* ORM and Admin UI: Can't comment on this one. I'm writing for google app engine and simply using their object store. It feels more comfortable than RDB so far. But sometimes I use GQL if it's faster.

* Form Validation and Generation: I've created a couple of dynamic forms extended with dynamic fields by jquery, as well as some forms with fields and validation generated on the fly (from user input, or saved data)... I can't find anything that's not possible with django forms. Sometimes I customise forms as needed, sometimes the autogenerated ones are almost perfect. Again - not using helpers all the time is not "dropping django".

I'm a bit disappointed that they didn't provide more examples and their
solutions... maybe we could learn something from that.

------
mlLK
It doesn't even sound like he made an effort at learning django, let alone
python. . .look, django has a bit of a high learning curve behind it (I'm
still at it myself) but when it comes down to its a web-framework, a web-
framework for people who like programming in python.

I'll admit I felt the same way at first, but I was honest with myself enough
to stop toiling with django and set aside the time to learn how to program in
python. Once I started pin-pointing the obvious advantages of writing
application-level programs in python I started to grasp the underlying
advantages of django's design and philosophy.

~~~
pmclanahan
That's the impression I got as well. He didn't seem to "get it." I can't see
complaining about Django being poorly decoupled, only to then go on to
describe how little of it you're still using. How tightly-coupled can it be if
you're only using small pieces?

Also, it seems like a lot of the complaints are about contributed apps like
authentication and the admin. It seems to me that he never really tried to
learn the admin, or was using a very old version. And you don't have to use
authentication at all, you can completely write your own, or fork the one that
comes with it and make it work for you.

But the main thing that bugs me is that he obviously doesn't get opensource
either. If you think you have a better way, get on the mailing list and
suggest it, create a ticket, or implement your changes and submit a patch.
Writing your own stuff, not releasing it, and complaining on a blog doesn't
help anyone.

~~~
snprbob86
The admin is bar far the biggest offender of tight coupling: primarily to
authentication and the ORM. Being "contributed" isn't an excuse. Everything is
"contributed". It's open source!

I haven't got time to actively participate in Django's development. Especially
because I'm not particularly interested in the details discussed on the
mailing list and I've already found components I'd prefer to work with (and,
by extension, contribute to). I've got a product to build. I took some time to
write down my thoughts and the key contributors are welcome to read my rant,
ask questions, and learn from it.

~~~
jbronn
Open source software is not a one-way street. If you had spent as much effort
on this gripe post as participating in the community (or even reading the
docs!) then you would have had the answers to your questions rather than
having to roll your own framework.

~~~
jasonkester
But now he has something _better_ than django that he can use on his next
project. It works well for the kinds of projects he builds, and does what he
expects. He wins.

There's no reason to contribute it back to the community, because it's
specifically targeted to his needs (and therefore wouldn't be considered
_better_ by anybody outside his team). Spending even an hour polishing it up
for somebody else's consumption would be a distraction.

~~~
turtle4
But if he would contribute back, then -everyone- would have something better
than the (current) django. That is how it works. I agree with grandparent
poster that more people should take the time to contribute and/or make their
changes available.

That said, at least he documented things and presented his issues cogently so
that the dev team can see where issues are, and possibly address them in the
future.

~~~
jasonkester
Not likely. I'm a big advocate of rolling your own framework that meets your
(and only your) needs.

The thing we use at Expat is incredibly fast and turns out really good code.
It's the reason we can move so fast, and it's a competitive advantage. But I
wouldn't release it to the world.

It just has too many optimizations for the way we like to do things. And
there's still the matter of the order-of-magnitude gap in level of effort
between something you use in house and something you can release as a product.

Right now, this guy has something stripped down to the bare essentials to do
what his shop does. Ideally, he's shed all the useless garbage that naturally
accumulates in any commercial framework the size of django. And as a result,
the final product probably isn't of any use to anybody outside his team.

------
intellectronica
I'm no big fan of Django, but it sounds to me like you started using a well-
established framework and whenever something was painful you chose to roll
your own. Maybe a better approach would have been to engage with the Django
community and help make these things less painful. That way your experience
would benefit the next users, and you'd benefit from the collective wisdom and
shared resources of a big and serious community. All other things being equal,
rolling your own is rarely the right solution.

~~~
snprbob86
I only rolled my own URL routing. The complete implementation is less than 70
lines of Python.

Why am I obliged to engage the community when things are painful? I took an
easier route: I choose less painful components.

~~~
dmoho
I wouldn't say that you're obliged, but I'm sure they'd appreciate the
feedback about what was painful and what wasn't.

Edit: I guess the article could be considered feedback :)

------
tptacek
"We wouldn't ever hire a designer who couldn't pass a code review for some
trivial template logic."

I've worked with four design firms now, three of them excellent, and none of
them could have been expected to understand templating code. If you're asking
your designers to work with a template language, you're doing it wrong.

This has nothing to do with whether you put logic in your templates or not.
The designer's deliverable isn't a working site; it's HTML/CSS/PNGs, and it's
a dev's job to pull that into the framework.

~~~
po
Those two opposing viewpoints on a designer's role probably have a lot to do
with the type of application you are designing. If I was doing the hiring, I
would expect more template language understanding for a web application than
from marketing or traditional web site.

I think it's fair for him to say he wouldn't ever hire a designer like that
but I think it's because he's only built sites where it makes sense to
optimize for that.

~~~
tptacek
Why on earth would you want to narrow your options? There are dozens of
template languages. Why would you want to spend one cent extra, or sacrifice
one extra cent of quality, to find a designer who was not only skilled in
information design, graphic design, typography, and interaction design, but
also Django (or Erb or PHP or Clearsilver) literate?

~~~
blasdel
Django templates are significantly different than all the other ones you
mentioned.

It was architected from the beginning to be friendly to non-programmers -- the
idea was that someone writing an article for the Lawrence Journal-World (or a
designer) could easily use custom templating in a constrained templating
language that developers can augment with custom tags and filters.

It surprisingly works incredibly well for that use case. The templating
language strictly enforces view-separation -- the template author can't do
anything the developer didn't intentionally let them do.

It can be ridiculously frustrating if you're expecting it to be a normal
language -- for instance __getitem__, __getattr__, and __call__ all use the
same "obj.property: arg" syntax. It calls hasattr _at every call site_ to
figure this out, and you can't use () or [] even if you wanted to. Fuck, you
can't pass multiple arguments to a function!

------
tvon
Django is not without it's problems, but some of this isn't correct (upon a
quick skim). For example, the Django admin does support filtering and sorting,
you just need to indicate this in the admin class.

~~~
snprbob86
You can set sorting order and filtering options in your admin class, but the
UI doesn't provide clickable column headers or anything like a search box.

EDIT: Apparently I was mistaken, as the replies point out. I read the Django
book, but I do not recall this chapter. My apologies.

~~~
jonknee
Maybe I am misunderstanding you, but it does do clickable column headers (by
default even I think) and you can definitely have a search box.

~~~
ubernostrum
By default, any field on the model that's displayed as a column in the list of
objects is clickable to sort. You can also display things based on other
attributes of the model (e.g., calling a method), and if you like you can
specify that they're tied to particular fields to get clickable sorting for
those as well.

------
paulgb
I've found the same thing with django. It does some things well (the admin
interface, for example.) Other things it does in ways that seem very
unintuitive and unpythonic.

For example:

\- includes a test framework, but tests on a fresh project don't pass

\- no relative paths in settings.py make it hard to work with other people
(sure, since settings.py is python code you can write code to get around it,
but I don't like that approach)

\- you can't extend the User class (except by using deprecated code); the
workaround is to create a one-to-one table but that's ugly.

\- templates have their own control structures rather than using the ones
pythonists already know (django's ifequals vs. python's if, for example)

If you're fed up with django, try Pylons. It is very loosely coupled, to the
point where the recommended ORM and template system are separate projects
(SQLAlchemy and Mako).

------
steamboiler
"We are now using SqlAlchemy via schema reflection; _no declarative layer_."
(emphasis mine)

What next? Will web development come full circle to using raw SQL queries like
Phil Greenspun suggested years ago? (Not that there is anything wrong with it)

~~~
gecko
I've worked with a number of different ORMs, including two on the project I'm
on right now, one custom one, and a handful of open-source ones on Ruby and
Python and the like, and every single time, the story's the same.

At the start of the project, when queries are few and datasets are small, all
of the above worked great. But the further you get into the project, and the
more complex things you are trying to do with larger and larger datasets, the
ORM ends up blowing up in your face. For example, LINQ to SQL--which I want to
emphasize I'm picking on only because I'm using it righ tnow--happens to
silently and transparently convert from IQueryable (meaning that your LINQ
will execute in the DB) to IEnumerable (which means you'll suck in all data
required for filtering past that point), which means that you never have a
good idea whether your query is going to be optimized or not unless you check
the SQL being generated. When you have to do this a few dozen times, you start
wishing you'd just written SQL in the first case.

The situation gets worse when you start getting into join-heavy queries. I've
never seen an ORM that actually can cover everything you need to make an app
performant. It doesn't handle full joins, or compound indices, or
distinguishing between clustered and nonclustered indices, or calculated
columns, or some other thing that, if you were in raw SQL, would easily solve
your problem, so at that point, you start introducing raw SQL. The older your
app gets, the more instances of this you get, until you'd have been better off
simply using SQL the entire time anyway.

I love the idea of an ORM in theory, but I'm pretty solidly convinced these
days that if you want objects, you should us an OODBMS, and otherwise, you
should just embrace the relational model for what it is, and not pretend
you're working with objects. For most people, that'll mean writing SQL and
getting back query sets.

~~~
snprbob86
I haven't used Linq to SQL except for to play with it for a few minutes. It
seemed like a very capable ORM, but I sensed that the IQueriable to
IEnumerable conversion may cause some headachs.

Linq to Objects, however, is freaking amazing. C#'s functional and querying
features are like Python's generator expressions on crack, speed, steroids,
and acid. Absolutely love them.

~~~
gecko
LINQ to Objects is C#'s (very good) take on Python's list comprehensions, and
is awesome. However, that's just providing a declarative, functional way to
query/iterate objects--not an ORM. LINQ to XML is likewise also okay, since
XML's tree-based model happens to map extremely well to objects in a way that
a relational model cannot do.

LINQ is great. LINQ to SQL is actually very good, so far as that goes; it just
happens to be trying to do something that I'm not convinced can be done well.

------
lacker
I've had similar experiences... too often Django makes it difficult to do
something really simple. If you are not building a newspaper-like site that
fits exactly to the Django model, it gets annoying.

But it does support a lot of stuff out of the box, so it's still my favorite
python web framework, and I have probably set up about a dozen different
Django projects.

~~~
forsaken
What problems did you exactly run into? I hear a lot of people say this, but
never get good examples, which would hopefully make the framework better.

~~~
paulgb
The article gave some examples that I've run into myself: using email
addresses instead of usernames for authentication, and adding additional
fields to the User class. I also dislike the template language. Why invent
your own language and control structures when everyone using it knows python?
Mako (<http://www.makotemplates.org/>) does a good job of not reinventing the
wheel.

~~~
mtrichardson
One of the main assumptions behind the Django templating language is that you
don't need to know Python.

[http://docs.djangoproject.com/en/dev/misc/design-
philosophie...](http://docs.djangoproject.com/en/dev/misc/design-
philosophies/#template-system)

"The Django template system recognizes that templates are most often written
by designers, not programmers, and therefore should not assume Python
knowledge."

In my experience this has often been the case.

~~~
paulgb
I figured that had to do with it, but it doesn't really explain why they don't
just use an equivalently powerful subset of python. Better yet, allow full
python like Mako does, and let the designers decide what subset of that to use
in templates.

~~~
racketman4
The template language isn't for you.

~~~
paulgb
Which is why, given the choice, I would use something more like Mako.

------
bad_user
I also did my own URL routing ... <http://code.google.com/p/django-catalyst/>

I copied the chained actions model from Catalyst, and the routing is
automatically generated. I also have template tags defined that construct
these URLs for me (not uploaded in the repository).

I structure my views in a structure like ...

    
    
       views/root.py
       views/articles.py
       views/users.py
    

views.root contains a "begin" method, that will be chained to all other
requests. If views.articles needs users to be authenticated, I also add a
"begin" view to views.articles (where I do the authorization required). So as
an example, a chain could look like this ...

    
    
       views.root.begin -> views.articles.begin -> views.articles.item -> views.articles.show
    

This is really far from the way things are done in Django, but it seems more
intuitive to me.

What I find cool about Django is that the dispatching is really simple to
understand, and it can be extended (and components aren't hard to replace in
general).

------
dnaquin
I really should start making a list of things horribly broken in Django. By
design.

I write off and hack around problems almost daily.

------
megaman821
I don't quite understand the URL complaint. Each app can have its own urls
file that you include in the main urls file. Isn't that a tree-like structure?

Also views can be served by callable classes, so an init function can populate
the context (or a chain of them with class inheritance) and then the
appropriate code can be run to serve the view.

~~~
snprbob86
It's a tree of lists of trees. I rather a tree, than tree-like :-)

Some of our apps have deeply nested paths (typically a no-no, but actually
quite appropriate for our problem domain), so it is impractical to create a
module and call "include" for each tree node.

As for callable classes: someone has to instantiate them. That's no different
than our custom routing and authentication. I just choose function composition
over class inheritence.

------
ghostwheel
And what project does this refer to? It might be more informative to see the
actual app and then compare it to his comments.

~~~
snprbob86
I'm trying to keep my work, personal, and startup lives seperate. My project
is no secret, but one of my recent blog posts was trafficed by some co-
workers. I don't need my manager wondering if/when I'll be quiting.

Our site: <http://www.classlet.com>

Announced here: <http://news.ycombinator.com/item?id=679000>

There is a new version on the way with a huge host of new features and some
significant cleanup. The version that is live now is more of a proof of
concept.

