From 0f40f3b757f51c5d1e006364291f89cc754b81bf Mon Sep 17 00:00:00 2001 From: Jacob Kaplan-Moss Date: Fri, 15 Jul 2005 15:31:20 +0000 Subject: [PATCH] More doc improvments: moved overview into doc system so it can be distributed with the package, and fixed a few spelling errors in templates doc (fixes #31). git-svn-id: http://code.djangoproject.com/svn/django/trunk@49 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/overview.txt | 308 +++++++++++++++++++++++++++++++++++++++++++++ docs/templates.txt | 7 +- 2 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 docs/overview.txt diff --git a/docs/overview.txt b/docs/overview.txt new file mode 100644 index 0000000000..2220c505c4 --- /dev/null +++ b/docs/overview.txt @@ -0,0 +1,308 @@ +=============== +Django overview +=============== + +Because Django was developed in a fast-paced newsroom environment, it was +designed to make common Web-development tasks fast and easy. Here's an informal +overview of how to write a database-driven Web app with Django. + +The goal of this document is to give you enough technical specifics to +understand how Django works, but this isn't intended to be a tutorial or +reference. Please see our more-detailed Django documentation_ when you're ready +to start a project. + +.. _documentation: http://www.djangoproject.com/documentation/ + +Design your model +================= + +Start by describing your database layout in Python code. Django's data-model API +offers many rich ways of representing your models — so far, it's been +solving two years' worth of database-schema problems. Here's a quick example:: + + class Reporter(meta.Model): + fields = ( + meta.CharField('full_name', "reporter's full name", maxlength=70), + ) + + def __repr__(self): + return self.full_name + + class Article(meta.Model): + fields = ( + meta.DateTimeField('pub_date', 'publication date'), + meta.CharField('headline', 'headline', maxlength=200), + meta.TextField('article', 'article'), + meta.ForeignKey(Reporter), + ) + + def __repr__(self): + return self.headline + +Install it +========== + +Next, run the Django command-line utility. It'll create the database tables for +you automatically, in the database specified in your Django settings. Django +works with PostgreSQL and MySQL, although other database adapters are on the +way:: + + django-admin.py install news + +Enjoy the free API +================== + +With that, you've got a free, and rich, Python API to access your data. The API +is created on the fly: No code generation necessary:: + + # Modules are dynamically created within django.models. + # Their names are plural versions of the model class names. + >>> from django.models.news import reporters, articles + + # No reporters are in the system yet. + >>> reporters.get_list() + [] + + # Create a new Reporter. + >>> r = reporters.Reporter(id=None, full_name='John Smith') + + # Save the object into the database. You have to call save() explicitly. + >>> r.save() + + # Now it has an ID. + >>> r.id + 1 + + # Now the new reporter is in the database. + >>> reporters.get_list() + [John Smith] + + # Fields are represented as attributes on the Python object. + >>> r.full_name + 'John Smith' + + # Django provides a rich database lookup API that's entirely driven by keyword arguments. + >>> reporters.get_object(id__exact=1) + John Smith + >>> reporters.get_object(full_name__startswith='John') + John Smith + >>> reporters.get_object(full_name__contains='mith') + John Smith + >>> reporters.get_object(id__exact=2) + Traceback (most recent call last): + ... + django.models.polls.ReporterDoesNotExist: Reporter does not exist for {'id__exact': 2} + + # Create an article. + >>> from datetime import datetime + >>> a = articles.Article(id=None, pub_date=datetime.now(), headline='Django is cool', article='Yeah.', reporter_id=1) + >>> a.save() + + # Now the article is in the database. + >>> articles.get_list() + [Django is cool] + + # Article objects get API access to related Reporter objects. + >>> r = a.get_reporter() + >>> r.full_name + 'John Smith' + + # And vice versa: Reporter objects get API access to Article objects. + >>> r.get_article_list() + [Django is cool] + + # The API follows relationships as far as you need. + # Find all articles by a reporter whose name starts with "John". + >>> articles.get_list(reporter__full_name__startswith="John") + [Django is cool] + + # Change an object by altering its attributes and calling save(). + >>> r.full_name = 'Billy Goat' + >>> r.save() + + # Delete an object with delete(). + >>> r.delete() + +A dynamic admin interface: It's not just scaffolding -- it's the whole house +============================================================================ + +Once your models are defined, Django can automatically create an administrative +interface — a Web site that lets authenticated users add, change and +delete objects. It's as easy as adding an extra admin attribute to your model +classes:: + + class Article(meta.Model): + fields = ( + meta.DateTimeField('pub_date', 'publication date'), + meta.CharField('headline', 'headline', maxlength=200), + meta.TextField('article', 'article'), + meta.ForeignKey(Reporter), + ) + admin = meta.Admin( + fields = ( + (None, {'fields': ('headline', 'article')}), + ('Extra stuff', {'fields': ('pub_date', 'reporter_id')}), + ), + ) + +The ``admin.fields`` defines the layout of your admin form. Each element in the +fields tuple corresponds to a ``
`` in the form. + +The philosophy here is that your site is edited by a staff, or a client, or +maybe just you -- and you don't want to have to deal with creating backend +interfaces just to manage content. + +Our typical workflow at World Online is to create models and get the admin sites +up and running as fast as possible, so our staff journalists can start +populating data. Then we develop the way data is presented to the public. + +Design your URLs + +A clean, elegant URL scheme is an important detail in a high-quality Web +application. Django lets you design URLs however you want, with no framework +limitations. + +To design URLs for an app, you create a Python module. For the above +Reporter/Article example, here's what that might look like:: + + from django.conf.urls.defaults import * + + urlpatterns = patterns('', + (r'^/articles/(?P\d{4})/$', 'myproject.news.views.articles.year_archive'), + (r'^/articles/(?P\d{4})/(?P\d{2})/$', 'myproject.news.views.articles.month_archive'), + (r'^/articles/(?P\d{4})/(?P\d{2})/$', 'myproject.news.views.articles.month_archive'), + (r'^/articles/(?P\d{4})/(?P\d{2})/(?P\d+)/$', 'myproject.news.views.articles.article_detail'), + ) + + +The code above maps URLs, as regular expressions, to the location of Python +callback functions (views). The regular expressions use parenthesis to "capture" +values from the URLs. When a user requests a page, Django runs through each +regular expression, in order, and stops at the first one that matches the +requested URL. (If none of them matches, Django calls a special 404 view.) This +is blazingly fast, because the regular expressions are compiled at load time. + +Once one of the regexes matches, Django imports and calls the given view, which +is a simple Python function. Each view gets passed a request object — +which contains request metadata and lets you access GET and POST data as simple +dictionaries — and the values captured in the regex, via keyword +arguments. + +For example, if a user requested the URL "/articles/2005/05/39323/", Django +would call the function ``myproject.news.views.articles.article_detail(request, +year='2005', month='05', article_id='39323')``. + +Write your views +================ + +Each view is responsible for doing one of two things: Returning an +``HttpResponse`` object containing the content for the requested page, or +raising an exception such as ``Http404``. The rest is up to you. + +Generally, a view retrieves data according to the parameters, loads a template +and renders the template with the retrieved data. Here's an example view for +article_detail from above:: + + from django.models.news import articles + + def article_detail(request, year, month, article_id): + # Use the Django API to find an object matching the URL criteria. + try: + a = articles.get_object(pub_date__year=year, pub_date__month=month, id__exact=article_id) + except articles.ArticleDoesNotExist: + raise Http404 + t = template_loader.get_template('news/article_detail') + c = Context(request, { + 'article': a, + }) + content = t.render(c) + return HttpResponse(content) + +This example uses Django's template system, which has several key features. + +Design your templates +===================== + +The code above loads the ``news/article_detail`` template. + +Django has a template search path, which allows you to minimize redundancy among +templates. In your Django settings, you specify a list of directories to check +for templates. If a template doesn't exist in the first directory, it checks the +second, and so on. + +Let's say the ``news/article_detail`` template was found. Here's what that might +look like:: + + {% extends "base" %} + + {% block title %}{{ article.headline }}{% endblock %} + + {% block content %} +

{{ article.headline }}

+

By {{ article.get_reporter.full_name }}

+

Published {{ article.pub_date|date:"F j, Y" }}

+ {{ article.article }} + {% endblock %} + + +It should look straightforward. Variables are surrounded by double-curly braces. +``{{ article.headline }}`` means "Output the value of the article's headline +attribute." But dots aren't used only for attribute lookup: They also can do +dictionary-key lookup, index lookup and function calls (as is the case with +``article.get_reporter``). + +Note ``{{ article.pub_date|date:"F j, Y" }}`` uses a Unix-style "pipe" (the "|" +character). This is called a template filter, and it's a way to filter the value +of a variable. In this case, the date filter formats a Python datetime object in +the given format (as found in PHP's date function; yes, there is one good idea +in PHP). + +You can chain together as many filters as you'd like. You can write custom +filters. You can write custom template tags, which run custom Python code behind +the scenes. + +Finally, Django uses the concept of template inheritance: That's what the ``{% +extends "base" %}`` does. It means "First load the template called 'base', which +has defined a bunch of blocks, and fill the blocks with the following blocks." +In short, that lets you dramatically cut down on redundancy in templates: Each +template has to define only what's unique to that template. + +Here's what the "base" template might look like:: + + + + + {% block title %} + + + Logo + {% block content %}{% endblock %} + + + +Simplistically, it defines the look-and-feel of the site (with the site's logo), +and provides "holes" for child templates to fill. This makes a site redesign as +easy as changing a single file — the base template. + +Note that you don't have to use Django's template system if you prefer another +system. While Django's template system is particularly well-integrated with +Django's model layer, nothing forces you to use it. For that matter, you don't +have to use Django's API, either. You can use another database abstraction +layer, you can read XML files, you can read files off disk, or anything you +want. Each piece of Django — models, views, templates — is decoupled +from the next. + +This is just the surface +======================== + +This has been only a quick overview of Django's functionality. Some more useful +features: + + * A caching framework that integrates with memcached or other backends. + * An RSS framework that makes creating RSS feeds as easy as writing a + small Python class. + * More sexy automatically-generated admin features — this overview barely + scratched the surface + +The next obvious steps are for you to download Django, read the documentation +and join the community. Thanks for your interest! \ No newline at end of file diff --git a/docs/templates.txt b/docs/templates.txt index 2239190086..671ad75123 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -21,7 +21,8 @@ To actually be useful, a template will contain **variables**, which get replaced with values from the database when the template is evaluated, and **tags**, which control the logic of the template. -Below is a minimal template that I'll be using to illustrate the parts of a template throughout this introduction:: +Below is a minimal template that I'll be using to illustrate the parts of a +template throughout this introduction:: {% extends base_generic %} @@ -47,7 +48,7 @@ Variables look like this: ``{{ variable }}``. When the template engine encounters a variable, it evaluates that variable and replaces the variable with the result. Many variables will be structures with named attributes; you can "drill down" into these structures with dots (``.``), so in the above example `` -{{ section.title }}`` will be replaces with the ``title`` attribute of the +{{ section.title }}`` will be replaced with the ``title`` attribute of the ``section`` object. If you use a variable that doesn't exist, it will be silently ignored; the @@ -61,7 +62,7 @@ Variables may be modified before being displayed by **filters**. What's a filter? ================ -Filters look like this: ``{{ name|lower }}``. This display the value of the +Filters look like this: ``{{ name|lower }}``. This displays the value of the ``{{ name }}`` variable after being filtered through the ``lower`` filter which, as you might have guessed, lowercases the text passed through it.