#

## Django documentation

# Design philosophies

This document explains some of the fundamental philosophies Django's developers have used in creating the framework. Its goal is to explain the past and guide the future.

## Overall

### Loose coupling

A fundamental goal of Django's stack is loose coupling and tight cohesion. The various layers of the framework shouldn't "know" about each other unless absolutely necessary.

For example, the template system knows nothing about Web requests, the database layer knows nothing about data display and the view system doesn't care which template system a programmer uses.

### Less code

Django apps should use as little code as possible; they should lack boilerplate. Django should take full advantage of Python's dynamic capabilities, such as introspection.

### Quick development

The point of a Web framework in the 21st century is to make the tedious aspects of Web development fast. Django should allow for incredibly quick Web development.

### Don't repeat yourself (DRY)

Every distinct concept and/or piece of data should live in one, and only one, place. Redundancy is bad. Normalization is good.

The framework, within reason, should deduce as much as possible from as little as possible.

### Explicit is better than implicit

This, a core Python principle, means Django shouldn't do too much "magic." Magic shouldn't happen unless there's a really good reason for it.

### Consistency

The framework should be consistent at all levels. Consistency applies to everything from low-level (the Python coding style used) to high-level (the "experience" of using Django).

## Models

### Explicit is better than implicit

Fields shouldn't assume certain behaviors based solely on the name of the field. This requires too much knowledge of the system and is prone to errors. Instead, behaviors should be based on keyword arguments and, in some cases, on the type of the field.

### Include all relevant domain logic

Models should encapsulate every aspect of an "object," following Martin Fowler's Active Record design pattern.

This is why model-specific admin options are included in the model itself; data related to a model should be stored in the model.

## Database API

The core goals of the database API are:

### SQL efficiency

It should execute SQL statements as few times as possible, and it should optimize statements internally.

This is why developers need to call `save()` explicitly, rather than the framework saving things behind the scenes silently.

This is also why the `select_related` argument exists. It's an optional performance booster for the common case of selecting "every related object."

### Terse, powerful syntax

The database API should allow rich, expressive statements in as little syntax as possible. It should not rely on importing other modules or helper objects.

Joins should be performed automatically, behind the scenes, when necessary.

Every object should be able to access every related object, systemwide. This access should work both ways.

### Option to drop into raw SQL easily, when needed

The database API should realize it's a shortcut but not necessarily an end-all-be-all. The framework should make it easy to write custom SQL -- entire statements, or just custom `WHERE` clauses as custom parameters to API calls.

## URL design

### Loose coupling

URLs in a Django app should not be coupled to the underlying Python code. Tying URLs to Python function names is a Bad And Ugly Thing.

Along these lines, the Django URL system should allow URLs for the same app to be different in different contexts. For example, one site may put stories at `/stories/`, while another may use `/news/`.

### Infinite flexibility

URLs should be as flexible as possible. Any conceivable URL design should be allowed.

### Encourage best practices

The framework should make it just as easy (or even easier) for a developer to design pretty URLs than ugly ones.

File extensions in Web-page URLs should be avoided.

### Definitive URLs

Technically, `foo.com/bar` and `foo.com/bar/` are two different URLs, and search-engine robots (and some Web traffic-analyzing tools) would treat them as separate pages. Django should make an effort to "normalize" URLs so that search-engine robots don't get confused.

This is the reasoning behind the `APPEND_SLASH` setting.

## Template system

### Separate logic from presentation

We see a template system as a tool that controls presentation and presentation-related logic -- and that's it. The template system shouldn't support functionality that goes beyond this basic goal.

If we wanted to put everything in templates, we'd be using PHP. Been there, done that, wised up.

### Discourage redundancy

The majority of dynamic Web sites use some sort of common sitewide design -- a common header, footer, navigation bar, etc. The Django template system should make it easy to store those elements in a single place, eliminating duplicate code.

This is the philosophy behind template inheritance.

### Be decoupled from HTML

The template system shouldn't be designed so that it only outputs HTML. It should be equally good at generating other text-based formats, or just plain text.

### Assume designer competence

The template system shouldn't be designed so that templates necessarily are displayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of a limitation and wouldn't allow the syntax to be as nice as it is. Django expects template authors are comfortable editing HTML directly.

### Treat whitespace obviously

The template system shouldn't do magic things with whitespace. If a template includes whitespace, the system should treat the whitespace as it treats text -- just display it. Any whitespace that's not in a template tag should be displayed.

### Don't invent a programming language

The template system intentionally doesn't allow the following:

> - Assignment to variables
> - Advanced logic

The goal is not to invent a programming language. The goal is to offer just enough programming-esque functionality, such as branching and looping, that is essential for making presentation-related decisions.

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

### Safety and security

The template system, out of the box, should forbid the inclusion of malicious code -- such as commands that delete database records.

This is another reason the template system doesn't allow arbitrary Python code.

### Extensibility

The template system should recognize that advanced template authors may want to extend its technology.

This is the philosophy behind custom template tags and filters.

## Views

### Simplicity

Writing a view should be as simple as writing a Python function. Developers shouldn't have to instantiate a class when a function will do.

### Use request objects

Views should have access to a request object -- an object that stores metadata about the current request. The object should be passed directly to a view function, rather than the view function having to access the request data from a global variable. This makes it light, clean and easy to test views by passing in "fake" request objects.

### Loose coupling

A view shouldn't care about which template system the developer uses -- or even whether a template system is used at all.

### Designate between GET and POST

GET and POST are distinct; developers should explicitly use one or the other. The framework should make it easy to distinguish between GET and POST data.

## Comments

### rezzrovv October 14, 2005 at 11:49 a.m.

One of the things I appreciate is the fact that you haven't felt the need to wrap EVERYTHING in a class but that where a simple "utility" function will suffice, you supply one.

### rjwittams October 14, 2005 at 7:26 p.m.

Not sure about the whitespace treatment being 'obvious'.

The thing is that as good pythonistas, we like to indent control structures : ie conditionals and loops. In the template system, the indentation and the newlines are preserved and in the case of loops is duplicated on output.

This can lead to a huge amount of unwanted and unexpected whitespace in template output, especially with nested loops.
Once the user knows this, it leads him to cut out indentation whitespace and newlines, often reducing readability of the template.

So I'm not convinced that we can say that 'obvious' whitespace treatment is currently a feature of the template system.

### Adrian Holovaty October 14, 2005 at 11:58 p.m.

rjwittams: You're entitled to your opinion. :)

### rjwittams October 15, 2005 at 9:58 a.m.

Erm, could you address the content of the comment? I'm saying that the design philosophy is unfulfilled. I'd love to know how you think that the current treatment is 'obvious'....

### Eric Moritz October 18, 2005 at 7:31 a.m.

I'll have to agree with rj here, so many times we have to put for's and if's on the same line to reduce extra whitespace in the output of html, which tends to put a space when it's on wanted. Most of the time, we don't have to worry about the extra whitespace, but sometimes, it's a nuicence.

For instance if we are outputting a list of data seperated by a comma: "item1, item2, item3 and item4" if that list is generated with a for loop, we would need an if statement to determine if the comma should be displayed or the "and" should be displayed. If we want the template to look readable, we'd have end lines after the for tag, after the if tag and tabs all over the place.
Something simular to

{% for item in myLish %}
{{ item }}
{% if forloop.last %}
and
{% else %}
,
{% endif %}
{% endfor %}

This would cause the list to look like this in html, "item1 , item2 , item3 and item4". However to get the desired html output we would have to write the same as:

{% for item in myLish %}{{ item }}{% if forloop.last %}and{% else %},{% endif %}{% endfor %}

Again, this is a rare case and I wouldn't recommend rewriting the templating system to remove all but I've seen many web based scripting languages have a mechanism to reduce the amount of whitespace that is produced. Perhaps a template tag that could be wrapped around a block of code that would remove the exceess whitespace could be provided if that is possible.

### Bjørn Stabell October 26, 2005 at 5:17 a.m.

It'd be nice if you could run fully automatic, like Ruby, which the class META generated from introspection into the database. A lot of the "wow" effect Ruby gets (= more publicity = more developers = more successful longer term) is because of the extreme ease of getting a working program up and running. Django isn't as easy yet, partly because of the (ugly) class META, but could if some more defaults + conventions were allowed.

I'm not saying most real programs don't need more model knowledge than database introspection can provide, but it does lower the learning curve and makes for an impressive demo. (A demo is another important PR thing Django is missing, AFAIK.)

### Adrian Holovaty October 26, 2005 at 8:05 a.m.

Bjørn: See the "django-admin.py inspectdb" command, which introspects the database to create a model. There are no plans to have Django introspect on the fly. Our philosophy is that the model (in Python code) is the definitive place to store all model logic.

Personally I think it's a design smell that a foreign-key relationship in Ruby on Rails needs to be defined in two places (both members of the relationship). Talk about a DRY violation!

And demos are coming. :-)

## Post a comment

Note: Please only use the comments for questions/critcisms/suggestions on the docs; if you experience errors please file a ticket, ask in the IRC channel, or post to the django-users list. Comments will be periodically reviewed, integrated into the documentation proper, and removed.

Your name:

Comment: