Django in a Nutshell
                            Python User Group München - µPy
                                   6. November 2012

                            juergen.schackmann@gmail.com




© Juergen Schackmann 2012
Ziel

 ▸    Überblick über Django
 ▸    Besprechung wesentlicher Komponenten
 ▸    Customizing Möglichkeiten
 ▸    Django Ökosystem
 ▸    Bewertung


 ▸    Kein Django Tutorial
 ▸    Kein hands-on workshop (gerne als separater Termin)




© Juergen Schackmann 2012                                   2/69
Agenda

 ▸    Übersicht
 ▸    Quick Start
 ▸    Project und (pluggable) Apps
 ▸    Wesentlich Django Komponenten
 ▸    Admin
 ▸    Settings
 ▸    Room for Improvement




© Juergen Schackmann 2012             3/69
Übersicht
Was ist Django (nicht)

 ▸   Web application Framework
 ▸   Pure Python
 ▸   Full-Stack (keine bzw. kaum externe dependencies)
 ▸   Philosophie:
      ▸   Dry
      ▸   Loose Coupling
      ▸   MVC bzw. MVT
 ▸   BSD Lizenz
 ▸   Django Software Foundation
 ▸   Sehr gute Dokumentation und große freundliche Community
 ▸   Django ist kein Content Management System (aber es gibt in Django implementierte
     CMS)


     Quellen: django-workshop.de/einfuehrung.html, djangobook.com/en/2.0/chapter01.html



© Juergen Schackmann 2012                                                                 5/69
Historie

 ▸   Entstanden 2003/2004 bei lawrence.com (Medienunternehmen, Zeitung) als
     closed source in Kansas (ebenso wie memcache)
 ▸   Benannt nach Django Reinhardt (Jazz Guitarist)
 ▸   Open Source: 2005
 ▸   “Benevolent Dictators for Life”: Jacob Kaplan-Moss, Adrian Holovaty
 ▸   Ursprung aus der Medienindustrie hat die Use Cases und Sweet Spots
     geprägt
 ▸   Aktuelle stabile Version: 1.4.2
 ▸   Version 1.5 bringt Python 3 Unterstützung
 ▸   Minor Release alle 9 Monate


Quellen:
http://www.quora.com/What-is-the-history-of-the-Django-web-framework,http://www.djangobook.com/en/2.0/chapter01.html


© Juergen Schackmann 2012                                                                                              6/69
Django Ressourcen

 ▸    Homepage: djangoproject.com
 ▸    Docs: docs.djangoproject.com/en/1.4/
 ▸    Code: github.com/django/django
 ▸    User Mailing List: groups.google.com/forum/?fromgroups#!forum/django-
      users
 ▸    Django App Ökosystem: djangopackages.com
 ▸    Django powered Websites: djangosites.org
 ▸    Django Snipptes: djangosnippets.org




© Juergen Schackmann 2012                                                7/69
Bücher, Tutorials, Trainings, ...

 ▸   Tutorial: docs.djangoproject.com/en/1.4/intro/tutorial01/


 ▸   Django Workshop (deutsch): django-workshop.de


 ▸   Django Book: djangobook.com/en/2.0/index.html


 ▸   amazon.de/Pro-Django-Experts-Voice-
     Development/dp/1430210478


 ▸   amazon.de/Python-Development-Django-Developers-
     Library/dp/0132356139

© Juergen Schackmann 2012                                        8/69
Videos


 ▸    Serie von Django Video Tutorials (für Anfänger):
      hackedexistence.com/project-django.html
 ▸    Video: Django Blog in 30 min (für Fortschreitende):
      http://arunrocks.com/blog/2012/03/05/building_a_bl
      og_in_30_mins_with_django_%28screencast%2
 ▸    Django in Depth, sehr gute 3h presentation (nichts
      für Anfänger): youtube.com/watch?v=t_ziKY1ayCo




© Juergen Schackmann 2012                                  9/69
Bekannte Django Sites

   pinterest.com

                                                       bitbucket.org




                                                  disqus.com
                            instagram.com
      nytimes.com




                              turnkeylinux.org
 washingtonpost.com


                                                 ubuntuusers.de



© Juergen Schackmann 2012                                              10/69
Quick-Start
Quick Start

 1. Django Installation


 2. Projekt erzeugen


 3. Development Web Server starten


 4. App(s) erzeugen


 5. Datenbank Schema erzeugen




© Juergen Schackmann 2012            12/69
Installation

 >>> pip install django


==> Done :-)


 ▸    7,7 MB download vom PyPi
 ▸    keine weiteren Dependencies
 ▸    Tip: am besten Installation in ein Virtualenv




© Juergen Schackmann 2012                             13/69
Projekt erzeugen

Django kommt mit Kommandozeilen Tool zur Erzeugung und Verwaltung von
Projekten und Apps
 >>> django-admin startproject nutshell
 >>> cd nutshell



Erzeugt die komplette Verzeichnisstruktur mit allen relevanten Daten für ein
Django Projekt
 nutshell/
      manage.py                    << Tool zur Verwaltung dieses Projekts
      nutshell/                    << Verzeichnis mit Code & Settings für dieses Projekt
           __init__.py
           settings.py             << Konfigurations File
           urls.py                 << Url Konfiguration
           wsgi.py                 << WSGI Applikation




© Juergen Schackmann 2012                                                                  14/69
Django Webserver starten


Starten des Django Webservers
 >>> python manage.py runserver




Und Aufruf unter http://127.0.0.1:8000/


Achtung: Django Webserver nur für Entwicklung nutzen, nicht für Produktion
vorgesehen




© Juergen Schackmann 2012                                               15/69
App(s) erzeugen

Jedes Django Projekt besteht aus mindestens einer App (in der Regel aber aus
sehr vielen Apps)
 >>> python manage.py startapp nuts



Erzeugt die komplette Verzeichnisstruktur mit allen relevanten Dateien für
eine Django App
 nutshell/                       << Root
      nutshell/                  << Project
      nuts/                      << App Verzeichnis
            __init__.py
            models..py           << App Models
            tests.py             << Unit Tests
            views.py             << Views (=Controllers)



Achtung: Apps müssen nicht im Project Verzeichns liegen, Python Path reicht
aus

© Juergen Schackmann 2012                                                    16/69
Datenbank Schema erzeugen



Generierung des Datenbank Schemas
 >>> python manage.py syncdb




Achtung: zuerst muss in settings.py die Datenbank/ Datenbankverbindung
eingetragen werden (am besten SQLite)




© Juergen Schackmann 2012                                                17/69
Notwendige nächste Schritte

 ▸    Anpassung settings.py
       ▸   Eintrag der Datenbank
       ▸   Hinzufügen gewünschter Apps



      ==> Happy Coding




© Juergen Schackmann 2012                18/69
Project und (pluggable) Apps
Apps im Project (Idealfall)



                    App 1            App 2        App 3          App 4




                     Konfiguration       URL Routing      Presentation
                      Settings.py          urls.py         Templates




 ▸    Project definiert sich über settings.py, urls.py und Templates (Verzeichnis)
 ▸    Project besteht aus unabhängigen Apps
 ▸    Apps müssen nichts übereinander wissen

© Juergen Schackmann 2012                                                      20/69
Pluggable Apps

 ▸     Jede App sollte
        ▸     genau eine Aufgabe sehr gut erledigen
        ▸     eigenständig funktionieren (ohne Wissen über andere Apps)
        ▸     möglichst weit konfigurierbar sein
        ▸     idealer Weise mit eigener setup.py und upload zu pypi
 ▸     Beispiele für gute Apps
        ▸     Tagging
        ▸     Themes/Skins
        ▸     Comments
 ▸     Beispiele for schlechte App:
       “Handle entries in a weblog, and users who post them, and their authentication, and
       tagging and categorization, and some flat pages for static content, and...
 ▸     Übersicht Django Apps: djangopackages.com
Quellen: http://media.b-list.org/presentations/2008/djangocon/reusable_apps.pdf, http://www.slideshare.net/coordt/pluggable-django-application-patterns-pycon-2011




© Juergen Schackmann 2012                                                                                                                                            21/69
Typisches Project Verzeichnis

 ▸    Default Einstellung sind Best Practice für kleinere bis mittlere Projekte
 ▸    Wording ist Konvention und beliebig anpassbar
 ▸    Verzeichnisstruktur mein persönlicher Vorschlag und beliebig anpassbar
 ▸    Konvention und Struktur wird in settings.py definiert


 nutshell/                  << Project Root
      manage.py             << Tool zur Verwaltung dieses Projects(automatisch erzeugt)
      site_static/          << Statische Files (wird während Deployment gefüllt)
      media/                << Media Files (upload files, wird während Nutzung gefüllt)
      nutshell/             << Verzeichnis mit Code & Settings für dieses Projekt
            __init__.py
            settings.py     << Konfigurations File (automatisch erzeugt und erweitert))
            urls.py         << Url Konfiguration (automatisch erzeugt und erweitert)
            wsgi.py         << WSGI Applikation(automatisch erzeugt)
            templates/      << Projektspezifische Templates (überschreiben App Templates)
            fixtures/       << Projektspezifische Fixtures(überschreiben App Fixtures)




© Juergen Schackmann 2012                                                                   22/69
Typisches App Verzeichnis

 ▸    All apps müssen als Package im Python Path auffindbar sein
 ▸    models.py ist die einzige Anforderung von Django, kann aber auch leer sein
 ▸    Wording für "templatetags" und "commands" ist fix
 nuts/                      << App Verzeichnis
         __init__.py
         settings.py        << App spezifische Settings / Konfiguration
         models.py          << App Models
         tests.py           << Unit Tests
         forms.py           << Django Formulare
         admin.py           << Admin (Admin Seiten für ausgewählte Models)
         views.py           << Views (=Controllers)
         urls.py            << Urls Conf (Url mapping auf App Views)
         templatetags/      << Custom templatetags
         command/           << Zusätzliche manage.py. commands
         templates/         << App Templates (durch Project Templates überschreibbar)
         static/            << Statische App files (durch statische Project files überschreibbar)
         fixtures/          << App Fixtures




© Juergen Schackmann 2012                                                                           23/69
Typische Django App Liste (settings.py)

 INSTALLED_APPS = (
   'django.contrib.auth',           << User Management, Authentifizierung, Autorisierung
   'django.contrib.contenttypes',   << Dependency für folgende
   'django.contrib.sessions',       << Session Management
   'django.contrib.sites',          << Betreiben mehrere Sites aus einem Projekt
   'django.contrib.messages',       << Messages im Browser
   'django.contrib.staticfiles',    << Statische files für Entwicklung und Deployment
   'django.contrib.admin',          << Admin für alle apps (sehr nützlich)
   'south',                         << Datenschema Migration
   'debug_toolbar'                  << Debug Toolbar im Browser (für Entwicklung)
   'nuts1',                         << Custom App
   'nuts2',                         << Custom App
 )




© Juergen Schackmann 2012                                                                  24/69
Wesentliche Django
  Komponenten
   (views,templates,models,forms)
Django Http Request (vereinfacht)


                                                     Model

                                                      Model
                                           Control
       Django
                            Url Konfigu-
        HTTP                                 View
                               raiton
       Handler



                                                     Templates



                                                      View




© Juergen Schackmann 2012                                        26/69
Model (ORM)
                                                                 models.py


                                                                  Model



        Django
                            Url Konfigu-
         HTTP                                  View
                               raiton
        Handler



                                                                 Templates




  ▸   Eigener Object-Relational-Mapper
  ▸   Verfügbare Backend Wrapper: SQLite, MySQL, PostgreSQL, Oracle
  ▸   Es werden alle wesentlichen Feldtypen unterstützt sowie 1-1, 1-n und m-n
      Beziehungen
  ▸   Datenbanktyp und Datenbankverbindung wird in settings.py definiert
  ▸   Initiale Erzeugung des Datenbankschemas inkl. Fixtures: manage.py syncdb

© Juergen Schackmann 2012                                                    27/69
Einfaches Model

 class Recipe(models.Model):
    title = models.CharField(verbose_name='Titel', max_length=255)
    preparation = models.TextField('Zubereitung', help_text='Zubereitung der Zutaten',blank=True)
    date_created = models.DateTimeField(editable=False)
    is_active = models.BooleanField('Aktiv')

     def __unicode__(self):
       return self.title




 ▸     Ausreichend für Erzeugung der Datenbankobjekte (syncdb)
 ▸     Verhält sich wie jede Python Class
 ▸     Viel __metaclass__ magic im Hintergrund


© Juergen Schackmann 2012                                                                           28/69
Models Meta

 class Recipe(models.Model):
    ...

     class Meta:
        verbose_name = 'Rezept'
        verbose_name_plural = 'Rezepte'
        ordering = ['-date_created']
        db_table = 'meine_rezepte'




 ▸     In Meta können unterschiedlichste Details konfiguriert werden
 ▸     Übersicht über alle Meta optionen:
       docs.djangoproject.com/en/1.4/ref/models/options/
 ▸     Die vorhandenen Defaults sind aber in der Regel ausreichend


© Juergen Schackmann 2012                                              29/69
Model Beziehungen

 class Category(models.Model):
    name = models.CharField('Name', max_length=100)
    description = models.TextField('Beschreibung', blank=True)

 class Recipe(models.Model):
    …
    categories = models.ManyToManyField(Category,related_name='recipes',verbose_name='Kategorie')
    author = models.ForeignKey(User, verbose_name='Autor') # User ist aus Django Contrib




 ▸   Django unterstützt 1-1, 1-n und m-n Beziehungen
 ▸   Mapping Models für m-n Beziehungen werden automatisch erzeugt oder
     können auch explizit definiert werden
 ▸   Beziehungsfeld im “entfernten” Model wird automatisch angelegt

© Juergen Schackmann 2012                                                                           30/69
Model Methoden

 class Recipe(models.Model):
   @models.permalink
   def get_absolute_url(self): # Empfohlene Methode fuer alle Modelle
      return ('recipes_recipe_detail', (), {'id': self.id})



   def save(self, *args, **kwargs): # Ueberschreiben einer Standard Methode
      if not self.id: # D.h. es handelt sich um eine neue, noch nicht gespeicherte Instanz
        self.date_created = datetime.datetime.now()
      super(Recipe, self).save(*args, **kwargs)



   def is_tasty(self): # Erzeugen einer eigenen Methode für Recipes
      return 'yes'


   @property
   def tasty(self): # Erzeugen einer Property
      return 'yes'


© Juergen Schackmann 2012                                                                    31/69
Model Managers

 class Recipe(models.Model):
    objects = models.Manager() # Default Manager (diese Zeile könnte auch weggelassen werden)
    active = ActiveRecipeManager() # Custom Manager der nur aktive Rezepte zurkückliefert




 ▸    Jedes Model hat mindestens ein Manager object; default Name "objects"
 ▸    Manager besitzt alle notwendigen Methoden, um Models
             ▸   zu verwalten (erzeugen, löschen, etc)
             ▸   Datenbankqueries abzusetzen (select)
 ▸    Manager funktioniert nicht bei Model Instanzen, d.h. nicht um einzelne
      Objecte zu managen.
 ▸    Docs: docs.djangoproject.com/en/dev/topics/db/managers/



© Juergen Schackmann 2012                                                                       32/69
Model QuerySets

 queryset=Recipe.objects.filter(title='abc')




 ▸    Django Abstraktion einer DB query
 ▸    Chainable
 ▸    “lazy”, d.h. Datenkbankzugriff erst dann, wenn unbedingt notwendig
 ▸    Benutzbar wie Python Listen
 ▸    Docs: docs.djangoproject.com/en/dev/ref/models/querysets/




© Juergen Schackmann 2012                                                  33/69
Beispiele Managers und Queries

 recipe=Recipe(title='test') # Neue Recipe Instanz wird erzeugt
 recipe.save() # Speicherung der neuen Instanz in Datenbank


 recipes=Recipe.objects.all() # liefert ein QuerySet zurück, aber noch keine Datenbankabfrage
 for recipe in recipes: # erst jetzt erfolgt die Datenbankabfrage und liefert liste zurück
   ....



 recipes=Recipe.objects.filter(active=True) # liefert QuerySet zurueck, aber noch keine Abfrage
 recipes = recipes.filter(author=user_juergen) # QuerySets lassen sich verketten
 recipe_first=recipes[0] # Erst jetzt erfolgt die Abfrage



 recipe = recipes.objects.get(author__name='juergen') # Beziehungen per '__', get findet genau
                                                                  eine Instance oder erzeugt Fehler
 recipe_first.objects.all() # Fehler, objects funktioniert nicht mit Instanzen




© Juergen Schackmann 2012                                                                             34/69
Model Vererbung

 class Recipe(models.Model):
    ...

 class PremiumRecipe(Recipe):
    price=models.FloatField()




 ▸    Modelle können vererbt werden
 ▸    Im Hintergrund wird 1-1 Beziehung zwischen Parent (Recipe) und Child
      (PremiumRecipe) erzeugt (und automatisch verwaltet)
 ▸    Zu tiefe Vererbung kann deshalb zu Performanceproblemen führen
 ▸    Spezialfälle: abstract, proxy, managed


© Juergen Schackmann 2012                                                    35/69
Templates
                                                                         Model



        Django
                             Url Konfigu-
         HTTP                                      View
                                raiton
        Handler



                                                                        Templates



                                                                        Templates/
 ▸    Eigenes Template System
 ▸    Kann ersetzt werden (bswp jinja)
 ▸    Performance: ok, aber schlechter als jinja


"the Django template system is not simply Python embedded into HTML. This is by design:
the template system is meant to express presentation, not program logic."




© Juergen Schackmann 2012                                                            36/69
Wesentliche Template Elemente

 ▸    Jedes Template wird mit einem Context dict gerendert
 ▸    Nur Objekte aus dem übergebenen Context sind verfügbar
 ▸    Aus Template heraus können nur Funktionen ohne Parameter aufgerufen
      werden, bspw. recipe.objects.all(), aber nicht
      recipe.objects.filter(title='test')
 ▸    Direkter Aufruf von Context Objekten:
                                        {{ user }}
 ▸    Tags sind komplexere Funktionen und Logik:
                            {% if user %} Welcome {% endif %}
 ▸    Filter sind Funktionen die den Input verändern:
                                 {{ user.name|capfirst }}


© Juergen Schackmann 2012                                              37/69
Einfaches Beispiel

 <head><title>Kochbuch</title></head>
 <body>
   <h1>Kochbuch</h1>
   {% if user %}Welcome {{ user.name|capfirst }} {% else %} Login {% endif %}
   <h2>Alle Rezepte</h2>
   <ul>
      {% for recipe in object_list %}
           <li><a href="{{ recipe.get_absolute_url }}">{{ recipe.title }}</a></li>
      {% endfor %}
   </ul>
 </body>




© Juergen Schackmann 2012                                                            38/69
Template Vererbung

 ▸    Templates können einfach vererbt werden per "extends"
 ▸    Mehrfachvererbung ist nicht möglich
 ▸    In einem Templates können Blöcke definiert werden
 ▸    In einem vererbten Template können die Blöcke überschrieben oder
      erweitert werden
 ▸    Mehrfahrvererbung durch "include" simuliert




© Juergen Schackmann 2012                                                39/69
Beispiel Vererbung: base.html

 <head>
      <title>{% block title %}Kochbuch{% endblock%}</title>
 </head>
 <body>
   <h1>Kochbuch</h1>
   {% block login %} {% endblock %}
   {% block content %} {% endblock %}
 </body>




© Juergen Schackmann 2012                                     40/69
Beispiel Vererbung: recipe_list.html

 {% extends "base.html" %}


 {% block title %}{{ block.super }} - Alle Rezepte{% endblock %}



 {% block login %} {% include "userauth/login.html" %} {% endblock %}



 {% block content %}
   <h2>Alle Rezepte</h2>
   <ul>
      {% for recipe in object_list %}
      <li><a href="{{ recipe.get_absolute_url }}">{{ recipe.title }}</a></li>
      {% endfor %}
   </ul>
 {% endblock %}




© Juergen Schackmann 2012                                                       41/69
Templates Finder & Loader

Kein direkter Zugriff auf Template files, nur über Templates Loader (definiert in
settings.py)

TEMPLATE_LOADERS = (
  'django.template.loaders.filesystem.Loader',
  'django.template.loaders.app_directories.Loader',)



 ▸   Loader werden in definierter Reihenfolge abgearbeitet
 ▸   Erster Fund wird zurückgeliefert
 ▸   Default Verhalten:
      ▸   Suche im Project Template Verzeichnis (d.h. gecustomized für Project)
      ▸   Wenn nicht gefunden, suche in den App Template Verzeichnissen aller Apps (in
          der Reihenfolge wie in INSTALLED_APPS) und liefer ersten Fund zurück
      ▸   Apps können sich Templates also auch selbst überschreiben (wichtig für
          Skins/Themes)


© Juergen Schackmann 2012                                                           42/69
Beispiel Finder & Loader

nuts/recipe_list.html extends extends nuts/base.html extends base.html

 nutshell/                                    << Root
       nutshell/                              << Project
               templates/                     << Project Templates
                    base.html                 << Project Base
                    nuts/                     << Project Nuts Templates
                            base.html         << Projet Nuts bass
       nuts/                                  << App Verzeichnis
               templates/                     << App Templates
                    nuts/                     << App Nuts Templates Verzeichnis
                            base.html         << App Nuts Base
                            recipe_list.hml




© Juergen Schackmann 2012                                                         43/69
Views
                                                                            Model
                                                        views.py/

          Django
                                Url Konfigu-
           HTTP                                           View
                                   raiton
          Handler



                                                                           Templates


 ▸   Views sind die Django Controller (MVC)
 ▸   View Anforderungen
      ▸    Callable
      ▸    Parameter: Django request object (plus optionale args,kwargs)
      ▸    Return: Django response object
 ▸   Typische Struktur:
      ▸    Bestimmung Templates
      ▸    Berechnung des Context objects (dict)
      ▸    Rendern des Templates mit Context
      ▸    Return des gerenderten Templates in Django Response object

© Juergen Schackmann 2012                                                              44/69
Einfacher View

def hello(request):
   return HttpResponse("<html><body>Hello World</body></html>")




         Views können implementiert werden ohne Django ORM
                           und Templates!




© Juergen Schackmann 2012                                         45/69
View mit Logik und Shortcuts

def recipe_detail(request, recipe_id):
  try:
     r = Recipe.objects.get(pk=recipe_id)
  except Recipe.DoesNotExist:
     raise Http404
  t = loader.get_template('recipe/recipe_detail.html')
  c = RequestContext(request, {'recipe': r})
  return HttpResponse(t.render(c))



def recipe_detail(request, recipe_id):
   r=get_object_or_404(Recipe, pk=recipe_id)
   return render(request,'recipe/recipe_detail.html', {'recipe': r})




© Juergen Schackmann 2012                                              46/69
Class Based (Generic) Views

class RecipeDetailView(DetailView):
     model=Recipe
     #template_name='recipe/recipe_detail.html' << default



class RecipeListView(ListView):
     model=Recipe
     template_name='recipe/my_recipe_list.html' << default



 ▸     Customizing via
        ▸   __init__ Parameter (ohne neue Klasse)
        ▸   Class Atrribute
        ▸   Methoden überschreiben
 ▸     Methoden überschreiben komplex, derzeit schwache Doku
 ▸     Achtung: class based views haben in UrlConf spezielle Syntax
© Juergen Schackmann 2012                                             47/69
Forms

 ▸   Eigenes Forms Package
      ▸   Initialisierung aus Model
      ▸   Automatisches Rendern in HTML
      ▸   Einfaches umwandlen von Post Request zurück in Model


 ▸   ModelForms
      ▸   Dynamische Generierung aus Model


 ▸   Hilfreiche App: ChrispyForms github.com/maraujop/django-crispy-forms


 ▸   Docs: docs.djangoproject.com/en/1.4/topics/forms



© Juergen Schackmann 2012                                               48/69
Form Handling Beispiel

def edit(request, recipe_id):
   recipe = get_object_or_404(Recipe, pk=recipe_id)
   if request.method == 'POST':
      form = RecipeForm(instance=recipe, data=request.POST)
      if form.is_valid():
           form.save()
           return HttpResponseRedirect(recipe.get_absolute_url())
   else:
      form = RecipeForm(instance=recipe)
   return render(request, 'recipes/form.html',
      {'form': form, 'add': False, 'object': recipe})




© Juergen Schackmann 2012                                           49/69
Url Konfiguration
                                                        Model
                              urls.py/

        Django
                            Url Konfigu-
         HTTP                                View
                               raiton
        Handler



                                                       Templates




 ▸    Mapping Tuple: Regex ==> Views
 ▸    Tuple Name: “urlpatterns”
 ▸    Regex Arguments als args und kwargs für View
 ▸    Named Patterns mit Reverese URL Lookup
 ▸    App Urls pluggable in Project Urls via Include



© Juergen Schackmann 2012                                          50/69
Typische App Url Konfiguration

urlpatterns = patterns('recipes.views',
        url(r'^erstellen/$', 'add', name='recipes_recipe_add'),
        url(r'^bearbeiten/(?P<recipe_id>d+)/$', 'edit', name='recipes_recipe_edit'),
        url(r'^rezept/(?P<pk>[-w]+)/$', RecipeDetailView.as_view(), name='recipes_recipe_detail'),
        url(r'^$', RecipeListView.as_view(), name='recipes_recipe_index'),
)


    ▸     patterns(prefix,*list)
           ▸   Prefix: optional, gemeinsames Package für alle views
    ▸     url(regex,view, kwargs,name)
           ▸   view: view name als string oder callable
           ▸   kwargs (optional): zusätzliche default Parameter
           ▸   name(optional): beliebiger, aber eindeutiger name
    ▸     Weitere Syntaxvarianten möglich; siehe docs:
          docs.djangoproject.com/en/1.4/topics/http/urls/
© Juergen Schackmann 2012                                                                             51/69
Typische Project Url Konfiguration

admin.autodiscover() # ueblich wenn admin verwendet wird



urlpatterns = patterns('',
    url(r'^$', 'recipes.views.home', name='home'),
    url(r'^recipes/', include('recipes.urls')),
    url(r'^admin/', include(admin.site.urls)),
)




    ▸   Vial Include werden Url Konfigurationen ineinander geschachtelt
    ▸   Vorallem App Urls ==> Project Urls
    ▸   Achtung: Url von Apps nicht fix, sondern abhängig von Project ==>
        reverse lookup


© Juergen Schackmann 2012                                                 52/69
Reverse URL Lookup

# in templates mit template tag
{% url recipes_recipe_add %}



# im python code
reverse('recipes_recipe_detail', kwargs={'pk':id})



# via get_absolute_url und permalink decorator
recipe.get_absolute_url()




© Juergen Schackmann 2012                            53/69
Django Http Request Lifecycle




                       Request                                     View
                                           Url Config                                Model
                      Middleware                                Middleware


    Django
     HTTP                                                                    View
    Handler



                               Response                 Exception                   Templates
                              Middleware                Middleware




© Juergen Schackmann 2012                                                                    54/69
Admin
Django.contrib.admin


 ▸    Meistgenutzte Applikation
 ▸    Größter Django Selling Point
 ▸    Hierarchische Struktur
       ▸   Liste aller Apps
       ▸   Liste aller Models je App
       ▸   List und Detail View je Model
 ▸    Dynamische Generierung der Seiten auf Basis der Models
 ▸    Sehr umfangreiches Customizing möglich
 ▸    Unterschiedliche Admin Sites mit unterschiedlichen
      Ausprägungen möglich

© Juergen Schackmann 2012                                      56/69
Admin Beispiel


class RecipeAdmin(admin.ModelAdmin):
   fields = ['title','preparation', 'date_created']


   def get_query_set(self,request):
      return Recipe.objects.filter(active=True)


admin.site.register(Category)
admin.site.register(Recipe, RecipeAdmin)




© Juergen Schackmann 2012                             57/69
Screenshots


 ▸    xxx




© Juergen Schackmann 2012   58/69
Settings
Settings.py

 ▸    Zentrale Konfiguration Django Project
 ▸    Python File
 ▸    100+ Django Settings (mit sinnvollen defaults)
       ▸   Datenbank
       ▸   Apps
       ▸   Template Verzeichnisse
       ▸   Statische Verzeichnisse
       ▸   Middleware
       ▸   Locale, Timezone, …
 ▸    Kann auch for eigene App settings genutzt werden
 ▸    Docs: docs.djangoproject.com/en/1.4/ref/settings/


© Juergen Schackmann 2012                                 60/69
Wichtige Settings Einstellungen


 ▸    DEBUG
 ▸    Datenbank
 ▸    Installed Apps
 ▸    Middleware
 ▸    Context_Processors
 ▸    Statische Verzeichnisse
 ▸    Template Verzeichnisse
 ▸    Timezone
 ▸    Locale


© Juergen Schackmann 2012           61/69
Typische Django App Liste (settings.py)

 INSTALLED_APPS = (
   'django.contrib.auth',           << User Management, Authentifizierung, Autorisierung
   'django.contrib.contenttypes',   << Dependency für folgende
   'django.contrib.sessions',       << Session Management
   'django.contrib.sites',          << Betreiben mehrere Sites aus einem Projekt
   'django.contrib.messages',       << Messages im Browser
   'django.contrib.staticfiles',    << Statische files für Entwicklung und Deployment
   'django.contrib.admin',          << Admin für alle apps (sehr nützlich)
   'south',                         << Datenschema Migration
   'debug_toolbar'                  << Debug Toolbar im Browser (für Entwicklung)
   'nuts1',                         << Custom App
   'nuts2',                         << Custom App
 )




© Juergen Schackmann 2012                                                                  62/69
Typische Settings Komponenten


 ▸    Bestimmung Project Root für generische Verweise auf
      Verzeichnisse
PROJECT_ROOT = dir(abspath(__file__)) # Kann ff für Verzeichnisdefinition verwendet werden


TEMPLATE_DIRS=(join(PROJECT_ROOT,'templates'))




 ▸    Definition von settings in Abhängigkeit von Debug setting
if DEBUG:
     ….




© Juergen Schackmann 2012                                                                    63/69
Settings in komplexen Umgebungen


 ▸      Verteilung settings auf verschiedenen files
        ▸   Unterschiedliche Settings Files für unterschiedliche
            Umgebungen
        ▸   Import files in “master” settings file in Abhängigkeit von
            bestimmten Bedingungen
import common_settings


if environ('DJANGO_ENVIRONMENT')=='DEV':
   import dev_settings
else:
   import prod_settings


try:
   import local_settings
except:
   pass

© Juergen Schackmann 2012                                                64/69
Zugriff auf Settings und App Settings


 ▸    Zugriff auf settings via django.conf.settings object
       ▸   Django Default Settings
       ▸   Project Settings
       ▸   Lazy Loading
 ▸    In settings.py sind nicht nur Django Core Settings erlaubt
 ▸    Jede App kann eigene settings definieren und nutzen

from django.conf import settings


NUTS_MY_SETTING =settings.get('NUTS_MY_SETTING','My_Default')




© Juergen Schackmann 2012                                          65/69
Room for Improvement?
Pro Django


 ▸    Sehr flache Lernkurve
 ▸    Genügend Flexibilität bei komplexen Anforderungen
 ▸    Modulares Gesamtkonzept
 ▸    Sehr großes App Ökosystem
 ▸    Große Community und nachhaltige Entwicklung




© Juergen Schackmann 2012                                 67/69
“Batteries Included”


 ▸    Admin
 ▸    Session Handling
 ▸    User Management, Authentifizeirung, Authorisierung,
      Permissions
 ▸    Comments
 ▸    Tags
 ▸    Static Files
 ▸    Content Types
 ▸    Internationalisierung, Lokalisierung
 ▸    Caching

© Juergen Schackmann 2012                                   68/69
Room for Improvement

 ▸    Convention sehr liberal
 ▸    Pluggable != Pluggable
 ▸    Viele Apps für das selbe Problem
 ▸    Qualität der Apps sehr unterschiedlich
 ▸    Fehlende Contrib Apps:
       ▸   Workflow
       ▸   Object Permissions
       ▸   Schema Migration
 ▸    Python 3 support für apps


© Juergen Schackmann 2012                      69/69

Django nutshell overview

  • 1.
    Django in aNutshell Python User Group München - µPy 6. November 2012 juergen.schackmann@gmail.com © Juergen Schackmann 2012
  • 2.
    Ziel ▸ Überblick über Django ▸ Besprechung wesentlicher Komponenten ▸ Customizing Möglichkeiten ▸ Django Ökosystem ▸ Bewertung ▸ Kein Django Tutorial ▸ Kein hands-on workshop (gerne als separater Termin) © Juergen Schackmann 2012 2/69
  • 3.
    Agenda ▸ Übersicht ▸ Quick Start ▸ Project und (pluggable) Apps ▸ Wesentlich Django Komponenten ▸ Admin ▸ Settings ▸ Room for Improvement © Juergen Schackmann 2012 3/69
  • 4.
  • 5.
    Was ist Django(nicht) ▸ Web application Framework ▸ Pure Python ▸ Full-Stack (keine bzw. kaum externe dependencies) ▸ Philosophie: ▸ Dry ▸ Loose Coupling ▸ MVC bzw. MVT ▸ BSD Lizenz ▸ Django Software Foundation ▸ Sehr gute Dokumentation und große freundliche Community ▸ Django ist kein Content Management System (aber es gibt in Django implementierte CMS) Quellen: django-workshop.de/einfuehrung.html, djangobook.com/en/2.0/chapter01.html © Juergen Schackmann 2012 5/69
  • 6.
    Historie ▸ Entstanden 2003/2004 bei lawrence.com (Medienunternehmen, Zeitung) als closed source in Kansas (ebenso wie memcache) ▸ Benannt nach Django Reinhardt (Jazz Guitarist) ▸ Open Source: 2005 ▸ “Benevolent Dictators for Life”: Jacob Kaplan-Moss, Adrian Holovaty ▸ Ursprung aus der Medienindustrie hat die Use Cases und Sweet Spots geprägt ▸ Aktuelle stabile Version: 1.4.2 ▸ Version 1.5 bringt Python 3 Unterstützung ▸ Minor Release alle 9 Monate Quellen: http://www.quora.com/What-is-the-history-of-the-Django-web-framework,http://www.djangobook.com/en/2.0/chapter01.html © Juergen Schackmann 2012 6/69
  • 7.
    Django Ressourcen ▸ Homepage: djangoproject.com ▸ Docs: docs.djangoproject.com/en/1.4/ ▸ Code: github.com/django/django ▸ User Mailing List: groups.google.com/forum/?fromgroups#!forum/django- users ▸ Django App Ökosystem: djangopackages.com ▸ Django powered Websites: djangosites.org ▸ Django Snipptes: djangosnippets.org © Juergen Schackmann 2012 7/69
  • 8.
    Bücher, Tutorials, Trainings,... ▸ Tutorial: docs.djangoproject.com/en/1.4/intro/tutorial01/ ▸ Django Workshop (deutsch): django-workshop.de ▸ Django Book: djangobook.com/en/2.0/index.html ▸ amazon.de/Pro-Django-Experts-Voice- Development/dp/1430210478 ▸ amazon.de/Python-Development-Django-Developers- Library/dp/0132356139 © Juergen Schackmann 2012 8/69
  • 9.
    Videos ▸ Serie von Django Video Tutorials (für Anfänger): hackedexistence.com/project-django.html ▸ Video: Django Blog in 30 min (für Fortschreitende): http://arunrocks.com/blog/2012/03/05/building_a_bl og_in_30_mins_with_django_%28screencast%2 ▸ Django in Depth, sehr gute 3h presentation (nichts für Anfänger): youtube.com/watch?v=t_ziKY1ayCo © Juergen Schackmann 2012 9/69
  • 10.
    Bekannte Django Sites pinterest.com bitbucket.org disqus.com instagram.com nytimes.com turnkeylinux.org washingtonpost.com ubuntuusers.de © Juergen Schackmann 2012 10/69
  • 11.
  • 12.
    Quick Start 1.Django Installation 2. Projekt erzeugen 3. Development Web Server starten 4. App(s) erzeugen 5. Datenbank Schema erzeugen © Juergen Schackmann 2012 12/69
  • 13.
    Installation >>> pipinstall django ==> Done :-) ▸ 7,7 MB download vom PyPi ▸ keine weiteren Dependencies ▸ Tip: am besten Installation in ein Virtualenv © Juergen Schackmann 2012 13/69
  • 14.
    Projekt erzeugen Django kommtmit Kommandozeilen Tool zur Erzeugung und Verwaltung von Projekten und Apps >>> django-admin startproject nutshell >>> cd nutshell Erzeugt die komplette Verzeichnisstruktur mit allen relevanten Daten für ein Django Projekt nutshell/ manage.py << Tool zur Verwaltung dieses Projekts nutshell/ << Verzeichnis mit Code & Settings für dieses Projekt __init__.py settings.py << Konfigurations File urls.py << Url Konfiguration wsgi.py << WSGI Applikation © Juergen Schackmann 2012 14/69
  • 15.
    Django Webserver starten Startendes Django Webservers >>> python manage.py runserver Und Aufruf unter http://127.0.0.1:8000/ Achtung: Django Webserver nur für Entwicklung nutzen, nicht für Produktion vorgesehen © Juergen Schackmann 2012 15/69
  • 16.
    App(s) erzeugen Jedes DjangoProjekt besteht aus mindestens einer App (in der Regel aber aus sehr vielen Apps) >>> python manage.py startapp nuts Erzeugt die komplette Verzeichnisstruktur mit allen relevanten Dateien für eine Django App nutshell/ << Root nutshell/ << Project nuts/ << App Verzeichnis __init__.py models..py << App Models tests.py << Unit Tests views.py << Views (=Controllers) Achtung: Apps müssen nicht im Project Verzeichns liegen, Python Path reicht aus © Juergen Schackmann 2012 16/69
  • 17.
    Datenbank Schema erzeugen Generierungdes Datenbank Schemas >>> python manage.py syncdb Achtung: zuerst muss in settings.py die Datenbank/ Datenbankverbindung eingetragen werden (am besten SQLite) © Juergen Schackmann 2012 17/69
  • 18.
    Notwendige nächste Schritte ▸ Anpassung settings.py ▸ Eintrag der Datenbank ▸ Hinzufügen gewünschter Apps ==> Happy Coding © Juergen Schackmann 2012 18/69
  • 19.
  • 20.
    Apps im Project(Idealfall) App 1 App 2 App 3 App 4 Konfiguration URL Routing Presentation Settings.py urls.py Templates ▸ Project definiert sich über settings.py, urls.py und Templates (Verzeichnis) ▸ Project besteht aus unabhängigen Apps ▸ Apps müssen nichts übereinander wissen © Juergen Schackmann 2012 20/69
  • 21.
    Pluggable Apps ▸ Jede App sollte ▸ genau eine Aufgabe sehr gut erledigen ▸ eigenständig funktionieren (ohne Wissen über andere Apps) ▸ möglichst weit konfigurierbar sein ▸ idealer Weise mit eigener setup.py und upload zu pypi ▸ Beispiele für gute Apps ▸ Tagging ▸ Themes/Skins ▸ Comments ▸ Beispiele for schlechte App: “Handle entries in a weblog, and users who post them, and their authentication, and tagging and categorization, and some flat pages for static content, and... ▸ Übersicht Django Apps: djangopackages.com Quellen: http://media.b-list.org/presentations/2008/djangocon/reusable_apps.pdf, http://www.slideshare.net/coordt/pluggable-django-application-patterns-pycon-2011 © Juergen Schackmann 2012 21/69
  • 22.
    Typisches Project Verzeichnis ▸ Default Einstellung sind Best Practice für kleinere bis mittlere Projekte ▸ Wording ist Konvention und beliebig anpassbar ▸ Verzeichnisstruktur mein persönlicher Vorschlag und beliebig anpassbar ▸ Konvention und Struktur wird in settings.py definiert nutshell/ << Project Root manage.py << Tool zur Verwaltung dieses Projects(automatisch erzeugt) site_static/ << Statische Files (wird während Deployment gefüllt) media/ << Media Files (upload files, wird während Nutzung gefüllt) nutshell/ << Verzeichnis mit Code & Settings für dieses Projekt __init__.py settings.py << Konfigurations File (automatisch erzeugt und erweitert)) urls.py << Url Konfiguration (automatisch erzeugt und erweitert) wsgi.py << WSGI Applikation(automatisch erzeugt) templates/ << Projektspezifische Templates (überschreiben App Templates) fixtures/ << Projektspezifische Fixtures(überschreiben App Fixtures) © Juergen Schackmann 2012 22/69
  • 23.
    Typisches App Verzeichnis ▸ All apps müssen als Package im Python Path auffindbar sein ▸ models.py ist die einzige Anforderung von Django, kann aber auch leer sein ▸ Wording für "templatetags" und "commands" ist fix nuts/ << App Verzeichnis __init__.py settings.py << App spezifische Settings / Konfiguration models.py << App Models tests.py << Unit Tests forms.py << Django Formulare admin.py << Admin (Admin Seiten für ausgewählte Models) views.py << Views (=Controllers) urls.py << Urls Conf (Url mapping auf App Views) templatetags/ << Custom templatetags command/ << Zusätzliche manage.py. commands templates/ << App Templates (durch Project Templates überschreibbar) static/ << Statische App files (durch statische Project files überschreibbar) fixtures/ << App Fixtures © Juergen Schackmann 2012 23/69
  • 24.
    Typische Django AppListe (settings.py) INSTALLED_APPS = ( 'django.contrib.auth', << User Management, Authentifizierung, Autorisierung 'django.contrib.contenttypes', << Dependency für folgende 'django.contrib.sessions', << Session Management 'django.contrib.sites', << Betreiben mehrere Sites aus einem Projekt 'django.contrib.messages', << Messages im Browser 'django.contrib.staticfiles', << Statische files für Entwicklung und Deployment 'django.contrib.admin', << Admin für alle apps (sehr nützlich) 'south', << Datenschema Migration 'debug_toolbar' << Debug Toolbar im Browser (für Entwicklung) 'nuts1', << Custom App 'nuts2', << Custom App ) © Juergen Schackmann 2012 24/69
  • 25.
    Wesentliche Django Komponenten (views,templates,models,forms)
  • 26.
    Django Http Request(vereinfacht) Model Model Control Django Url Konfigu- HTTP View raiton Handler Templates View © Juergen Schackmann 2012 26/69
  • 27.
    Model (ORM) models.py Model Django Url Konfigu- HTTP View raiton Handler Templates ▸ Eigener Object-Relational-Mapper ▸ Verfügbare Backend Wrapper: SQLite, MySQL, PostgreSQL, Oracle ▸ Es werden alle wesentlichen Feldtypen unterstützt sowie 1-1, 1-n und m-n Beziehungen ▸ Datenbanktyp und Datenbankverbindung wird in settings.py definiert ▸ Initiale Erzeugung des Datenbankschemas inkl. Fixtures: manage.py syncdb © Juergen Schackmann 2012 27/69
  • 28.
    Einfaches Model classRecipe(models.Model): title = models.CharField(verbose_name='Titel', max_length=255) preparation = models.TextField('Zubereitung', help_text='Zubereitung der Zutaten',blank=True) date_created = models.DateTimeField(editable=False) is_active = models.BooleanField('Aktiv') def __unicode__(self): return self.title ▸ Ausreichend für Erzeugung der Datenbankobjekte (syncdb) ▸ Verhält sich wie jede Python Class ▸ Viel __metaclass__ magic im Hintergrund © Juergen Schackmann 2012 28/69
  • 29.
    Models Meta classRecipe(models.Model): ... class Meta: verbose_name = 'Rezept' verbose_name_plural = 'Rezepte' ordering = ['-date_created'] db_table = 'meine_rezepte' ▸ In Meta können unterschiedlichste Details konfiguriert werden ▸ Übersicht über alle Meta optionen: docs.djangoproject.com/en/1.4/ref/models/options/ ▸ Die vorhandenen Defaults sind aber in der Regel ausreichend © Juergen Schackmann 2012 29/69
  • 30.
    Model Beziehungen classCategory(models.Model): name = models.CharField('Name', max_length=100) description = models.TextField('Beschreibung', blank=True) class Recipe(models.Model): … categories = models.ManyToManyField(Category,related_name='recipes',verbose_name='Kategorie') author = models.ForeignKey(User, verbose_name='Autor') # User ist aus Django Contrib ▸ Django unterstützt 1-1, 1-n und m-n Beziehungen ▸ Mapping Models für m-n Beziehungen werden automatisch erzeugt oder können auch explizit definiert werden ▸ Beziehungsfeld im “entfernten” Model wird automatisch angelegt © Juergen Schackmann 2012 30/69
  • 31.
    Model Methoden classRecipe(models.Model): @models.permalink def get_absolute_url(self): # Empfohlene Methode fuer alle Modelle return ('recipes_recipe_detail', (), {'id': self.id}) def save(self, *args, **kwargs): # Ueberschreiben einer Standard Methode if not self.id: # D.h. es handelt sich um eine neue, noch nicht gespeicherte Instanz self.date_created = datetime.datetime.now() super(Recipe, self).save(*args, **kwargs) def is_tasty(self): # Erzeugen einer eigenen Methode für Recipes return 'yes' @property def tasty(self): # Erzeugen einer Property return 'yes' © Juergen Schackmann 2012 31/69
  • 32.
    Model Managers classRecipe(models.Model): objects = models.Manager() # Default Manager (diese Zeile könnte auch weggelassen werden) active = ActiveRecipeManager() # Custom Manager der nur aktive Rezepte zurkückliefert ▸ Jedes Model hat mindestens ein Manager object; default Name "objects" ▸ Manager besitzt alle notwendigen Methoden, um Models ▸ zu verwalten (erzeugen, löschen, etc) ▸ Datenbankqueries abzusetzen (select) ▸ Manager funktioniert nicht bei Model Instanzen, d.h. nicht um einzelne Objecte zu managen. ▸ Docs: docs.djangoproject.com/en/dev/topics/db/managers/ © Juergen Schackmann 2012 32/69
  • 33.
    Model QuerySets queryset=Recipe.objects.filter(title='abc') ▸ Django Abstraktion einer DB query ▸ Chainable ▸ “lazy”, d.h. Datenkbankzugriff erst dann, wenn unbedingt notwendig ▸ Benutzbar wie Python Listen ▸ Docs: docs.djangoproject.com/en/dev/ref/models/querysets/ © Juergen Schackmann 2012 33/69
  • 34.
    Beispiele Managers undQueries recipe=Recipe(title='test') # Neue Recipe Instanz wird erzeugt recipe.save() # Speicherung der neuen Instanz in Datenbank recipes=Recipe.objects.all() # liefert ein QuerySet zurück, aber noch keine Datenbankabfrage for recipe in recipes: # erst jetzt erfolgt die Datenbankabfrage und liefert liste zurück .... recipes=Recipe.objects.filter(active=True) # liefert QuerySet zurueck, aber noch keine Abfrage recipes = recipes.filter(author=user_juergen) # QuerySets lassen sich verketten recipe_first=recipes[0] # Erst jetzt erfolgt die Abfrage recipe = recipes.objects.get(author__name='juergen') # Beziehungen per '__', get findet genau eine Instance oder erzeugt Fehler recipe_first.objects.all() # Fehler, objects funktioniert nicht mit Instanzen © Juergen Schackmann 2012 34/69
  • 35.
    Model Vererbung classRecipe(models.Model): ... class PremiumRecipe(Recipe): price=models.FloatField() ▸ Modelle können vererbt werden ▸ Im Hintergrund wird 1-1 Beziehung zwischen Parent (Recipe) und Child (PremiumRecipe) erzeugt (und automatisch verwaltet) ▸ Zu tiefe Vererbung kann deshalb zu Performanceproblemen führen ▸ Spezialfälle: abstract, proxy, managed © Juergen Schackmann 2012 35/69
  • 36.
    Templates Model Django Url Konfigu- HTTP View raiton Handler Templates Templates/ ▸ Eigenes Template System ▸ Kann ersetzt werden (bswp jinja) ▸ Performance: ok, aber schlechter als jinja "the Django template system is not simply Python embedded into HTML. This is by design: the template system is meant to express presentation, not program logic." © Juergen Schackmann 2012 36/69
  • 37.
    Wesentliche Template Elemente ▸ Jedes Template wird mit einem Context dict gerendert ▸ Nur Objekte aus dem übergebenen Context sind verfügbar ▸ Aus Template heraus können nur Funktionen ohne Parameter aufgerufen werden, bspw. recipe.objects.all(), aber nicht recipe.objects.filter(title='test') ▸ Direkter Aufruf von Context Objekten: {{ user }} ▸ Tags sind komplexere Funktionen und Logik: {% if user %} Welcome {% endif %} ▸ Filter sind Funktionen die den Input verändern: {{ user.name|capfirst }} © Juergen Schackmann 2012 37/69
  • 38.
    Einfaches Beispiel <head><title>Kochbuch</title></head> <body> <h1>Kochbuch</h1> {% if user %}Welcome {{ user.name|capfirst }} {% else %} Login {% endif %} <h2>Alle Rezepte</h2> <ul> {% for recipe in object_list %} <li><a href="{{ recipe.get_absolute_url }}">{{ recipe.title }}</a></li> {% endfor %} </ul> </body> © Juergen Schackmann 2012 38/69
  • 39.
    Template Vererbung ▸ Templates können einfach vererbt werden per "extends" ▸ Mehrfachvererbung ist nicht möglich ▸ In einem Templates können Blöcke definiert werden ▸ In einem vererbten Template können die Blöcke überschrieben oder erweitert werden ▸ Mehrfahrvererbung durch "include" simuliert © Juergen Schackmann 2012 39/69
  • 40.
    Beispiel Vererbung: base.html <head> <title>{% block title %}Kochbuch{% endblock%}</title> </head> <body> <h1>Kochbuch</h1> {% block login %} {% endblock %} {% block content %} {% endblock %} </body> © Juergen Schackmann 2012 40/69
  • 41.
    Beispiel Vererbung: recipe_list.html {% extends "base.html" %} {% block title %}{{ block.super }} - Alle Rezepte{% endblock %} {% block login %} {% include "userauth/login.html" %} {% endblock %} {% block content %} <h2>Alle Rezepte</h2> <ul> {% for recipe in object_list %} <li><a href="{{ recipe.get_absolute_url }}">{{ recipe.title }}</a></li> {% endfor %} </ul> {% endblock %} © Juergen Schackmann 2012 41/69
  • 42.
    Templates Finder &Loader Kein direkter Zugriff auf Template files, nur über Templates Loader (definiert in settings.py) TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader',) ▸ Loader werden in definierter Reihenfolge abgearbeitet ▸ Erster Fund wird zurückgeliefert ▸ Default Verhalten: ▸ Suche im Project Template Verzeichnis (d.h. gecustomized für Project) ▸ Wenn nicht gefunden, suche in den App Template Verzeichnissen aller Apps (in der Reihenfolge wie in INSTALLED_APPS) und liefer ersten Fund zurück ▸ Apps können sich Templates also auch selbst überschreiben (wichtig für Skins/Themes) © Juergen Schackmann 2012 42/69
  • 43.
    Beispiel Finder &Loader nuts/recipe_list.html extends extends nuts/base.html extends base.html nutshell/ << Root nutshell/ << Project templates/ << Project Templates base.html << Project Base nuts/ << Project Nuts Templates base.html << Projet Nuts bass nuts/ << App Verzeichnis templates/ << App Templates nuts/ << App Nuts Templates Verzeichnis base.html << App Nuts Base recipe_list.hml © Juergen Schackmann 2012 43/69
  • 44.
    Views Model views.py/ Django Url Konfigu- HTTP View raiton Handler Templates ▸ Views sind die Django Controller (MVC) ▸ View Anforderungen ▸ Callable ▸ Parameter: Django request object (plus optionale args,kwargs) ▸ Return: Django response object ▸ Typische Struktur: ▸ Bestimmung Templates ▸ Berechnung des Context objects (dict) ▸ Rendern des Templates mit Context ▸ Return des gerenderten Templates in Django Response object © Juergen Schackmann 2012 44/69
  • 45.
    Einfacher View def hello(request): return HttpResponse("<html><body>Hello World</body></html>") Views können implementiert werden ohne Django ORM und Templates! © Juergen Schackmann 2012 45/69
  • 46.
    View mit Logikund Shortcuts def recipe_detail(request, recipe_id): try: r = Recipe.objects.get(pk=recipe_id) except Recipe.DoesNotExist: raise Http404 t = loader.get_template('recipe/recipe_detail.html') c = RequestContext(request, {'recipe': r}) return HttpResponse(t.render(c)) def recipe_detail(request, recipe_id): r=get_object_or_404(Recipe, pk=recipe_id) return render(request,'recipe/recipe_detail.html', {'recipe': r}) © Juergen Schackmann 2012 46/69
  • 47.
    Class Based (Generic)Views class RecipeDetailView(DetailView): model=Recipe #template_name='recipe/recipe_detail.html' << default class RecipeListView(ListView): model=Recipe template_name='recipe/my_recipe_list.html' << default ▸ Customizing via ▸ __init__ Parameter (ohne neue Klasse) ▸ Class Atrribute ▸ Methoden überschreiben ▸ Methoden überschreiben komplex, derzeit schwache Doku ▸ Achtung: class based views haben in UrlConf spezielle Syntax © Juergen Schackmann 2012 47/69
  • 48.
    Forms ▸ Eigenes Forms Package ▸ Initialisierung aus Model ▸ Automatisches Rendern in HTML ▸ Einfaches umwandlen von Post Request zurück in Model ▸ ModelForms ▸ Dynamische Generierung aus Model ▸ Hilfreiche App: ChrispyForms github.com/maraujop/django-crispy-forms ▸ Docs: docs.djangoproject.com/en/1.4/topics/forms © Juergen Schackmann 2012 48/69
  • 49.
    Form Handling Beispiel defedit(request, recipe_id): recipe = get_object_or_404(Recipe, pk=recipe_id) if request.method == 'POST': form = RecipeForm(instance=recipe, data=request.POST) if form.is_valid(): form.save() return HttpResponseRedirect(recipe.get_absolute_url()) else: form = RecipeForm(instance=recipe) return render(request, 'recipes/form.html', {'form': form, 'add': False, 'object': recipe}) © Juergen Schackmann 2012 49/69
  • 50.
    Url Konfiguration Model urls.py/ Django Url Konfigu- HTTP View raiton Handler Templates ▸ Mapping Tuple: Regex ==> Views ▸ Tuple Name: “urlpatterns” ▸ Regex Arguments als args und kwargs für View ▸ Named Patterns mit Reverese URL Lookup ▸ App Urls pluggable in Project Urls via Include © Juergen Schackmann 2012 50/69
  • 51.
    Typische App UrlKonfiguration urlpatterns = patterns('recipes.views', url(r'^erstellen/$', 'add', name='recipes_recipe_add'), url(r'^bearbeiten/(?P<recipe_id>d+)/$', 'edit', name='recipes_recipe_edit'), url(r'^rezept/(?P<pk>[-w]+)/$', RecipeDetailView.as_view(), name='recipes_recipe_detail'), url(r'^$', RecipeListView.as_view(), name='recipes_recipe_index'), ) ▸ patterns(prefix,*list) ▸ Prefix: optional, gemeinsames Package für alle views ▸ url(regex,view, kwargs,name) ▸ view: view name als string oder callable ▸ kwargs (optional): zusätzliche default Parameter ▸ name(optional): beliebiger, aber eindeutiger name ▸ Weitere Syntaxvarianten möglich; siehe docs: docs.djangoproject.com/en/1.4/topics/http/urls/ © Juergen Schackmann 2012 51/69
  • 52.
    Typische Project UrlKonfiguration admin.autodiscover() # ueblich wenn admin verwendet wird urlpatterns = patterns('', url(r'^$', 'recipes.views.home', name='home'), url(r'^recipes/', include('recipes.urls')), url(r'^admin/', include(admin.site.urls)), ) ▸ Vial Include werden Url Konfigurationen ineinander geschachtelt ▸ Vorallem App Urls ==> Project Urls ▸ Achtung: Url von Apps nicht fix, sondern abhängig von Project ==> reverse lookup © Juergen Schackmann 2012 52/69
  • 53.
    Reverse URL Lookup #in templates mit template tag {% url recipes_recipe_add %} # im python code reverse('recipes_recipe_detail', kwargs={'pk':id}) # via get_absolute_url und permalink decorator recipe.get_absolute_url() © Juergen Schackmann 2012 53/69
  • 54.
    Django Http RequestLifecycle Request View Url Config Model Middleware Middleware Django HTTP View Handler Response Exception Templates Middleware Middleware © Juergen Schackmann 2012 54/69
  • 55.
  • 56.
    Django.contrib.admin ▸ Meistgenutzte Applikation ▸ Größter Django Selling Point ▸ Hierarchische Struktur ▸ Liste aller Apps ▸ Liste aller Models je App ▸ List und Detail View je Model ▸ Dynamische Generierung der Seiten auf Basis der Models ▸ Sehr umfangreiches Customizing möglich ▸ Unterschiedliche Admin Sites mit unterschiedlichen Ausprägungen möglich © Juergen Schackmann 2012 56/69
  • 57.
    Admin Beispiel class RecipeAdmin(admin.ModelAdmin): fields = ['title','preparation', 'date_created'] def get_query_set(self,request): return Recipe.objects.filter(active=True) admin.site.register(Category) admin.site.register(Recipe, RecipeAdmin) © Juergen Schackmann 2012 57/69
  • 58.
    Screenshots ▸ xxx © Juergen Schackmann 2012 58/69
  • 59.
  • 60.
    Settings.py ▸ Zentrale Konfiguration Django Project ▸ Python File ▸ 100+ Django Settings (mit sinnvollen defaults) ▸ Datenbank ▸ Apps ▸ Template Verzeichnisse ▸ Statische Verzeichnisse ▸ Middleware ▸ Locale, Timezone, … ▸ Kann auch for eigene App settings genutzt werden ▸ Docs: docs.djangoproject.com/en/1.4/ref/settings/ © Juergen Schackmann 2012 60/69
  • 61.
    Wichtige Settings Einstellungen ▸ DEBUG ▸ Datenbank ▸ Installed Apps ▸ Middleware ▸ Context_Processors ▸ Statische Verzeichnisse ▸ Template Verzeichnisse ▸ Timezone ▸ Locale © Juergen Schackmann 2012 61/69
  • 62.
    Typische Django AppListe (settings.py) INSTALLED_APPS = ( 'django.contrib.auth', << User Management, Authentifizierung, Autorisierung 'django.contrib.contenttypes', << Dependency für folgende 'django.contrib.sessions', << Session Management 'django.contrib.sites', << Betreiben mehrere Sites aus einem Projekt 'django.contrib.messages', << Messages im Browser 'django.contrib.staticfiles', << Statische files für Entwicklung und Deployment 'django.contrib.admin', << Admin für alle apps (sehr nützlich) 'south', << Datenschema Migration 'debug_toolbar' << Debug Toolbar im Browser (für Entwicklung) 'nuts1', << Custom App 'nuts2', << Custom App ) © Juergen Schackmann 2012 62/69
  • 63.
    Typische Settings Komponenten ▸ Bestimmung Project Root für generische Verweise auf Verzeichnisse PROJECT_ROOT = dir(abspath(__file__)) # Kann ff für Verzeichnisdefinition verwendet werden TEMPLATE_DIRS=(join(PROJECT_ROOT,'templates')) ▸ Definition von settings in Abhängigkeit von Debug setting if DEBUG: …. © Juergen Schackmann 2012 63/69
  • 64.
    Settings in komplexenUmgebungen ▸ Verteilung settings auf verschiedenen files ▸ Unterschiedliche Settings Files für unterschiedliche Umgebungen ▸ Import files in “master” settings file in Abhängigkeit von bestimmten Bedingungen import common_settings if environ('DJANGO_ENVIRONMENT')=='DEV': import dev_settings else: import prod_settings try: import local_settings except: pass © Juergen Schackmann 2012 64/69
  • 65.
    Zugriff auf Settingsund App Settings ▸ Zugriff auf settings via django.conf.settings object ▸ Django Default Settings ▸ Project Settings ▸ Lazy Loading ▸ In settings.py sind nicht nur Django Core Settings erlaubt ▸ Jede App kann eigene settings definieren und nutzen from django.conf import settings NUTS_MY_SETTING =settings.get('NUTS_MY_SETTING','My_Default') © Juergen Schackmann 2012 65/69
  • 66.
  • 67.
    Pro Django ▸ Sehr flache Lernkurve ▸ Genügend Flexibilität bei komplexen Anforderungen ▸ Modulares Gesamtkonzept ▸ Sehr großes App Ökosystem ▸ Große Community und nachhaltige Entwicklung © Juergen Schackmann 2012 67/69
  • 68.
    “Batteries Included” ▸ Admin ▸ Session Handling ▸ User Management, Authentifizeirung, Authorisierung, Permissions ▸ Comments ▸ Tags ▸ Static Files ▸ Content Types ▸ Internationalisierung, Lokalisierung ▸ Caching © Juergen Schackmann 2012 68/69
  • 69.
    Room for Improvement ▸ Convention sehr liberal ▸ Pluggable != Pluggable ▸ Viele Apps für das selbe Problem ▸ Qualität der Apps sehr unterschiedlich ▸ Fehlende Contrib Apps: ▸ Workflow ▸ Object Permissions ▸ Schema Migration ▸ Python 3 support für apps © Juergen Schackmann 2012 69/69