Design philosophies

This document explains some of the fundamental philosophies Django’s developershave used in creating the framework. Its goal is to explain the past and guidethe 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 unlessabsolutely necessary.

For example, the template system knows nothing about Web requests, the databaselayer knows nothing about data display and the view system doesn’t care whichtemplate system a programmer uses.

Although Django comes with a full stack for convenience, the pieces of thestack are independent of another wherever possible.

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 asintrospection.

Quick development

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

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 littleas possible.

See also

The discussion of DRY on the Portland Pattern Repository

Explicit is better than implicit

This is a core Python principle listed in PEP 20, and it means Djangoshouldn’t do too much “magic.” Magic shouldn’t happen unless there’s a reallygood reason for it. Magic is worth using only if it creates a huge convenienceunattainable in other ways, and it isn’t implemented in a way that confusesdevelopers who are trying to learn how to use the feature.

Consistency

The framework should be consistent at all levels. Consistency applies toeverything 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 thefield. 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, onthe type of the field.

Include all relevant domain logic

Models should encapsulate every aspect of an “object,” following MartinFowler’s Active Record design pattern.

This is why both the data represented by a model and information aboutit (its human-readable name, options like default ordering, etc.) aredefined in the model class; all the information needed to understand agiven 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 shouldoptimize statements internally.

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

This is also why the select_related() QuerySet method exists. It’s anoptional performance booster for the common case of selecting “every relatedobject.”

Terse, powerful syntax

The database API should allow rich, expressive statements in as little syntaxas 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. Thisaccess 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 anend-all-be-all. The framework should make it easy to write custom SQL – entirestatements, 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. TyingURLs to Python function names is a Bad And Ugly Thing.

Along these lines, the Django URL system should allow URLs for the same app tobe 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 beallowed.

Encourage best practices

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

File extensions in Web-page URLs should be avoided.

Vignette-style commas in URLs deserve severe punishment.

Definitive URLs

Technically, foo.com/bar and foo.com/bar/ are two different URLs, andsearch-engine robots (and some Web traffic-analyzing tools) would treat them asseparate pages. Django should make an effort to “normalize” URLs so thatsearch-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 andpresentation-related logic – and that’s it. The template system shouldn’tsupport functionality that goes beyond this basic goal.

Discourage redundancy

The majority of dynamic websites use some sort of common sitewide design –a common header, footer, navigation bar, etc. The Django template system shouldmake it easy to store those elements in a single place, eliminating duplicatecode.

This is the philosophy behind template inheritance.

Be decoupled from HTML

The template system shouldn’t be designed so that it only outputs HTML. Itshould be equally good at generating other text-based formats, or just plaintext.

XML should not be used for template languages

Using an XML engine to parse templates introduces a whole new world of humanerror in editing templates – and incurs an unacceptable level of overhead intemplate processing.

Assume designer competence

The template system shouldn’t be designed so that templates necessarily aredisplayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe ofa limitation and wouldn’t allow the syntax to be as nice as it is. Djangoexpects template authors are comfortable editing HTML directly.

Treat whitespace obviously

The template system shouldn’t do magic things with whitespace. If a templateincludes whitespace, the system should treat the whitespace as it treats text– just display it. Any whitespace that’s not in a template tag should bedisplayed.

Don’t invent a programming language

The goal is not to invent a programming language. The goal is to offer justenough programming-esque functionality, such as branching and looping, that isessential for making presentation-related decisions. The Django TemplateLanguage (DTL) aims to avoid advanced logic.

The Django template system recognizes that templates are most often written bydesigners, not programmers, and therefore should not assume Pythonknowledge.

Safety and security

The template system, out of the box, should forbid the inclusion of maliciouscode – 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 wantto 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. Developersshouldn’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 metadataabout the current request. The object should be passed directly to a viewfunction, rather than the view function having to access the request data froma global variable. This makes it light, clean and easy to test views by passingin “fake” request objects.

Loose coupling

A view shouldn’t care about which template system the developer uses – or evenwhether a template system is used at all.

Differentiate 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.

Cache Framework

The core goals of Django’s cache framework are:

Less code

A cache should be as fast as possible. Hence, all framework code surroundingthe cache backend should be kept to the absolute minimum, especially forget() operations.

Consistency

The cache API should provide a consistent interface across the differentcache backends.

Extensibility

The cache API should be extensible at the application level based on thedeveloper’s needs (for example, see Cache key transformation).