A Quick Overview
A bit about me

•   Programmer @ 5Q Communications
•   Hack on Django mostly full-time
•   Dozen+ sites in production
•   Calvin grad
A bit about Django

•   Named after Django Reinhart, jazz guitarist
•   Python 2.3+ (Not 3.x yet, afiak)
•   BSD license
•   djangoproject.com
•   Current release: 1.1
Who uses it?
•   NASA
•   PBS
•   NY Times
•   LA Times
•   National Geographic
•   Discovery Channel
Features

•   Object-Relational     •   i18n/unicode support
    Mapper
                          •   Cache framework
•   MVC architecture
                          •   Testing framework
•   Templating Language
                          •   Great docs (650+ pages)
•   “Automatic” admins
                          •   Friendly community
•   Elegant urls
More Features

•   Jython support        •   Built-in RSS/ATOM
•   Geospacial content    •   Built-in site maps
    (via GeoDjango)
                          •   Send emails easily
•   Built-in dev server
                          •   “Signal” hooks
•   Nice support
                          •   Solid security emphasis
    for forms
Projects and Apps
Settings: database,               App   Live anywhere in your
email, caching, etc.   Project          PYTHONPATH
                                  App


      HTML, CSS,                  App
      images, etc. Templates
                       & Assets   App
Typical Project Layout
       project/
         __init__.py
         settings.py
         manage.py
         urls.py
         templates/
         static/
         staff_members/
            __init__.py
            models.py
            admin.py
            views.py
            urls.py
            tests.py
            templates/
Typical App Workflow

1. Create app
2. Create models.py and admin.py
3. ‘python manage.py syncdb’
4. Create urls.py and views.py
class StaffMemberGroup(models.Model):
   name = models.CharField(blank=True, max_length=100)
   order = models.IntegerField(blank=True, null=True)

class StaffMember(models.Model):
   first_name = models.CharField(max_length=100)
   last_name = models.CharField(max_length=100)
   title = models.CharField(blank=True, max_length=100)
   bio = models.TextField(blank=True)
   image = models.FileField(upload_to='bio_images', blank=True)
   email = models.EmailField()
   published = models.BooleanField()
   staff_group = models.ForeignKey(StaffMemberGroup)
python manage.py syncdb

1. Create tables
2. Create basic indexes
3. Create intermediate tables
   for m2m relationships
bob = StaffMember(first_name=”Bob”, last_name=”Smith”)

members = StaffMember.objects.all()

ordered_members =
 StaffMember.objects.all().order_by(‘last_name’)

published_members =
 StaffMember.objects.filter(published=True)
groups = StaffMemberGroup.objects.all()

for group in groups:
  print group.name
    for member in group.staffmember_set.all():
       print member.first_name
class StaffMemberAdmin(admin.ModelAdmin):
   list_display = ('last_name', 'first_name', 'email', 'published')
   list_filter = ('published', 'staff_group')
   search_fields = ('first_name', 'last_name', 'bio', 'title', 'email')
   fieldsets = (
       (None, {
           'fields': (('first_name', 'last_name'), 'title', 'email', 'image', 'bio'),
           'description': '',
       }),
       ('Options', {
           'fields': ('published', 'staff_group'),
       })
   )
admin.site.register(StaffMember, StaffMemberAdmin)
project urls.py
urlpatterns = patterns('',
   (r'^staff_members/', include('grpug.staff_members.urls')),
   (r'^admin/doc/', include('django.contrib.admindocs.urls')),
   (r'^admin/(.*)', admin.site.root),
)


staff_members app urls.py:
urlpatterns = patterns('grpug.staff_members.views',
   url(r'^$', 'show_staff_members', name='staff-members'),
)
def show_staff_members(request):
  groups = StaffMemberGroup.objects.all()
  return render_to_response(
     'staff_member.html',
     {'groups': groups}
  )
staff_member.html
{% for group in groups %}
  <h2>{{group.name}}</h2>
  <ul>
     {% for member in group.staffmember_set.all %}
        <li>
        <h3>{{member.first_name}} {{member.last_name}}</h3>
        <p>{{member.bio}}</p>
        </li>
     {% endfor %}
  </ul>
{% endfor %}
staff_member.html
{% extends ‘base_site.html’ %}

  {% block content %}
  {% for group in groups %}
    <h2>{{group.name}}</h2>
    <ul>
       {% for member in group.staffmember_set.all %}
          <li>
          <h3>{{member.first_name}} {{member.last_name}}</h3>
          <p>{{member.bio}}</p>
          </li>
       {% endfor %}
    </ul>
  {% endfor %}
{% endblock content %}
base_site.html
  <html>
  <body>
    {% block content %}
    {% endblock content %}
  </body>
  </html>
Middleware

•   process_request(self, request)
•   process_view(self, request, view_func,
      view_args, view_kwargs)
•   process_response(self, request, response)
•   process_exception(self, request, exception)
Testing Framework

•   doctests
•   unit tests
•   helpful stuff: fixtures, email test, “client”

    c = Client()
    response = c.post(‘/login’, user_dict)
Some Warts
•   No support for           •   REST/SOAP
    multiple databases           support lacking
•   Poor environment         •   “Explicit” but still tightly
    support (think rails)        coupled for some things
•   Template logic tags      •   No integrated
    below average                deployment toolchain
•   No built-in migrations   •   CMS extras lacking
                                 (wysiwyg, file browser...)
•   Too big?
Rest of the stack

•   Databases        •       Deployment
    •   SQLite           •    mod_python
    •   MySQL            •    mod_wsgi
    •   Postgresql       •    fast cgi
    •   Oracle
Tips
•   virtualenv is your friend
•   default settings.py is about 50% of what a
    production site ends up requiring
•   local_settings.py
•   Don’t be afraid of lots of apps
•   ‘South’ is a solid migrations tool
Docs, Books, People

•   docs.djangoproject.com
•   djangobook.com
•   djangosnippets.com
•   djangopeople.net
•   djangosites.org
Code Samples


•   http://bitbucket.org/btol45/grpug-example/

Django Overview

  • 1.
  • 2.
    A bit aboutme • Programmer @ 5Q Communications • Hack on Django mostly full-time • Dozen+ sites in production • Calvin grad
  • 4.
    A bit aboutDjango • Named after Django Reinhart, jazz guitarist • Python 2.3+ (Not 3.x yet, afiak) • BSD license • djangoproject.com • Current release: 1.1
  • 6.
    Who uses it? • NASA • PBS • NY Times • LA Times • National Geographic • Discovery Channel
  • 7.
    Features • Object-Relational • i18n/unicode support Mapper • Cache framework • MVC architecture • Testing framework • Templating Language • Great docs (650+ pages) • “Automatic” admins • Friendly community • Elegant urls
  • 8.
    More Features • Jython support • Built-in RSS/ATOM • Geospacial content • Built-in site maps (via GeoDjango) • Send emails easily • Built-in dev server • “Signal” hooks • Nice support • Solid security emphasis for forms
  • 9.
    Projects and Apps Settings:database, App Live anywhere in your email, caching, etc. Project PYTHONPATH App HTML, CSS, App images, etc. Templates & Assets App
  • 10.
    Typical Project Layout project/ __init__.py settings.py manage.py urls.py templates/ static/ staff_members/ __init__.py models.py admin.py views.py urls.py tests.py templates/
  • 11.
    Typical App Workflow 1.Create app 2. Create models.py and admin.py 3. ‘python manage.py syncdb’ 4. Create urls.py and views.py
  • 12.
    class StaffMemberGroup(models.Model): name = models.CharField(blank=True, max_length=100) order = models.IntegerField(blank=True, null=True) class StaffMember(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) title = models.CharField(blank=True, max_length=100) bio = models.TextField(blank=True) image = models.FileField(upload_to='bio_images', blank=True) email = models.EmailField() published = models.BooleanField() staff_group = models.ForeignKey(StaffMemberGroup)
  • 13.
    python manage.py syncdb 1.Create tables 2. Create basic indexes 3. Create intermediate tables for m2m relationships
  • 14.
    bob = StaffMember(first_name=”Bob”,last_name=”Smith”) members = StaffMember.objects.all() ordered_members = StaffMember.objects.all().order_by(‘last_name’) published_members = StaffMember.objects.filter(published=True)
  • 15.
    groups = StaffMemberGroup.objects.all() forgroup in groups: print group.name for member in group.staffmember_set.all(): print member.first_name
  • 16.
    class StaffMemberAdmin(admin.ModelAdmin): list_display = ('last_name', 'first_name', 'email', 'published') list_filter = ('published', 'staff_group') search_fields = ('first_name', 'last_name', 'bio', 'title', 'email') fieldsets = ( (None, { 'fields': (('first_name', 'last_name'), 'title', 'email', 'image', 'bio'), 'description': '', }), ('Options', { 'fields': ('published', 'staff_group'), }) ) admin.site.register(StaffMember, StaffMemberAdmin)
  • 20.
    project urls.py urlpatterns =patterns('', (r'^staff_members/', include('grpug.staff_members.urls')), (r'^admin/doc/', include('django.contrib.admindocs.urls')), (r'^admin/(.*)', admin.site.root), ) staff_members app urls.py: urlpatterns = patterns('grpug.staff_members.views', url(r'^$', 'show_staff_members', name='staff-members'), )
  • 21.
    def show_staff_members(request): groups = StaffMemberGroup.objects.all() return render_to_response( 'staff_member.html', {'groups': groups} )
  • 22.
    staff_member.html {% for groupin groups %} <h2>{{group.name}}</h2> <ul> {% for member in group.staffmember_set.all %} <li> <h3>{{member.first_name}} {{member.last_name}}</h3> <p>{{member.bio}}</p> </li> {% endfor %} </ul> {% endfor %}
  • 23.
    staff_member.html {% extends ‘base_site.html’%} {% block content %} {% for group in groups %} <h2>{{group.name}}</h2> <ul> {% for member in group.staffmember_set.all %} <li> <h3>{{member.first_name}} {{member.last_name}}</h3> <p>{{member.bio}}</p> </li> {% endfor %} </ul> {% endfor %} {% endblock content %}
  • 24.
    base_site.html <html> <body> {% block content %} {% endblock content %} </body> </html>
  • 25.
    Middleware • process_request(self, request) • process_view(self, request, view_func, view_args, view_kwargs) • process_response(self, request, response) • process_exception(self, request, exception)
  • 26.
    Testing Framework • doctests • unit tests • helpful stuff: fixtures, email test, “client” c = Client() response = c.post(‘/login’, user_dict)
  • 27.
    Some Warts • No support for • REST/SOAP multiple databases support lacking • Poor environment • “Explicit” but still tightly support (think rails) coupled for some things • Template logic tags • No integrated below average deployment toolchain • No built-in migrations • CMS extras lacking (wysiwyg, file browser...) • Too big?
  • 28.
    Rest of thestack • Databases • Deployment • SQLite • mod_python • MySQL • mod_wsgi • Postgresql • fast cgi • Oracle
  • 29.
    Tips • virtualenv is your friend • default settings.py is about 50% of what a production site ends up requiring • local_settings.py • Don’t be afraid of lots of apps • ‘South’ is a solid migrations tool
  • 30.
    Docs, Books, People • docs.djangoproject.com • djangobook.com • djangosnippets.com • djangopeople.net • djangosites.org
  • 31.
    Code Samples • http://bitbucket.org/btol45/grpug-example/