6 ms·
Dropping Django
- far33d 17y agoThis 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.
- jwecker 17y agoAgreed. I eventually moved from django to pylons going exactly through this process- except that instead of rewriting pieces I was able to just plug them in with pylons. I believe the reddit guys had a similar experience.
- mrshoe 17y agoExactly 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.
- jp_sc 17y agoHave you tried Werkzeug (http://werkzeug.pocoo.org/ http://werkzeug.pocoo.org/)? It's a very interesting piece of technology. Like CheeryPy plus a Rails-like dispatcher.
- jamesbritt 17y ago"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 17y agoFrom 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 17y agoIt 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 17y agoWell, 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.
- mlLK 17y agoIt 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 17y agoThat'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.
- eculver 17y agoIf I could vote this comment up a thousand times I would.
- snprbob86 17y agoThe 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.
- steamboiler 17y ago"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)
- snprbob86 17y agoMy next post will be about ORMs and the declartive paradigm in particular. It may prove to be more controversial than this post :-)
- wehriam 17y agoI wish. I find raw SQL much easier to use than any of the abstraction layers.
- ams6110 17y agoNice to see at least one other person thinks so.
- jp_sc 17y agoWeb.py does something like that. Not raw SQL but almost: result = db.select('table', what='id, name', where='id>3', order='id', limit=5) Is better than cursors, but for medium to large web applications is too much work. I used to be against ORMs ("Another layer? How inefficient"), but now I see them like compilers: They're easier to work with and, most of the time, SQLAlchemy does the job better than me (lazy-loading, etc.).
- gecko 17y agoI'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.
- lacker 17y agoI'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 17y agoWhat 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 17y agoThe 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/ http://www.makotemplates.org/) does a good job of not reinventing the wheel.
- mtrichardson 17y agoOne 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-philosophies/#template-system http://docs.djangoproject.com/en/dev/misc/design-philosophie... "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 17y agoI 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.
- deleted 17y ago[deleted]
- ghostwheel 17y agoAnd what project does this refer to? It might be more informative to see the actual app and then compare it to his comments.
- snprbob86 17y agoI'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 http://www.classlet.com Announced here: http://news.ycombinator.com/item?id=679000 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.
- tvon 17y agoDjango 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 17y agoYou 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 17y agoMaybe 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 17y agoBy 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.
- sebg 17y agoI was going through the django book and here is something that could help you out: search_fields = ('title',) "Finally, the search_fields option creates a field that allows text searches. It allows searches by the title field (so you could type Django to show all books with “Django” in the title)." http://www.djangobook.com/en/1.0/chapter06/ http://www.djangobook.com/en/1.0/chapter06/
- jbronn 17y agoThe admin provides both of these features -- specify the columns you want to be clickable in the `list_display` attribute on your `ModelAdmin` class. Similarly, specify a `search_fields` attribute to add a search box for the columns you want to search. Why read the documentation or look for examples when you can write a blog post screed and post it on HN?
- intellectronica 17y agoI'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 17y agoI 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 17y agoI 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 :)
- megaman821 17y agoI 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 17y agoIt'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.
- tptacek 17y ago"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 17y agoThose 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 17y agoWhy 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 17y agoDjango 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!
- viraptor 17y agoIt'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 }} · 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.
- paulgb 17y agoI'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).
- dnaquin 17y agoI really should start making a list of things horribly broken in Django. By design. I write off and hack around problems almost daily.
- bad_user 17y agoI also did my own URL routing ... http://code.google.com/p/django-catalyst/ 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).