{"title":"Design philosophies","version":"dev","locale":"en","docname":"misc/design-philosophies","url":"/en/dev/misc/design-philosophies/","canonical":"https://djangodocs.dev/en/dev/misc/design-philosophies/","summary":"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…","html":"<h1>Design philosophies<a class=\"heading-anchor\" href=\"#design-philosophies\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>This document explains some of the fundamental philosophies Django’s developers\nhave used in creating the framework. Its goal is to explain the past and guide\nthe future.</p>\n<section id=\"overall\">\n<h2>Overall<a class=\"heading-anchor\" href=\"#overall\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"loose-coupling\">\n<span id=\"id1\"></span><h3>Loose coupling<a class=\"heading-anchor\" href=\"#loose-coupling\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p id=\"index-0\">A fundamental goal of Django’s stack is <a class=\"reference external\" href=\"https://wiki.c2.com/?CouplingAndCohesion\">loose coupling and tight cohesion</a>.\nThe various layers of the framework shouldn’t “know” about each other unless\nabsolutely necessary.</p>\n<p>For example, the template system knows nothing about web requests, the database\nlayer knows nothing about data display and the view system doesn’t care which\ntemplate system a programmer uses.</p>\n<p>Although Django comes with a full stack for convenience, the pieces of the\nstack are independent of another wherever possible.</p>\n</section>\n<section id=\"less-code\">\n<span id=\"id2\"></span><h3>Less code<a class=\"heading-anchor\" href=\"#less-code\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django apps should use as little code as possible; they should lack\nboilerplate. Django should take full advantage of Python’s dynamic\ncapabilities, such as introspection.</p>\n</section>\n<section id=\"quick-development\">\n<span id=\"id3\"></span><h3>Quick development<a class=\"heading-anchor\" href=\"#quick-development\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The point of a web framework in the 21st century is to make the tedious aspects\nof web development fast. Django should allow for incredibly quick web\ndevelopment.</p>\n</section>\n<section id=\"don-t-repeat-yourself-dry\">\n<span id=\"dry\"></span><h3>Don’t repeat yourself (DRY)<a class=\"heading-anchor\" href=\"#don-t-repeat-yourself-dry\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p id=\"index-1\">Every distinct concept and/or piece of data should live in one, and only one,\nplace. Redundancy is bad. Normalization is good.</p>\n<p>The framework, within reason, should deduce as much as possible from as little\nas possible.</p>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">See also</p>\n<p>The <a class=\"reference external\" href=\"https://wiki.c2.com/?DontRepeatYourself\">discussion of DRY on the Portland Pattern Repository</a></p>\n</aside>\n</section>\n<section id=\"explicit-is-better-than-implicit\">\n<span id=\"id5\"></span><h3>Explicit is better than implicit<a class=\"heading-anchor\" href=\"#explicit-is-better-than-implicit\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>This is a core Python principle listed in <span class=\"target\" id=\"index-2\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0020/\"><strong>PEP 20</strong></a>, and it means Django\nshouldn’t do too much “magic.” Magic shouldn’t happen unless there’s a really\ngood reason for it. Magic is worth using only if it creates a huge convenience\nunattainable in other ways, and it isn’t implemented in a way that confuses\ndevelopers who are trying to learn how to use the feature.</p>\n</section>\n<section id=\"consistency\">\n<span id=\"id6\"></span><h3>Consistency<a class=\"heading-anchor\" href=\"#consistency\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The framework should be consistent at all levels. Consistency applies to\neverything from low-level (the Python coding style used) to high-level (the\n“experience” of using Django).</p>\n</section>\n</section>\n<section id=\"models\">\n<h2>Models<a class=\"heading-anchor\" href=\"#models\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"id7\">\n<h3>Explicit is better than implicit<a class=\"heading-anchor\" href=\"#id7\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Fields shouldn’t assume certain behaviors based solely on the name of the\nfield. This requires too much knowledge of the system and is prone to errors.\nInstead, behaviors should be based on keyword arguments and, in some cases, on\nthe type of the field.</p>\n</section>\n<section id=\"include-all-relevant-domain-logic\">\n<h3>Include all relevant domain logic<a class=\"heading-anchor\" href=\"#include-all-relevant-domain-logic\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Models should encapsulate every aspect of an “object,” following Martin\nFowler’s <a class=\"reference external\" href=\"https://www.martinfowler.com/eaaCatalog/activeRecord.html\">Active Record</a> design pattern.</p>\n<p>This is why both the data represented by a model and information about\nit (its human-readable name, options like default ordering, etc.) are\ndefined in the model class; all the information needed to understand a\ngiven model should be stored <em>in</em> the model.</p>\n</section>\n</section>\n<section id=\"database-api\">\n<h2>Database API<a class=\"heading-anchor\" href=\"#database-api\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The core goals of the database API are:</p>\n<section id=\"sql-efficiency\">\n<h3>SQL efficiency<a class=\"heading-anchor\" href=\"#sql-efficiency\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>It should execute SQL statements as few times as possible, and it should\noptimize statements internally.</p>\n<p>This is why developers need to call <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> explicitly, rather than the\nframework saving things behind the scenes silently.</p>\n<p>This is also why the <code class=\"docutils literal notranslate\"><span class=\"pre\">FETCH_PEERS</span></code> <a class=\"reference internal\" href=\"/en/dev/topics/db/fetch-modes/\"><span class=\"doc\">fetch mode</span></a>\nexists. It’s an optional performance booster for the common case of selecting\nrelated objects for every peer in a <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code>.</p>\n</section>\n<section id=\"terse-powerful-syntax\">\n<h3>Terse, powerful syntax<a class=\"heading-anchor\" href=\"#terse-powerful-syntax\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The database API should allow rich, expressive statements in as little syntax\nas possible. It should not rely on importing other modules or helper objects.</p>\n<p>Joins should be performed automatically, behind the scenes, when necessary.</p>\n<p>Every object should be able to access every related object, systemwide. This\naccess should work both ways.</p>\n</section>\n<section id=\"option-to-drop-into-raw-sql-easily-when-needed\">\n<h3>Option to drop into raw SQL easily, when needed<a class=\"heading-anchor\" href=\"#option-to-drop-into-raw-sql-easily-when-needed\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The database API should realize it’s a shortcut but not necessarily an\nend-all-be-all. The framework should make it easy to write custom SQL – entire\nstatements, or just custom <code class=\"docutils literal notranslate\"><span class=\"pre\">WHERE</span></code> clauses as custom parameters to API calls.</p>\n</section>\n</section>\n<section id=\"url-design\">\n<h2>URL design<a class=\"heading-anchor\" href=\"#url-design\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"id8\">\n<h3>Loose coupling<a class=\"heading-anchor\" href=\"#id8\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>URLs in a Django app should not be coupled to the underlying Python code. Tying\nURLs to Python function names is a Bad And Ugly Thing.</p>\n<p>Along these lines, the Django URL system should allow URLs for the same app to\nbe different in different contexts. For example, one site may put stories at\n<code class=\"docutils literal notranslate\"><span class=\"pre\">/stories/</span></code>, while another may use <code class=\"docutils literal notranslate\"><span class=\"pre\">/news/</span></code>.</p>\n</section>\n<section id=\"infinite-flexibility\">\n<h3>Infinite flexibility<a class=\"heading-anchor\" href=\"#infinite-flexibility\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>URLs should be as flexible as possible. Any conceivable URL design should be\nallowed.</p>\n</section>\n<section id=\"encourage-best-practices\">\n<h3>Encourage best practices<a class=\"heading-anchor\" href=\"#encourage-best-practices\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The framework should make it just as easy (or even easier) for a developer to\ndesign pretty URLs than ugly ones.</p>\n<p>File extensions in web-page URLs should be avoided.</p>\n<p>Vignette-style commas in URLs deserve severe punishment.</p>\n</section>\n<section id=\"definitive-urls\">\n<span id=\"id9\"></span><h3>Definitive URLs<a class=\"heading-anchor\" href=\"#definitive-urls\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p id=\"index-3\">Technically, <code class=\"docutils literal notranslate\"><span class=\"pre\">foo.com/bar</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">foo.com/bar/</span></code> are two different URLs, and\nsearch-engine robots (and some web traffic-analyzing tools) would treat them as\nseparate pages. Django should make an effort to “normalize” URLs so that\nsearch-engine robots don’t get confused.</p>\n<p>This is the reasoning behind the <a class=\"reference internal\" href=\"/en/dev/ref/settings/#std-setting-APPEND_SLASH\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">APPEND_SLASH</span></code></a> setting.</p>\n</section>\n</section>\n<section id=\"template-system\">\n<h2>Template system<a class=\"heading-anchor\" href=\"#template-system\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"separate-logic-from-presentation\">\n<span id=\"separation-of-logic-and-presentation\"></span><h3>Separate logic from presentation<a class=\"heading-anchor\" href=\"#separate-logic-from-presentation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>We see a template system as a tool that controls presentation and\npresentation-related logic – and that’s it. The template system shouldn’t\nsupport functionality that goes beyond this basic goal.</p>\n</section>\n<section id=\"discourage-redundancy\">\n<h3>Discourage redundancy<a class=\"heading-anchor\" href=\"#discourage-redundancy\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The majority of dynamic websites use some sort of common sitewide design –\na common header, footer, navigation bar, etc. The Django template system should\nmake it easy to store those elements in a single place, eliminating duplicate\ncode.</p>\n<p>This is the philosophy behind <a class=\"reference internal\" href=\"/en/dev/ref/templates/language/#template-inheritance\"><span class=\"std std-ref\">template inheritance</span></a>.</p>\n</section>\n<section id=\"be-decoupled-from-html\">\n<h3>Be decoupled from HTML<a class=\"heading-anchor\" href=\"#be-decoupled-from-html\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The template system shouldn’t be designed so that it only outputs HTML. It\nshould be equally good at generating other text-based formats, or just plain\ntext.</p>\n</section>\n<section id=\"xml-should-not-be-used-for-template-languages\">\n<h3>XML should not be used for template languages<a class=\"heading-anchor\" href=\"#xml-should-not-be-used-for-template-languages\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p id=\"index-4\">Using an XML engine to parse templates introduces a whole new world of human\nerror in editing templates – and incurs an unacceptable level of overhead in\ntemplate processing.</p>\n</section>\n<section id=\"assume-designer-competence\">\n<h3>Assume designer competence<a class=\"heading-anchor\" href=\"#assume-designer-competence\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The template system shouldn’t be designed so that templates necessarily are\ndisplayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of\na limitation and wouldn’t allow the syntax to be as nice as it is. Django\nexpects template authors are comfortable editing HTML directly.</p>\n</section>\n<section id=\"treat-whitespace-obviously\">\n<h3>Treat whitespace obviously<a class=\"heading-anchor\" href=\"#treat-whitespace-obviously\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The template system shouldn’t do magic things with whitespace. If a template\nincludes whitespace, the system should treat the whitespace as it treats text\n– just display it. Any whitespace that’s not in a template tag should be\ndisplayed.</p>\n</section>\n<section id=\"don-t-invent-a-programming-language\">\n<h3>Don’t invent a programming language<a class=\"heading-anchor\" href=\"#don-t-invent-a-programming-language\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The goal is not to invent a programming language. The goal is to offer just\nenough programming-esque functionality, such as branching and looping, that is\nessential for making presentation-related decisions. The <a class=\"reference internal\" href=\"/en/dev/topics/templates/#template-language-intro\"><span class=\"std std-ref\">Django Template\nLanguage (DTL)</span></a> aims to avoid advanced logic.</p>\n</section>\n<section id=\"safety-and-security\">\n<h3>Safety and security<a class=\"heading-anchor\" href=\"#safety-and-security\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The template system, out of the box, should forbid the inclusion of malicious\ncode – such as commands that delete database records.</p>\n<p>This is another reason the template system doesn’t allow arbitrary Python code.</p>\n</section>\n<section id=\"extensibility\">\n<h3>Extensibility<a class=\"heading-anchor\" href=\"#extensibility\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The template system should recognize that advanced template authors may want\nto extend its technology.</p>\n<p>This is the philosophy behind custom template tags and filters.</p>\n</section>\n</section>\n<section id=\"views\">\n<h2>Views<a class=\"heading-anchor\" href=\"#views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"simplicity\">\n<h3>Simplicity<a class=\"heading-anchor\" href=\"#simplicity\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Writing a view should be as simple as writing a Python function. Developers\nshouldn’t have to instantiate a class when a function will do.</p>\n</section>\n<section id=\"use-request-objects\">\n<h3>Use request objects<a class=\"heading-anchor\" href=\"#use-request-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Views should have access to a request object – an object that stores metadata\nabout the current request. The object should be passed directly to a view\nfunction, rather than the view function having to access the request data from\na global variable. This makes it light, clean and easy to test views by passing\nin “fake” request objects.</p>\n</section>\n<section id=\"id10\">\n<h3>Loose coupling<a class=\"heading-anchor\" href=\"#id10\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A view shouldn’t care about which template system the developer uses – or even\nwhether a template system is used at all.</p>\n</section>\n<section id=\"differentiate-between-get-and-post\">\n<h3>Differentiate between GET and POST<a class=\"heading-anchor\" href=\"#differentiate-between-get-and-post\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>GET and POST are distinct; developers should explicitly use one or the other.\nThe framework should make it easy to distinguish between GET and POST data.</p>\n</section>\n</section>\n<section id=\"cache-framework\">\n<span id=\"cache-design-philosophy\"></span><h2>Cache Framework<a class=\"heading-anchor\" href=\"#cache-framework\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The core goals of Django’s <a class=\"reference internal\" href=\"/en/dev/topics/cache/\"><span class=\"doc\">cache framework</span></a> are:</p>\n<section id=\"id11\">\n<h3>Less code<a class=\"heading-anchor\" href=\"#id11\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A cache should be as fast as possible. Hence, all framework code surrounding\nthe cache backend should be kept to the absolute minimum, especially for\n<code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> operations.</p>\n</section>\n<section id=\"id12\">\n<h3>Consistency<a class=\"heading-anchor\" href=\"#id12\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The cache API should provide a consistent interface across the different\ncache backends.</p>\n</section>\n<section id=\"id13\">\n<h3>Extensibility<a class=\"heading-anchor\" href=\"#id13\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The cache API should be extensible at the application level based on the\ndeveloper’s needs (for example, see <a class=\"reference internal\" href=\"/en/dev/topics/cache/#cache-key-transformation\"><span class=\"std std-ref\">Cache key transformation</span></a>).</p>\n</section>\n</section>","rootId":"design-philosophies","toc":[{"title":"Overall","anchor":"overall","children":[{"title":"Loose coupling","anchor":"loose-coupling","children":[]},{"title":"Less code","anchor":"less-code","children":[]},{"title":"Quick development","anchor":"quick-development","children":[]},{"title":"Don’t repeat yourself (DRY)","anchor":"don-t-repeat-yourself-dry","children":[]},{"title":"Explicit is better than implicit","anchor":"explicit-is-better-than-implicit","children":[]},{"title":"Consistency","anchor":"consistency","children":[]}]},{"title":"Models","anchor":"models","children":[{"title":"Explicit is better than implicit","anchor":"id7","children":[]},{"title":"Include all relevant domain logic","anchor":"include-all-relevant-domain-logic","children":[]}]},{"title":"Database API","anchor":"database-api","children":[{"title":"SQL efficiency","anchor":"sql-efficiency","children":[]},{"title":"Terse, powerful syntax","anchor":"terse-powerful-syntax","children":[]},{"title":"Option to drop into raw SQL easily, when needed","anchor":"option-to-drop-into-raw-sql-easily-when-needed","children":[]}]},{"title":"URL design","anchor":"url-design","children":[{"title":"Loose coupling","anchor":"id8","children":[]},{"title":"Infinite flexibility","anchor":"infinite-flexibility","children":[]},{"title":"Encourage best practices","anchor":"encourage-best-practices","children":[]},{"title":"Definitive URLs","anchor":"definitive-urls","children":[]}]},{"title":"Template system","anchor":"template-system","children":[{"title":"Separate logic from presentation","anchor":"separate-logic-from-presentation","children":[]},{"title":"Discourage redundancy","anchor":"discourage-redundancy","children":[]},{"title":"Be decoupled from HTML","anchor":"be-decoupled-from-html","children":[]},{"title":"XML should not be used for template languages","anchor":"xml-should-not-be-used-for-template-languages","children":[]},{"title":"Assume designer competence","anchor":"assume-designer-competence","children":[]},{"title":"Treat whitespace obviously","anchor":"treat-whitespace-obviously","children":[]},{"title":"Don’t invent a programming language","anchor":"don-t-invent-a-programming-language","children":[]},{"title":"Safety and security","anchor":"safety-and-security","children":[]},{"title":"Extensibility","anchor":"extensibility","children":[]}]},{"title":"Views","anchor":"views","children":[{"title":"Simplicity","anchor":"simplicity","children":[]},{"title":"Use request objects","anchor":"use-request-objects","children":[]},{"title":"Loose coupling","anchor":"id10","children":[]},{"title":"Differentiate between GET and POST","anchor":"differentiate-between-get-and-post","children":[]}]},{"title":"Cache Framework","anchor":"cache-framework","children":[{"title":"Less code","anchor":"id11","children":[]},{"title":"Consistency","anchor":"id12","children":[]},{"title":"Extensibility","anchor":"id13","children":[]}]}],"breadcrumbs":[{"docname":"misc/index","title":"Meta-documentation and miscellany","url":"/en/dev/misc/"}],"prev":{"docname":"misc/api-stability","title":"API stability","url":"/en/dev/misc/api-stability/"},"next":{"docname":"misc/distributions","title":"Third-party distributions of Django","url":"/en/dev/misc/distributions/"},"formats":{"html":"/en/dev/misc/design-philosophies/","markdown":"/en/dev/misc/design-philosophies.md","json":"/en/dev/misc/design-philosophies.json"},"source":"https://github.com/django/django/blob/main/docs/misc/design-philosophies.txt","official":"https://docs.djangoproject.com/en/dev/misc/design-philosophies/","inVersions":["dev","6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9","1.8"],"inLocales":["en"]}