Ok here it goes: I don't have a proper platform for my observations / rants so I figured I'd try my luck here. Django has been my favorite framework for developing web applications for about a year and a half, so it comes from a position of love when I say that the Django app really sucks as a level of abstraction. And I'm really looking for a way out so any suggestions are much appreciated. A tl;dr is provided below.
Others have complained before me. Two particular ones worth mentioning are: http://www.scribd.com/doc/37113340/Why-Django-Sucks-and-How-we-Can-Fix-it which claims that "Apps which provide models are inflexible" and http://www.mutualinformation.org/2010/03/why-i-switched-to-pylons-after-using-django-for-six-months/ Both claim that the Django app provides the wrong level of abstraction, neither goes in too much detail exactly why that is the case. That's the question I'll attempt to answer. Before we can answer the question we must first set some reasonable expectations for an "app". I'd say an app is a small package of closely related features as they are presented to the user (in the context of a web project) that can be easily modified/extended for any given project. Examples of apps (in my own particular context): * Dealing with customer information (a mini CRM). Adding, editing, useful overviews. * A small news app (Add, edit, overviews) * Our own particular UserProfile app (editing, viewing others, birthday calendars etc.) * A small budgetting tool (creating budgets, see how much money has been used) * Logging time lines (for worked hours), searching them. I choose this definition for "app" because it is a very useful one in the context of web projects. At least in my context it works like this: we have a lot of customers with similar intranets and extranets. Each one of them might want a particular subset of the various apps we have "on the shelf". By the way: there's other things that can already be reused quite well. Anything pure python for example. Or extensions to Django (extra fields, extra context managers, middleware etc etc.) This is not my concern, mainly because it already works well. One thing that deserves extra stress is that apss should be easily extendable. Exactly the fact that every customer want something that is slightly different from the next is how we're able to provide value. (This is also the reason I like Django in the first place: making stuff "your own way" is very easy). So: if no one want exactly the same, extensibility is a major prerequisite for reusability. What are some typical things we want to do when extending (modifying) an app for the context of a particular project? * Deal with authorization in the context of the particular django project * Styling for the project * Turn a subset of the functionality on or off for a given project (no docs, no 'advanced features') * Add one or more fields to one or more models and possibly related edit pages, view pages forms etc Given this control flow let's try to do some of the typical modifications mentioned above: Authorization: Django has a beautiful mechanism for authorization, which is using decorators (@may_do_a_b_or_c) directly in the views.py. Tempting, but will not be modifyable in any way once you lift the app. (because the decorator will become tied to the view function). Other mechanisms are not presented (in a standardized way). If anyone has ideas about this I'd love to discuss them. Styling: This actually works well, by providing sufficient amount of hooks in the templates and extending. Turning functionality on and off: This could be made to work by working with a 'url_parts.py' in the reusable app, that provides different url_patterns for the various subsets. So one for the CRUD, one for the docs, one for the simple features and one for the advanced features. Our project's urls.py would then simply include the right subset from this url_parts.py. I'm not sure it's very pretty though. Extending models This is the big one, for two reasons. 1. You almost always want to do this (for any change to the app that is reflected in the underlying data) 2. It's pretty much impossible. Why is it impossible? Firstly, /app/models.py is always discovered, so unless we make all Models abstract, or we do not include "app" in settings.py, models are created for syncdb and any related commands. Secondly, let's take a look at Django's control flow: * urls.py matches and calls, * possibly via a decorator * a view in views.py, that may use any number of * models, * forms and * templates The "official" way to modify a reusable app for your particular app is by making it available as a kwarg with proper default in the view, and then customizing it from urls.py. However, if you simply want to add one field to a much used object, this solution implies passing around the object class (factory) through your whole app. That's not very elegant. The same goes for any other changes at a lower level. Say I want to swap in a particular Form (not uncommon). Or reuse 90% of the views from an app, but replace 10% of the alltogether. If those 10% are referenced from {% url %} tags (or reverse in a view) we're screwed. By the way: where do modifications of apps go anyway? The reusable app already goes into /appname. So the modification (presuming it warrants a full directory) goes into /my_appname? If reusable apps are common, this means my projects look like this: /app_a /app_b /app_c /my_app_a /my_app_b /my_app_c Solutions: http://www.scribd.com/doc/37113340/Why-Django-Sucks-and-How-we-Can-Fix-it mentions using factories "everwhere". Too bad the actual speech cannot be heard at scribd because the slides are just a bit thin on details. settings.py In my humble opinion a good app adds no settings to settings.py. The problems with settings.py are mentioned in many places, suffice to say it's basically a big global. Also: we're programmers, not configurars. For the models problem specifically I came up with this about 7 months ago: https://bitbucket.org/vanschelven/superglue/ (very much proof of concept) Superglue works like this: For any reusable app that uses it, models are to be defined abstract. Then a magic method (glue) is to be called (from the apps models.py). This magic method looks at settings.py (meh) and possibly extends the model. At that point the extended, non-abstract model is made available for the rest of the app. I don't really like it yet, but it could be a start. Another possible way forward could be object oriented views, like here: http://djangosnippets.org/snippets/1009/ tl;dr * Django Apps Suck. Your reply explaining why they don't is expected. * Reuse of a lot of things doesn't suck. But the specific unit app, meaning a bunch of models that can be modified and presented with their model-specific features, is extremely hard to reuse. * Apps are mostly hard to reuse because they are hard to reuse with minor modifications (extensions). * Using decorators on views to define authorization levels ties in said authorization levels with the app (and makes it non-reusable) * The hardest things to change are at the bottom of Django's call chain. Deep inside the views, we find particular Models, Forms and references to other views. * Models are extra hard to change, because they are expected to be non- abstract in the app. * There is no logical separation (dir structure) between "a reusable app" and "my modifications to a reusable app". * Settings.py is not a solution (it is a problem), though I don't bother to explain why. * Some ideas for solutions exist, but this seems to be an open problem in the Django world. Correct me if I'm wrong. hope to hear from you, Klaas van Schelven -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-us...@googlegroups.com. To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.