SlideShare a Scribd company logo
1 of 139
Download to read offline
Introduction to Django

Jacob Kaplan-Moss

Strange Loop 2011
http://lanyrd.com/sfypm
Django Training

Part 1: Introduction to Django.
“Django is a high-level
Python web framework
 that encourages rapid
development and clean,



                     ”
   pragmatic design.


                          2
“Django is a high-level
Python web framework
 that encourages rapid
development and clean,



                     ”
   pragmatic design.


                          3
“Django is a high-level
Python web framework
 that encourages rapid
development and clean,



                     ”
   pragmatic design.


                          4
“Django is a high-level
Python web framework
 that encourages rapid
development and clean,



                     ”
   pragmatic design.


                          5
Documentation
           http://django.me/design
http://www.djangobook.com/en/2.0/chapter01/




                                              6
Which Django version
   should I use?


                       7
Installing Django

• Download and run http://bit.ly/dsetup
 (http://python-­‐distribute.org/distribute_setup.py)

• easy_install  Django
• Later: learn about pip and virtualenv
  http://pip.rtfd.org/
  http://virtualenv.rtfd.org/



                                                        8
“Projects”



             9
$  django-­‐admin.py  startproject  yabl




                                           10
yabl/
   __init__.py
   manage.py
   settings.py
   urls.py




                 11
$  python  manage.py  runserver
Validating  models...
0  errors  found.

Django  version  1.1  beta  1  SVN-­‐10844,  using  settings  'yabl.settings'
Development  server  is  running  at  http://127.0.0.1:8000/
Quit  the  server  with  CONTROL-­‐C.




                                                                                12
13
Project settings

• DATABASE_ENGINE
• DATABASE_NAME
• DATABASE_USER
• DATABASE_PASSWORD
• DATABASE_HOST


                      14
$  python  manage.py  syncdb
Creating  table  auth_permission
Creating  table  auth_group
Creating  table  auth_user
Creating  table  auth_message
Creating  table  django_content_type
Creating  table  django_session
Creating  table  django_site

You  just  installed  Django's  auth  system,  
which  means  you  don't  have  any  superusers  defined.
Would  you  like  to  create  one  now?  (yes/no):  yes
Username  (Leave  blank  to  use  'jacob'):  jacob
E-­‐mail  address:  jacob@jacobian.org
Password:  
Password  (again):  
Superuser  created  successfully.
Installing  index  for  auth.Permission  model
Installing  index  for  auth.Message  model


                                                            15
Documentation
http://django.me/about-settings
    http://django.me/settings
  http://django.me/manage.py




                                  16
Exercise:
  “it worked!”




                 17
Django Training

Part 2: Apps, models, and the admin
“Apps”



         2
“Models”



           3
What’s a model?



                  4
MVC?
(Model-View-Controller)




                          5
CREATE  TABLE  "entries_entry"  (
        "id"  integer  NOT  NULL  PRIMARY  KEY,
        "author_id"  integer  NOT  NULL,
        "pub_date"  datetime  NOT  NULL,
        "headline"  varchar(200)  NOT  NULL,
        "slug"  varchar(50)  NOT  NULL  UNIQUE,
        "summary"  text  NOT  NULL,
        "body"  text  NOT  NULL
)




                                                  6
Scary Quirky Language

• SQL is tough
• SQL knows no version control
• DRY
• Python is fun!



                                 7
import  datetime
from  django.db  import  models
from  yabl.authors.models  import  Author

class  Entry(models.Model):
        author              =  models.ForeignKey(Author,  related_name='entries')
        pub_date          =  models.DateTimeField(default=datetime.datetime.now)
        headline          =  models.CharField(max_length=200)
        slug                  =  models.SlugField(unique=True)
        summary            =  models.TextField()
        body                  =  models.TextField()




                                                                                    8
Defining Models



                 9
$  python  manage.py  startapp  authors




                                          10
authors/
   __init__.py
   models.py
   tests.py
   views.py




                 11
INSTALLED_APPS  =  (
        "django.contrib.auth",
        "django.contrib.contenttypes",
        "django.contrib.sessions",  
        "django.contrib.sites",
        "yabl.authors",
)




                                         12
from  django.db  import  models

class  Author(models.Model):
        first_name    =  models.CharField(max_length=200)
        last_name      =  models.CharField(max_length=200)
        bio                  =  models.TextField(blank=True)




                                                               13
$  python  manage.py  validate
0  errors  found.




                                 14
$  python  manage.py  sqlall  authors
BEGIN;
CREATE  TABLE  "authors_author"  (
        "id"  integer  NOT  NULL  PRIMARY  KEY,
        "first_name"  varchar(200)  NOT  NULL,
        "last_name"  varchar(200)  NOT  NULL,
        "bio"  text  NOT  NULL
);
COMMIT;




                                                  15
$  python  manage.py  syncdb
Creating  table  authors_author
Installing  index  for  authors.Author  model




                                                16
$  python  manage.py  shell

[1]  >>>  from  yabl.authors.models  import  Author

[2]  >>>  a  =  Author(first_name="John",  last_name="Barth")

[3]  >>>  a.save()




                                                                17
[4]  >>>  Author.objects.all()
[4]      :  [<Author:  Author  object>]

[5]  >>>  Author.objects.create(first_name='Miguel',  last_name='de  Cervantes')
[5]      :  <Author:  Author  object>

[6]  >>>  Author.objects.all()
[6]      :  [<Author:  Author  object>,  <Author:  Author  object>]

[7]  >>>  al  =  Author.objects.filter(first_name='John')

[8]  >>>  al[0].last_name
[8]      :  u'Barth'

[9]  >>>  Author.objects.get(last_name__startswith='de').first_name
[9]      :  u'Miguel'




                                                                                   18
Model metadata



                 19
class  Author(models.Model):
        first_name    =  models.CharField(max_length=200)
        last_name      =  models.CharField(max_length=200)
        bio                  =  models.TextField(blank=True)
        
        def  __unicode__(self):
                return  '%s  %s'  %  (self.first_name,  self.last_name)




                                                                          20
class  Author(models.Model):
        …

        class  Meta:
                verbose_name_plural  =  'authors'
                ordering  =  ['last_name',  'first_name']




                                                            21
[1]  >>>  from  yabl.authors.models  import  Author

[2]  >>>  Author.objects.all()
[2]      :  [<Author:  John  Barth>,  <Author:  Miguel  de  Cervantes>]

[3]  >>>  Author.objects.order_by('-­‐first_name')
[3]      :  [<Author:  Miguel  de  Cervantes>,  <Author:  John  Barth>]




                                                                          22
Documentation
          http://django.me/models
http://www.djangobook.com/en/2.0/chapter05/




                                              23
Exercise:
            Write some apps and some models:


• Author (authors app)       • Entry (entries app)
  • first_name (CharField)      • author (ForeignKey)
  • last_name (CharField)      • pub_date (DateTimeField)
  • bio (TextField)            • is_published (BooleanField)
                               • headline (CharField)
                               • slug (SlugField)
                               • summary (TextField)
                               • body (TextField)




                                                               24
Django’s
admin interface


                  25
“ A Web-based interface,
   limited to trusted site
administrators, that enables
  the adding, editing and




                                           ”
  deletion of site content.

             — The Django Book
            http://djangobook.com/en/2.0/chapter06/

                                                      26
from  django.contrib  import  admin
from  yabl.authors.models  import  Author

admin.site.register(Author)




                                            27
INSTALLED_APPS  =  (
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
        'django.contrib.admin',
        'yabl.authors',
        'yabl.entries',
)




                                         28
$  python  manage.py  syncdb
Creating  table  django_admin_log
Installing  index  for  admin.LogEntry  model




                                                29
from  django.conf.urls.defaults  import  *

#  Uncomment  the  next  two  lines  to  enable  the  admin:
from  django.contrib  import  admin
admin.autodiscover()

urlpatterns  =  patterns('',
        #  Example:
        #  (r'^yabl/',  include('yabl.foo.urls')),

        #  Uncomment  the  admin/doc  line  below  and  add  'django.contrib.admindocs'  
        #  to  INSTALLED_APPS  to  enable  admin  documentation:
        #  (r'^admin/doc/',  include('django.contrib.admindocs.urls')),

        #  Uncomment  the  next  line  to  enable  the  admin:
        (r'^admin/',  include(admin.site.urls)),
)




                                                                                            30
31
32
33
34
from  django.contrib  import  admin
from  yabl.authors.models  import  Author

class  AuthorAdmin(admin.ModelAdmin):
        pass

admin.site.register(Author,  AuthorAdmin)




                                            35
Documentation
http://djangobook.com/en/2.0/chapter06/
          http://django.me/admin




                                          36
Exercise:




            37
Django Training

Part 3: URLs, views, and templates
Views



        2
What’s a view?



                 3
4
URLs



       5
page.php

script.cgi?pageid=144

   StoryPage.aspx
                        6
0,2097,1-1-30-72-407-4752,00.html




                                    7
/authors/
/authors/jacob/
/authors/adrian/


                   8
ROOT_URLCONF  =  "yabl.urls"




                               9
yabl/urls.py

from  django.conf.urls.defaults  import  *

#  Uncomment  the  next  two  lines  to  enable  the  admin:
from  django.contrib  import  admin
admin.autodiscover()

urlpatterns  =  patterns('',
        (r'^authors/$',                  'yabl.authors.views.author_list'),
        (r'^authors/(d+)/$',      'yabl.authors.views.author_detail'),
        (r'^admin/',  include(admin.site.urls)),
)



                                                                              10
yabl/authors/urls.py


from  django.conf.urls.defaults  import  *

urlpatterns  =  patterns('',
        (r'^$',                  'yabl.authors.views.author_list'),
        (r'^(d+)/$',      'yabl.authors.views.author_detail'),
)




                                                                      11
yabl/urls.py

from  django.conf.urls.defaults  import  *

#  Uncomment  the  next  two  lines  to  enable  the  admin:
from  django.contrib  import  admin
admin.autodiscover()

urlpatterns  =  patterns('',
        (r'^authors/',  include('yabl.authors.urls')),
        (r'^admin/',      include(admin.site.urls)),
)




                                                               12
Regex crash course
a                    The letter “a”.
a+                   One or more “a”s.
b?                   Zero or one “b”s.
c{1,3}               One, two, or three “c”s.
.                    Any single character.
[abc]                Either an “a”, “b”, or “c”.
[A-­‐Z]              Any character between “A” and “Z”.
[A-­‐Za-­‐z0-­‐9]?   Zero or one letters “A-Z”, “a-z”, or “0-9”.
(d{3,4})            A group containing three or four digits.
(w*)                A group containing zero or more word characters (letters/digits).
[^/]+                One or more characters until (and not including) a forward slash.
^(joe|bob)           A string starting with “joe” or “bob”.
(?P<id>d+)          A group named “id” containing one or more digits.
article/$            A string ending with “article/”

                                                                                         13
Dissecting a request
• GET  /authors/1/
• ROOT_URLCONF
• yabl.urls
• (r'^authors/',  include('yabl.authors.urls'))
• yabl.authors.urls
• (r'^$',  'author_list')                    (no match)
• (r'^(d+)/',  'author_detail')      (match!)
• author_detail(request,  '1')
                                                          14
Documentation
  http://django.me/urls




                          15
A first view



              16
yabl/authors/views.py


from  django.http  import  HttpResponse

def  author_list(request):
        return  HttpResponse("This  is  the  author  list!")




                                                               17
yabl/authors/views.py

from  django.http  import  HttpResponse
from  yabl.authors.models  import  Author

def  author_list(request):
        r  =  "<ul>"
        for  a  in  Author.objects.all():
                r  +=  "<li>%s</li>"  %  a.name
        r  +=  "</ul>"
        return  HttpResponse(r)




                                                  18
yabl/authors/views.py

from  django  import  template
from  django.http  import  HttpResponse
from  yabl.authors.models  import  Author

def  author_list(request):
        as  =  Author.objects.all()
        tmpl  =  template.loader.get_template("authors/index.html")
        context  =  template.Context({"authors":  as})
        return  HttpResponse(tmpl.render(context))




                                                                      19
yabl/authors/views.py


from  django.shortcuts  import  render
from  yabl.authors.models  import  Author

def  author_list(request):
        context  =  {"authors"  :  Author.objects.all()}
        return  render(request,  "authors/index.html",  context)




                                                                   20
yabl/authors/views.py

from  django.http  import  Http404
from  django.shortcuts  import  render_to_response
from  yabl.authors.models  import  Author

def  author_detail(request,  author_id):
        try:
                author  =  Author.objects.get(id=author_id)
        except  Author.DoesNotExist:
                raise  Http404()

        return  render(request,  "authors/detail.html",  {"author"  :  author})



                                                                                  21
yabl/authors/views.py


from  django.shortcuts  import  render_to_response,  get_object_or_404
from  yabl.authors.models  import  Author

def  author_detail(request,  author_id):
        author  =  get_object_or_404(Author,  id=author_id)
        return  render(request,  "authors/detail.html",  {"author"  :  author})




                                                                                  22
Templates



            23
What’s a template?



                     24
<!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN">
<html  lang="en">
<head><title>Authors</title></head>
<body>
   <h1>Authors  ({{  authors|length  }}  total)</h1>
   <ul>
      {%  for  a  in  authors  %}
          <li>
             <a  href="{{  a.id  }}/">{{  a.name  }}</a>
          </li>
      {%  endfor  %}
   </ul>
</body>
</html>




                                                            25
Where to templates go?

• In an app’s templates directory.
• In directories specified by
  settings.TEMPLATE_DIRS.
• ...



                                     26
TEMPLATE_DIRS  =  [
        '/path/to/some/templates/',
        '/path/to/some/more/other/templates/',
]




                                                 27
TEMPLATE_DIRS  =  [
        '/Users/jacob/Projects/stl-­‐django/yabl/templates/',
]




                                                                28
<!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN">
<html  lang="en">
<head><title>Authors</title></head>
<body>
   <h1>Authors  ({{  authors|length  }}  total)</h1>
   <ul>
      {%  for  a  in  authors  %}
          <li>
             <a  href="{{  a.id  }}/">{{  a.name  }}</a>
          </li>
      {%  endfor  %}
   </ul>
</body>
</html>




                                                            29
The magic dot


• a["name"]
• a.name
• a.name()




                30
<!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN">
<html  lang="en">
<head><title>Authors</title></head>
<body>
   <h1>Authors  ({{  authors|length  }}  total)</h1>
   <ul>
      {%  for  a  in  authors  %}
          <li>
             <a  href="{{  a.id  }}/">{{  a.name  }}</a>
          </li>
      {%  endfor  %}
   </ul>
</body>
</html>




                                                            31
{{  text|escape|linkbreaks  }}




                                 32
{{  text|truncatewords:"30"  }}




                                  33
<!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN">
<html  lang="en">
<head><title>Authors</title></head>
<body>
   <h1>Authors  ({{  authors|length  }}  total)</h1>
   <ul>
      {%  for  a  in  authors  %}
          <li>
             <a  href="{{  a.id  }}/">{{  a.name  }}</a>
          </li>
      {%  endfor  %}
   </ul>
</body>
</html>




                                                            34
Template inheritance



                       35
<!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN">
<html  lang="en">
<head>
   <title>
      {%  block  title  %}YABL{%  endblock  %}
   </title>
</head>
<body>
   <div  id="content">
      {%  block  content  %}{%  endblock  %}
   </div>
   <div  id="footer">
      {%  block  footer  %}Copyright  blah..{%  endblock  %}
   </div>
</body>
</html>




                                                               36
<!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN">
<html  lang="en">
<head>
   <title>
      {%  block  title  %}YABL{%  endblock  %}
   </title>
</head>
<body>
   <div  id="content">
      {%  block  content  %}{%  endblock  %}
   </div>
   <div  id="footer">
      {%  block  footer  %}Copyright  blah..{%  endblock  %}
   </div>
</body>
</html>




                                                               37
{%  extends  "base.html"  %}

{%  block  title  %}
    Authors  |  {{  block.super  }}
{%  endblock  %}

{%  block  content  %}
    <h1>Authors  ({{  authors|length  }}  total)</h1>
    <ul>
       {%  for  a  in  authors  %}
           <li>
              <a  href="{{  a.id  }}/">{{  a.name  }}</a>
           </li>
       {%  endfor  %}
    </ul>
{%  endblock  %}




                                                            38
!                                 "

                                                                        93&45;
!"#$%&$'()#*+,)$-.$'$/0123&45*#"6         !"#$%&$'()#*+,)$23&45*#"6
                                                                        93$,(;
                                                                        ##9&0&5$;
!"#+5718#&0&5$#"6
##!!#)$1&07'2&0&5$#66
                                      $   !"#+5718#&0&5$#"6
                                          ##ABC7/5(2174
                                                                        ####!"#+5718#&0&5$#"6!"#$'(+5718#"6
                                                                        ##9<&0&5$;
!"#$'(+5718#"6                            !"#$'(+5718#"6
                                                                        9<3$,(;
                                                                        9+7(>;
!"#+5718#17'&$'&#"6                       !"#+5718#/,05#"6
                                                                        ##9(0G#0(H*/,05*;
##93:;!!#)$1&07'2&0&5$#669<3:;            ##9D5;
                                                                        ####!"#+5718#/,05#"6!"#$'(+5718#"6
##!"#=7/#)&7/>#0'#)&7/>-50)&#"6           ####950;E74$9<50;
                                                                        ##9<(0G;
####93?;!!#)&7/>23$,(50'$#669<3?;         ####950;A71,5#'$F)9<50;
                                                                        ##9(0G#0(H*17'&$'&*;
####9@;!!#)&7/>2&$,)$#66                  ####222
                                                                        ####!"#+5718#17'&$'&#"6!"#$'(+5718#"6
##!"#$'(=7/#"6                            ##9<D5;
                                                                        ##9<(0G;
!"#$'(+5718#"6                            !"#$'(+5718#"6
                                                                        9<+7(>;
                 section_index.html                 base_generic.html   9<3&45;                      base.html



                                      #



                                                                                                            39
Why?



       40
Inheritance tips
• {% extends %} must be the first thing in
  your template.
• More {% block %}s are better.
• If you’re duplicating content, you’re
  missing a block.
• {{ block.super }}


                                            41
Documentation
http://djangobook.com/en/2.0/chapter04/
        http://django.me/templates




                                          42
Exercise:
   /authors/
 /authors/{id}/

    /entries/
 /entries/{slug}/



                    43
Django training

BONUS: Models and queries
Terminology



              2
Models
a.k.a. “DDL”




               3
Managers
 a.k.a. “table”




                  4
QuerySets
 a.k.a. “selection”




                      5
Model instances
     a.k.a. “row”




                    6
!!!"!"#$#%&'()*+,-./'"*012'.(31"456,21"7.8$9(6.:
!!!"!"
#$%&'()*"+,&"-.'/0"123!4"$%&'()*"523"-.'/0"6,&!7

!!!".#$#!";<=
!!!".
$%&'()*"+,&"-.'/0"123!




  Model      Manager     QuerySet    Instance


                                                   7
Models



         8
Instance methods

class  Entry(models.Model):
        …

        def  is_by_jacob(self):
                return  "jacob"  in  self.author.name.lower()

…

[1]  >>>  e  =  Entry.objects.get(pk=1)

[2]  >>>  e.is_by_jacob()
[2]      :  False


                                                                9
“Special” instance methods




                             10
__unicode__

class  Entry(models.Model):
        …

        def  __unicode__(self):
                return  self.headline

…

[1]  >>>  Entry.objects.all()
[1]      :  [<Entry:  Man  bites  dog>,  <Entry:  Dog  bites  man>]




                                                                      11
save


class  Entry(models.Model):
        …

        def  save(self,  **kwargs):
                self.word_count  =  count_words(self.body)
                super(Entry,  self).save(**kwargs)




                                                             12
save


class  Entry(models.Model):
        …

        def  save(self,  **kwargs):
                self.word_count  =  count_words(self.body)
                super(Entry,  self).save(**kwargs)



                              Don’t forget this part!

                                                             13
delete


class  Author(models.Model):
        …

        def  delete(self):
                nobody  =  Author.objects.get(first_name='<NOBODY>')
                self.entries.update(author=nobody)
                super(Author,  self).delete()




                                                                       14
Managers



           15
Default manager

class  Entry(models.Model):
        …

        objects  =  models.Manager()

…

[1]  >>>  from  yabl.entries.models  import  Entry

[2]  >>>  Entry.objects
[2]      :  <django.db.models.manager.Manager  object  at  0x7eca70>



                                                                       16
Custom managers

class  EntryManager(models.Manager):
        def  future(self):
                …
        def  past(self):
                …

class  Entry(models.Model):
        …

        objects  =  EntryManager()




                                       17
[1]  >>>  from  yabl.entries.models  import  Entry

[2]  >>>  Entry.objects.future()
[2]      :  [<Entry:  Hi>]

[3]  >>>  Entry.objects.past()
[3]      :  [<Entry:  Man  bites  dog>,  <Entry:  Dog  bites  man>]




                                                                      18
Documentation
 http://django.me/managers




                             19
QuerySets



            20
Filters

[1]  >>>  Author.objects.filter(first_name='Jacob')
[1]      :  [<Author:  Jacob  Kaplan-­‐Moss>]

[2]  >>>  Author.objects.filter(last_name__contains='s')
[2]      :  [<Author:  Miguel  de  Cervantes>,  <Author:  Jacob  Kaplan-­‐Moss>]

[3]  >>>  Author.objects.filter(last_name__contains='s',  first_name='Miguel')
[3]      :  [<Author:  Miguel  de  Cervantes>]

[4]  >>>  Author.objects.filter(last_name__contains='s').filter(first_name='Miguel')
[4]      :  [<Author:  Miguel  de  Cervantes>]




                                                                                       21
Field lookups
exact,  iexact                  name__exact='Joe'
contains,  icontains            name__icontains='s'

startswith,  endswith,  
                                name__endswith='nd'
istartswith,  iendswith

                                name__in=('Joe',  'Jane')
in
                                author__in=Author.objects.filter(…)

gt,  gte,  lt,  lte             cost__gt=100

                                cost__range=(100,  500)
range
                                date__range=(now,  tomrrow)

                                date__year=2009
year,  month,  day,  week_day
                                date__month=7

isnull                          author__isnull=True
regex,  iregex                  name__regex='^J.*b$'

                                                                      22
Following relationships


[1]  >>>  Entry.objects.filter(author__first_name__startswith='J')
[1]      :  [<Entry:  Hi>]

[2]  >>>  Author.objects.filter(entries__headline='Hi')
[2]      :  [<Author:  Jacob  Kaplan-­‐Moss>]


                                 Where’d that come from?

                                                                     23
related_name


class  Entry(models.Model):
        author  =  models.ForeignKey(Author,  related_name='entries')




                                                                        24
select_related()
[1]  >>>  e  =  Entry.objects.get(pk=1)

[2]  >>>  e.author
[2]      :  <Author:  Jacob  Kaplan-­‐Moss>

Oops,  that  did  a  second,  needless  query.

[3]  >>>  e  =  Entry.objects.select_related().get(pk=1)

[4]  >>>  e.author
[5]      :  <Author:  Jacob  Kaplan-­‐Moss>

No  second  query  needed  for  e.author


                                                           25
Limiting select_related()


[1]  >>>  Entry.objects.select_related('author',  'category')

[2]  >>>  Entry.objects.select_related(depth=2)




                                                                26
QuerySet details



                   27
QuerySets are chainable


[1]  >>>  Entry.objects.filter(
    ....:          headline__contains='bites',
    ....:  ).exclude(
    ....:          pub_date__year=2008
    ....:  ).filter(
    ....:          pub_date__month=9
    ....:  )




                                                 28
QuerySets are unique


[1]  >>>  qs1  =  Entry.objects.filter(headline__icontains='dog')

[2]  >>>  qs2  =  qs1.exclude(pub_date__year=2008)

[3]  >>>  qs3  =  qs1.filter(pub_date__year=2008)




                                                                    29
QuerySets are lazy

[1]  >>>  qs  =  Entry.objects.filter(headline__icontains='dog')

[2]  >>>  qs  =  qs.exclude(pub_date__year=2008)

[3]  >>>  qs  =  qs.filter(author__first_name='Jacob')

[4]  >>>  qs
[4]      :  [<Entry:  Man  bites  dog>,  <Entry:  Dog  bites  man>]




                                                                      30
When QuerySets are evaluated


• Iteration   for  i  in  qs


• Slicing     qs[0:5]


• Printing    print  qs,  str(qs)


• len()       len(qs)


• list()      list(qs)




                                    31
Chainable methods
filter(),  exclude()       qs.filter(name='Joe')

order_by()                 qs.order_by('-­‐first_name')

reverse()                  qs.reverse()

distinct()                 qs.distinct()

values(),  values_list()   qs.values('first_name',  'last_name')

                           qs.dates('pub_date',  'year')
dates()
                           qs.dates('pub_date',  'month')

select_related()           qs.select_related()

                           qs.defer('body')
defer(),  only()
                           qs.only('body',  'headline')

                           qs.all()
none(),  all()
                           qs.none()

                                                                   32
Other QuerySet methods
get()             e  =  Entry.objects.get(…)


create()          e  =  Entry.objects.create(…)


get_or_create()   e,  created  =  Entry.objects.get_or_create(…)


count()           Entry.objects.count()


in_bulk()         Entry.objects.in_bulk([1,  2,  3])



latest()          Entry.objects.latest('pub_date')



                                                                   33
Raw SQL


[1]  >>>  query  =  "SELECT  *  FROM  authors_author  WHERE  first_name  =  %s"

[2]  >>>  params  =  ["Jacob"]

[3]  >>>  Entry.objects.raw(query,  params)
[3]          [<Person:  Jacob  Kaplan-­‐Moss>]




                                                                                  34
Entry.objects.raw(query  %  params)




        No!                           35
Other topics



               36
Aggregation
http://jacobian.org/r/django-aggregation




                                           37
Transaction control
 http://jacobian.org/r/django-transactions




                                             38
Exercise:
 /entries/future/
  /entries/past/




                    39
What else?
• Forms, model forms, form sets, ...
• File storage - local and remote.
• Cookies, sessions, authn/authz.
• GeoDjango
• Built-in SQLi, XSS and CSRF protection.
• i18n and l10n support.
• Generic views,
• &c!


                                            1
Thank you!
 jacob@jacobian.org


http://lanyrd.com/sfypm




                          2

More Related Content

What's hot

Getting started with Django 1.8
Getting started with Django 1.8Getting started with Django 1.8
Getting started with Django 1.8rajkumar2011
 
The effective use of Django ORM
The effective use of Django ORMThe effective use of Django ORM
The effective use of Django ORMYaroslav Muravskyi
 
Django Performance Recipes
Django Performance RecipesDjango Performance Recipes
Django Performance RecipesJon Atkinson
 
High Performance Django
High Performance DjangoHigh Performance Django
High Performance DjangoDjangoCon2008
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010ikailan
 
Moving from Django Apps to Services
Moving from Django Apps to ServicesMoving from Django Apps to Services
Moving from Django Apps to ServicesCraig Kerstiens
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2fishwarter
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Eric Palakovich Carr
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Kris Wallsmith
 
Maintainable JavaScript 2012
Maintainable JavaScript 2012Maintainable JavaScript 2012
Maintainable JavaScript 2012Nicholas Zakas
 
Let's write secure drupal code! - Drupal Camp Pannonia 2019
Let's write secure drupal code! - Drupal Camp Pannonia 2019Let's write secure drupal code! - Drupal Camp Pannonia 2019
Let's write secure drupal code! - Drupal Camp Pannonia 2019Balázs Tatár
 
Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Kris Wallsmith
 
Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019Balázs Tatár
 

What's hot (20)

Getting started with Django 1.8
Getting started with Django 1.8Getting started with Django 1.8
Getting started with Django 1.8
 
The effective use of Django ORM
The effective use of Django ORMThe effective use of Django ORM
The effective use of Django ORM
 
Django Performance Recipes
Django Performance RecipesDjango Performance Recipes
Django Performance Recipes
 
High Performance Django
High Performance DjangoHigh Performance Django
High Performance Django
 
OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010OSCON Google App Engine Codelab - July 2010
OSCON Google App Engine Codelab - July 2010
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
 
Moving from Django Apps to Services
Moving from Django Apps to ServicesMoving from Django Apps to Services
Moving from Django Apps to Services
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!Django Rest Framework and React and Redux, Oh My!
Django Rest Framework and React and Redux, Oh My!
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3
 
Maintainable JavaScript 2012
Maintainable JavaScript 2012Maintainable JavaScript 2012
Maintainable JavaScript 2012
 
Django
DjangoDjango
Django
 
Let's write secure drupal code! - Drupal Camp Pannonia 2019
Let's write secure drupal code! - Drupal Camp Pannonia 2019Let's write secure drupal code! - Drupal Camp Pannonia 2019
Let's write secure drupal code! - Drupal Camp Pannonia 2019
 
Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)
 
Ant
AntAnt
Ant
 
Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019Let's write secure Drupal code! DUG Belgium - 08/08/2019
Let's write secure Drupal code! DUG Belgium - 08/08/2019
 
Assetic (Zendcon)
Assetic (Zendcon)Assetic (Zendcon)
Assetic (Zendcon)
 
Ant
Ant Ant
Ant
 
WordPress and Ajax
WordPress and AjaxWordPress and Ajax
WordPress and Ajax
 
Intro to-ant
Intro to-antIntro to-ant
Intro to-ant
 

Viewers also liked

A quick python_tour
A quick python_tourA quick python_tour
A quick python_tourcghtkh
 
Outside-In Development With Cucumber
Outside-In Development With CucumberOutside-In Development With Cucumber
Outside-In Development With CucumberBen Mabey
 
Make It Cooler: Using Decentralized Version Control
Make It Cooler: Using Decentralized Version ControlMake It Cooler: Using Decentralized Version Control
Make It Cooler: Using Decentralized Version Controlindiver
 
Prepare for JDK 9
Prepare for JDK 9Prepare for JDK 9
Prepare for JDK 9haochenglee
 
Introduction to Git for developers
Introduction to Git for developersIntroduction to Git for developers
Introduction to Git for developersDmitry Guyvoronsky
 
Two scoops of Django - Security Best Practices
Two scoops of Django - Security Best PracticesTwo scoops of Django - Security Best Practices
Two scoops of Django - Security Best PracticesSpin Lai
 
The WHY behind TDD/BDD and the HOW with RSpec
The WHY behind TDD/BDD and the HOW with RSpecThe WHY behind TDD/BDD and the HOW with RSpec
The WHY behind TDD/BDD and the HOW with RSpecBen Mabey
 

Viewers also liked (10)

A quick python_tour
A quick python_tourA quick python_tour
A quick python_tour
 
Outside-In Development With Cucumber
Outside-In Development With CucumberOutside-In Development With Cucumber
Outside-In Development With Cucumber
 
Capybara
CapybaraCapybara
Capybara
 
Make It Cooler: Using Decentralized Version Control
Make It Cooler: Using Decentralized Version ControlMake It Cooler: Using Decentralized Version Control
Make It Cooler: Using Decentralized Version Control
 
Prepare for JDK 9
Prepare for JDK 9Prepare for JDK 9
Prepare for JDK 9
 
Introduction to Git for developers
Introduction to Git for developersIntroduction to Git for developers
Introduction to Git for developers
 
Two scoops of Django - Security Best Practices
Two scoops of Django - Security Best PracticesTwo scoops of Django - Security Best Practices
Two scoops of Django - Security Best Practices
 
The WHY behind TDD/BDD and the HOW with RSpec
The WHY behind TDD/BDD and the HOW with RSpecThe WHY behind TDD/BDD and the HOW with RSpec
The WHY behind TDD/BDD and the HOW with RSpec
 
Jenkins CI
Jenkins CIJenkins CI
Jenkins CI
 
Git Branching Model
Git Branching ModelGit Branching Model
Git Branching Model
 

Similar to Introduction To Django (Strange Loop 2011)

The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 ModelsVincent Chien
 
Django tutorial 2009
Django tutorial 2009Django tutorial 2009
Django tutorial 2009Ferenc Szalai
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineYared Ayalew
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJames Casey
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to DjangoJoaquim Rocha
 
Django for mobile applications
Django for mobile applicationsDjango for mobile applications
Django for mobile applicationsHassan Abid
 
Zagreb workshop
Zagreb workshopZagreb workshop
Zagreb workshopLynn Root
 
Gae Meets Django
Gae Meets DjangoGae Meets Django
Gae Meets Djangofool2nd
 
Introduction Django
Introduction DjangoIntroduction Django
Introduction DjangoWade Austin
 
Mini Curso Django Ii Congresso Academico Ces
Mini Curso Django Ii Congresso Academico CesMini Curso Django Ii Congresso Academico Ces
Mini Curso Django Ii Congresso Academico CesLeonardo Fernandes
 
Behind the curtain - How Django handles a request
Behind the curtain - How Django handles a requestBehind the curtain - How Django handles a request
Behind the curtain - How Django handles a requestDaniel Hepper
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Python Ireland
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Hands on django part 1
Hands on django part 1Hands on django part 1
Hands on django part 1MicroPyramid .
 

Similar to Introduction To Django (Strange Loop 2011) (20)

Mini Curso de Django
Mini Curso de DjangoMini Curso de Django
Mini Curso de Django
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 Models
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Django tutorial 2009
Django tutorial 2009Django tutorial 2009
Django tutorial 2009
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
DJango
DJangoDJango
DJango
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
django
djangodjango
django
 
Django for mobile applications
Django for mobile applicationsDjango for mobile applications
Django for mobile applications
 
Django web framework
Django web frameworkDjango web framework
Django web framework
 
Zagreb workshop
Zagreb workshopZagreb workshop
Zagreb workshop
 
Gae Meets Django
Gae Meets DjangoGae Meets Django
Gae Meets Django
 
Introduction Django
Introduction DjangoIntroduction Django
Introduction Django
 
Mini Curso Django Ii Congresso Academico Ces
Mini Curso Django Ii Congresso Academico CesMini Curso Django Ii Congresso Academico Ces
Mini Curso Django Ii Congresso Academico Ces
 
Django tricks (2)
Django tricks (2)Django tricks (2)
Django tricks (2)
 
Behind the curtain - How Django handles a request
Behind the curtain - How Django handles a requestBehind the curtain - How Django handles a request
Behind the curtain - How Django handles a request
 
Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)Google App Engine in 40 minutes (the absolute essentials)
Google App Engine in 40 minutes (the absolute essentials)
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Hands on django part 1
Hands on django part 1Hands on django part 1
Hands on django part 1
 

More from Jacob Kaplan-Moss

Writing great documentation - CodeConf 2011
Writing great documentation - CodeConf 2011Writing great documentation - CodeConf 2011
Writing great documentation - CodeConf 2011Jacob Kaplan-Moss
 
Django Introduction, Dev in Rio 2009
Django Introduction, Dev in Rio 2009Django Introduction, Dev in Rio 2009
Django Introduction, Dev in Rio 2009Jacob Kaplan-Moss
 
Building a web framework: Django's design decisions
Building a web framework: Django's design decisionsBuilding a web framework: Django's design decisions
Building a web framework: Django's design decisionsJacob Kaplan-Moss
 
Django - the first five years
Django - the first five yearsDjango - the first five years
Django - the first five yearsJacob Kaplan-Moss
 
A brief history of Django model syntax
A brief history of Django model syntaxA brief history of Django model syntax
A brief history of Django model syntaxJacob Kaplan-Moss
 

More from Jacob Kaplan-Moss (10)

Writing great documentation - CodeConf 2011
Writing great documentation - CodeConf 2011Writing great documentation - CodeConf 2011
Writing great documentation - CodeConf 2011
 
What's new in Django 1.2?
What's new in Django 1.2?What's new in Django 1.2?
What's new in Django 1.2?
 
Django Introduction, Dev in Rio 2009
Django Introduction, Dev in Rio 2009Django Introduction, Dev in Rio 2009
Django Introduction, Dev in Rio 2009
 
Snakes on the Web
Snakes on the WebSnakes on the Web
Snakes on the Web
 
Django In The Real World
Django In The Real WorldDjango In The Real World
Django In The Real World
 
Building a web framework: Django's design decisions
Building a web framework: Django's design decisionsBuilding a web framework: Django's design decisions
Building a web framework: Django's design decisions
 
State Of Django
State Of DjangoState Of Django
State Of Django
 
Django - the first five years
Django - the first five yearsDjango - the first five years
Django - the first five years
 
A brief history of Django model syntax
A brief history of Django model syntaxA brief history of Django model syntax
A brief history of Django model syntax
 
Django Update (OSCON 2007)
Django Update (OSCON 2007)Django Update (OSCON 2007)
Django Update (OSCON 2007)
 

Recently uploaded

Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 

Recently uploaded (20)

Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 

Introduction To Django (Strange Loop 2011)

  • 1. Introduction to Django Jacob Kaplan-Moss Strange Loop 2011 http://lanyrd.com/sfypm
  • 2. Django Training Part 1: Introduction to Django.
  • 3. “Django is a high-level Python web framework that encourages rapid development and clean, ” pragmatic design. 2
  • 4. “Django is a high-level Python web framework that encourages rapid development and clean, ” pragmatic design. 3
  • 5. “Django is a high-level Python web framework that encourages rapid development and clean, ” pragmatic design. 4
  • 6. “Django is a high-level Python web framework that encourages rapid development and clean, ” pragmatic design. 5
  • 7. Documentation http://django.me/design http://www.djangobook.com/en/2.0/chapter01/ 6
  • 8. Which Django version should I use? 7
  • 9. Installing Django • Download and run http://bit.ly/dsetup (http://python-­‐distribute.org/distribute_setup.py) • easy_install  Django • Later: learn about pip and virtualenv http://pip.rtfd.org/ http://virtualenv.rtfd.org/ 8
  • 12. yabl/ __init__.py manage.py settings.py urls.py 11
  • 13. $  python  manage.py  runserver Validating  models... 0  errors  found. Django  version  1.1  beta  1  SVN-­‐10844,  using  settings  'yabl.settings' Development  server  is  running  at  http://127.0.0.1:8000/ Quit  the  server  with  CONTROL-­‐C. 12
  • 14. 13
  • 15. Project settings • DATABASE_ENGINE • DATABASE_NAME • DATABASE_USER • DATABASE_PASSWORD • DATABASE_HOST 14
  • 16. $  python  manage.py  syncdb Creating  table  auth_permission Creating  table  auth_group Creating  table  auth_user Creating  table  auth_message Creating  table  django_content_type Creating  table  django_session Creating  table  django_site You  just  installed  Django's  auth  system,   which  means  you  don't  have  any  superusers  defined. Would  you  like  to  create  one  now?  (yes/no):  yes Username  (Leave  blank  to  use  'jacob'):  jacob E-­‐mail  address:  jacob@jacobian.org Password:   Password  (again):   Superuser  created  successfully. Installing  index  for  auth.Permission  model Installing  index  for  auth.Message  model 15
  • 17. Documentation http://django.me/about-settings http://django.me/settings http://django.me/manage.py 16
  • 18. Exercise: “it worked!” 17
  • 19. Django Training Part 2: Apps, models, and the admin
  • 24. CREATE  TABLE  "entries_entry"  (        "id"  integer  NOT  NULL  PRIMARY  KEY,        "author_id"  integer  NOT  NULL,        "pub_date"  datetime  NOT  NULL,        "headline"  varchar(200)  NOT  NULL,        "slug"  varchar(50)  NOT  NULL  UNIQUE,        "summary"  text  NOT  NULL,        "body"  text  NOT  NULL ) 6
  • 25. Scary Quirky Language • SQL is tough • SQL knows no version control • DRY • Python is fun! 7
  • 26. import  datetime from  django.db  import  models from  yabl.authors.models  import  Author class  Entry(models.Model):        author              =  models.ForeignKey(Author,  related_name='entries')        pub_date          =  models.DateTimeField(default=datetime.datetime.now)        headline          =  models.CharField(max_length=200)        slug                  =  models.SlugField(unique=True)        summary            =  models.TextField()        body                  =  models.TextField() 8
  • 28. $  python  manage.py  startapp  authors 10
  • 29. authors/ __init__.py models.py tests.py views.py 11
  • 30. INSTALLED_APPS  =  (        "django.contrib.auth",        "django.contrib.contenttypes",        "django.contrib.sessions",          "django.contrib.sites",        "yabl.authors", ) 12
  • 31. from  django.db  import  models class  Author(models.Model):        first_name    =  models.CharField(max_length=200)        last_name      =  models.CharField(max_length=200)        bio                  =  models.TextField(blank=True) 13
  • 32. $  python  manage.py  validate 0  errors  found. 14
  • 33. $  python  manage.py  sqlall  authors BEGIN; CREATE  TABLE  "authors_author"  (        "id"  integer  NOT  NULL  PRIMARY  KEY,        "first_name"  varchar(200)  NOT  NULL,        "last_name"  varchar(200)  NOT  NULL,        "bio"  text  NOT  NULL ); COMMIT; 15
  • 34. $  python  manage.py  syncdb Creating  table  authors_author Installing  index  for  authors.Author  model 16
  • 35. $  python  manage.py  shell [1]  >>>  from  yabl.authors.models  import  Author [2]  >>>  a  =  Author(first_name="John",  last_name="Barth") [3]  >>>  a.save() 17
  • 36. [4]  >>>  Author.objects.all() [4]      :  [<Author:  Author  object>] [5]  >>>  Author.objects.create(first_name='Miguel',  last_name='de  Cervantes') [5]      :  <Author:  Author  object> [6]  >>>  Author.objects.all() [6]      :  [<Author:  Author  object>,  <Author:  Author  object>] [7]  >>>  al  =  Author.objects.filter(first_name='John') [8]  >>>  al[0].last_name [8]      :  u'Barth' [9]  >>>  Author.objects.get(last_name__startswith='de').first_name [9]      :  u'Miguel' 18
  • 38. class  Author(models.Model):        first_name    =  models.CharField(max_length=200)        last_name      =  models.CharField(max_length=200)        bio                  =  models.TextField(blank=True)                def  __unicode__(self):                return  '%s  %s'  %  (self.first_name,  self.last_name) 20
  • 39. class  Author(models.Model):        …        class  Meta:                verbose_name_plural  =  'authors'                ordering  =  ['last_name',  'first_name'] 21
  • 40. [1]  >>>  from  yabl.authors.models  import  Author [2]  >>>  Author.objects.all() [2]      :  [<Author:  John  Barth>,  <Author:  Miguel  de  Cervantes>] [3]  >>>  Author.objects.order_by('-­‐first_name') [3]      :  [<Author:  Miguel  de  Cervantes>,  <Author:  John  Barth>] 22
  • 41. Documentation http://django.me/models http://www.djangobook.com/en/2.0/chapter05/ 23
  • 42. Exercise: Write some apps and some models: • Author (authors app) • Entry (entries app) • first_name (CharField) • author (ForeignKey) • last_name (CharField) • pub_date (DateTimeField) • bio (TextField) • is_published (BooleanField) • headline (CharField) • slug (SlugField) • summary (TextField) • body (TextField) 24
  • 44. “ A Web-based interface, limited to trusted site administrators, that enables the adding, editing and ” deletion of site content. — The Django Book http://djangobook.com/en/2.0/chapter06/ 26
  • 45. from  django.contrib  import  admin from  yabl.authors.models  import  Author admin.site.register(Author) 27
  • 46. INSTALLED_APPS  =  (        'django.contrib.auth',        'django.contrib.contenttypes',        'django.contrib.sessions',        'django.contrib.sites',        'django.contrib.admin',        'yabl.authors',        'yabl.entries', ) 28
  • 47. $  python  manage.py  syncdb Creating  table  django_admin_log Installing  index  for  admin.LogEntry  model 29
  • 48. from  django.conf.urls.defaults  import  * #  Uncomment  the  next  two  lines  to  enable  the  admin: from  django.contrib  import  admin admin.autodiscover() urlpatterns  =  patterns('',        #  Example:        #  (r'^yabl/',  include('yabl.foo.urls')),        #  Uncomment  the  admin/doc  line  below  and  add  'django.contrib.admindocs'          #  to  INSTALLED_APPS  to  enable  admin  documentation:        #  (r'^admin/doc/',  include('django.contrib.admindocs.urls')),        #  Uncomment  the  next  line  to  enable  the  admin:        (r'^admin/',  include(admin.site.urls)), ) 30
  • 49. 31
  • 50. 32
  • 51. 33
  • 52. 34
  • 53. from  django.contrib  import  admin from  yabl.authors.models  import  Author class  AuthorAdmin(admin.ModelAdmin):        pass admin.site.register(Author,  AuthorAdmin) 35
  • 55. Exercise: 37
  • 56. Django Training Part 3: URLs, views, and templates
  • 57. Views 2
  • 59. 4
  • 60. URLs 5
  • 61. page.php script.cgi?pageid=144 StoryPage.aspx 6
  • 65. yabl/urls.py from  django.conf.urls.defaults  import  * #  Uncomment  the  next  two  lines  to  enable  the  admin: from  django.contrib  import  admin admin.autodiscover() urlpatterns  =  patterns('',        (r'^authors/$',                  'yabl.authors.views.author_list'),        (r'^authors/(d+)/$',      'yabl.authors.views.author_detail'),        (r'^admin/',  include(admin.site.urls)), ) 10
  • 66. yabl/authors/urls.py from  django.conf.urls.defaults  import  * urlpatterns  =  patterns('',        (r'^$',                  'yabl.authors.views.author_list'),        (r'^(d+)/$',      'yabl.authors.views.author_detail'), ) 11
  • 67. yabl/urls.py from  django.conf.urls.defaults  import  * #  Uncomment  the  next  two  lines  to  enable  the  admin: from  django.contrib  import  admin admin.autodiscover() urlpatterns  =  patterns('',        (r'^authors/',  include('yabl.authors.urls')),        (r'^admin/',      include(admin.site.urls)), ) 12
  • 68. Regex crash course a The letter “a”. a+ One or more “a”s. b? Zero or one “b”s. c{1,3} One, two, or three “c”s. . Any single character. [abc] Either an “a”, “b”, or “c”. [A-­‐Z] Any character between “A” and “Z”. [A-­‐Za-­‐z0-­‐9]? Zero or one letters “A-Z”, “a-z”, or “0-9”. (d{3,4}) A group containing three or four digits. (w*) A group containing zero or more word characters (letters/digits). [^/]+ One or more characters until (and not including) a forward slash. ^(joe|bob) A string starting with “joe” or “bob”. (?P<id>d+) A group named “id” containing one or more digits. article/$ A string ending with “article/” 13
  • 69. Dissecting a request • GET  /authors/1/ • ROOT_URLCONF • yabl.urls • (r'^authors/',  include('yabl.authors.urls')) • yabl.authors.urls • (r'^$',  'author_list')                    (no match) • (r'^(d+)/',  'author_detail')      (match!) • author_detail(request,  '1') 14
  • 72. yabl/authors/views.py from  django.http  import  HttpResponse def  author_list(request):        return  HttpResponse("This  is  the  author  list!") 17
  • 73. yabl/authors/views.py from  django.http  import  HttpResponse from  yabl.authors.models  import  Author def  author_list(request):        r  =  "<ul>"        for  a  in  Author.objects.all():                r  +=  "<li>%s</li>"  %  a.name        r  +=  "</ul>"        return  HttpResponse(r) 18
  • 74. yabl/authors/views.py from  django  import  template from  django.http  import  HttpResponse from  yabl.authors.models  import  Author def  author_list(request):        as  =  Author.objects.all()        tmpl  =  template.loader.get_template("authors/index.html")        context  =  template.Context({"authors":  as})        return  HttpResponse(tmpl.render(context)) 19
  • 75. yabl/authors/views.py from  django.shortcuts  import  render from  yabl.authors.models  import  Author def  author_list(request):        context  =  {"authors"  :  Author.objects.all()}        return  render(request,  "authors/index.html",  context) 20
  • 76. yabl/authors/views.py from  django.http  import  Http404 from  django.shortcuts  import  render_to_response from  yabl.authors.models  import  Author def  author_detail(request,  author_id):        try:                author  =  Author.objects.get(id=author_id)        except  Author.DoesNotExist:                raise  Http404()        return  render(request,  "authors/detail.html",  {"author"  :  author}) 21
  • 77. yabl/authors/views.py from  django.shortcuts  import  render_to_response,  get_object_or_404 from  yabl.authors.models  import  Author def  author_detail(request,  author_id):        author  =  get_object_or_404(Author,  id=author_id)        return  render(request,  "authors/detail.html",  {"author"  :  author}) 22
  • 78. Templates 23
  • 80. <!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN"> <html  lang="en"> <head><title>Authors</title></head> <body> <h1>Authors  ({{  authors|length  }}  total)</h1> <ul> {%  for  a  in  authors  %} <li> <a  href="{{  a.id  }}/">{{  a.name  }}</a> </li> {%  endfor  %} </ul> </body> </html> 25
  • 81. Where to templates go? • In an app’s templates directory. • In directories specified by settings.TEMPLATE_DIRS. • ... 26
  • 82. TEMPLATE_DIRS  =  [        '/path/to/some/templates/',        '/path/to/some/more/other/templates/', ] 27
  • 83. TEMPLATE_DIRS  =  [        '/Users/jacob/Projects/stl-­‐django/yabl/templates/', ] 28
  • 84. <!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN"> <html  lang="en"> <head><title>Authors</title></head> <body> <h1>Authors  ({{  authors|length  }}  total)</h1> <ul> {%  for  a  in  authors  %} <li> <a  href="{{  a.id  }}/">{{  a.name  }}</a> </li> {%  endfor  %} </ul> </body> </html> 29
  • 85. The magic dot • a["name"] • a.name • a.name() 30
  • 86. <!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN"> <html  lang="en"> <head><title>Authors</title></head> <body> <h1>Authors  ({{  authors|length  }}  total)</h1> <ul> {%  for  a  in  authors  %} <li> <a  href="{{  a.id  }}/">{{  a.name  }}</a> </li> {%  endfor  %} </ul> </body> </html> 31
  • 89. <!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN"> <html  lang="en"> <head><title>Authors</title></head> <body> <h1>Authors  ({{  authors|length  }}  total)</h1> <ul> {%  for  a  in  authors  %} <li> <a  href="{{  a.id  }}/">{{  a.name  }}</a> </li> {%  endfor  %} </ul> </body> </html> 34
  • 91. <!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN"> <html  lang="en"> <head> <title> {%  block  title  %}YABL{%  endblock  %} </title> </head> <body> <div  id="content"> {%  block  content  %}{%  endblock  %} </div> <div  id="footer"> {%  block  footer  %}Copyright  blah..{%  endblock  %} </div> </body> </html> 36
  • 92. <!DOCTYPE  HTML  PUBLIC  "-­‐//W3C//DTD  HTML  4.01//EN"> <html  lang="en"> <head> <title> {%  block  title  %}YABL{%  endblock  %} </title> </head> <body> <div  id="content"> {%  block  content  %}{%  endblock  %} </div> <div  id="footer"> {%  block  footer  %}Copyright  blah..{%  endblock  %} </div> </body> </html> 37
  • 93. {%  extends  "base.html"  %} {%  block  title  %} Authors  |  {{  block.super  }} {%  endblock  %} {%  block  content  %} <h1>Authors  ({{  authors|length  }}  total)</h1> <ul> {%  for  a  in  authors  %} <li> <a  href="{{  a.id  }}/">{{  a.name  }}</a> </li> {%  endfor  %} </ul> {%  endblock  %} 38
  • 94. ! " 93&45; !"#$%&$'()#*+,)$-.$'$/0123&45*#"6 !"#$%&$'()#*+,)$23&45*#"6 93$,(; ##9&0&5$; !"#+5718#&0&5$#"6 ##!!#)$1&07'2&0&5$#66 $ !"#+5718#&0&5$#"6 ##ABC7/5(2174 ####!"#+5718#&0&5$#"6!"#$'(+5718#"6 ##9<&0&5$; !"#$'(+5718#"6 !"#$'(+5718#"6 9<3$,(; 9+7(>; !"#+5718#17'&$'&#"6 !"#+5718#/,05#"6 ##9(0G#0(H*/,05*; ##93:;!!#)$1&07'2&0&5$#669<3:; ##9D5; ####!"#+5718#/,05#"6!"#$'(+5718#"6 ##!"#=7/#)&7/>#0'#)&7/>-50)&#"6 ####950;E74$9<50; ##9<(0G; ####93?;!!#)&7/>23$,(50'$#669<3?; ####950;A71,5#'$F)9<50; ##9(0G#0(H*17'&$'&*; ####9@;!!#)&7/>2&$,)$#66 ####222 ####!"#+5718#17'&$'&#"6!"#$'(+5718#"6 ##!"#$'(=7/#"6 ##9<D5; ##9<(0G; !"#$'(+5718#"6 !"#$'(+5718#"6 9<+7(>; section_index.html base_generic.html 9<3&45; base.html # 39
  • 95. Why? 40
  • 96. Inheritance tips • {% extends %} must be the first thing in your template. • More {% block %}s are better. • If you’re duplicating content, you’re missing a block. • {{ block.super }} 41
  • 98. Exercise: /authors/ /authors/{id}/ /entries/ /entries/{slug}/ 43
  • 104. Model instances a.k.a. “row” 6
  • 106. Models 8
  • 107. Instance methods class  Entry(models.Model):        …        def  is_by_jacob(self):                return  "jacob"  in  self.author.name.lower() … [1]  >>>  e  =  Entry.objects.get(pk=1) [2]  >>>  e.is_by_jacob() [2]      :  False 9
  • 109. __unicode__ class  Entry(models.Model):        …        def  __unicode__(self):                return  self.headline … [1]  >>>  Entry.objects.all() [1]      :  [<Entry:  Man  bites  dog>,  <Entry:  Dog  bites  man>] 11
  • 110. save class  Entry(models.Model):        …        def  save(self,  **kwargs):                self.word_count  =  count_words(self.body)                super(Entry,  self).save(**kwargs) 12
  • 111. save class  Entry(models.Model):        …        def  save(self,  **kwargs):                self.word_count  =  count_words(self.body)                super(Entry,  self).save(**kwargs) Don’t forget this part! 13
  • 112. delete class  Author(models.Model):        …        def  delete(self):                nobody  =  Author.objects.get(first_name='<NOBODY>')                self.entries.update(author=nobody)                super(Author,  self).delete() 14
  • 113. Managers 15
  • 114. Default manager class  Entry(models.Model):        …        objects  =  models.Manager() … [1]  >>>  from  yabl.entries.models  import  Entry [2]  >>>  Entry.objects [2]      :  <django.db.models.manager.Manager  object  at  0x7eca70> 16
  • 115. Custom managers class  EntryManager(models.Manager):        def  future(self):                …        def  past(self):                … class  Entry(models.Model):        …        objects  =  EntryManager() 17
  • 116. [1]  >>>  from  yabl.entries.models  import  Entry [2]  >>>  Entry.objects.future() [2]      :  [<Entry:  Hi>] [3]  >>>  Entry.objects.past() [3]      :  [<Entry:  Man  bites  dog>,  <Entry:  Dog  bites  man>] 18
  • 118. QuerySets 20
  • 119. Filters [1]  >>>  Author.objects.filter(first_name='Jacob') [1]      :  [<Author:  Jacob  Kaplan-­‐Moss>] [2]  >>>  Author.objects.filter(last_name__contains='s') [2]      :  [<Author:  Miguel  de  Cervantes>,  <Author:  Jacob  Kaplan-­‐Moss>] [3]  >>>  Author.objects.filter(last_name__contains='s',  first_name='Miguel') [3]      :  [<Author:  Miguel  de  Cervantes>] [4]  >>>  Author.objects.filter(last_name__contains='s').filter(first_name='Miguel') [4]      :  [<Author:  Miguel  de  Cervantes>] 21
  • 120. Field lookups exact,  iexact name__exact='Joe' contains,  icontains name__icontains='s' startswith,  endswith,   name__endswith='nd' istartswith,  iendswith name__in=('Joe',  'Jane') in author__in=Author.objects.filter(…) gt,  gte,  lt,  lte cost__gt=100 cost__range=(100,  500) range date__range=(now,  tomrrow) date__year=2009 year,  month,  day,  week_day date__month=7 isnull author__isnull=True regex,  iregex name__regex='^J.*b$' 22
  • 121. Following relationships [1]  >>>  Entry.objects.filter(author__first_name__startswith='J') [1]      :  [<Entry:  Hi>] [2]  >>>  Author.objects.filter(entries__headline='Hi') [2]      :  [<Author:  Jacob  Kaplan-­‐Moss>] Where’d that come from? 23
  • 122. related_name class  Entry(models.Model):        author  =  models.ForeignKey(Author,  related_name='entries') 24
  • 123. select_related() [1]  >>>  e  =  Entry.objects.get(pk=1) [2]  >>>  e.author [2]      :  <Author:  Jacob  Kaplan-­‐Moss> Oops,  that  did  a  second,  needless  query. [3]  >>>  e  =  Entry.objects.select_related().get(pk=1) [4]  >>>  e.author [5]      :  <Author:  Jacob  Kaplan-­‐Moss> No  second  query  needed  for  e.author 25
  • 124. Limiting select_related() [1]  >>>  Entry.objects.select_related('author',  'category') [2]  >>>  Entry.objects.select_related(depth=2) 26
  • 126. QuerySets are chainable [1]  >>>  Entry.objects.filter(    ....:          headline__contains='bites',    ....:  ).exclude(    ....:          pub_date__year=2008    ....:  ).filter(    ....:          pub_date__month=9    ....:  ) 28
  • 127. QuerySets are unique [1]  >>>  qs1  =  Entry.objects.filter(headline__icontains='dog') [2]  >>>  qs2  =  qs1.exclude(pub_date__year=2008) [3]  >>>  qs3  =  qs1.filter(pub_date__year=2008) 29
  • 128. QuerySets are lazy [1]  >>>  qs  =  Entry.objects.filter(headline__icontains='dog') [2]  >>>  qs  =  qs.exclude(pub_date__year=2008) [3]  >>>  qs  =  qs.filter(author__first_name='Jacob') [4]  >>>  qs [4]      :  [<Entry:  Man  bites  dog>,  <Entry:  Dog  bites  man>] 30
  • 129. When QuerySets are evaluated • Iteration for  i  in  qs • Slicing qs[0:5] • Printing print  qs,  str(qs) • len() len(qs) • list() list(qs) 31
  • 130. Chainable methods filter(),  exclude() qs.filter(name='Joe') order_by() qs.order_by('-­‐first_name') reverse() qs.reverse() distinct() qs.distinct() values(),  values_list() qs.values('first_name',  'last_name') qs.dates('pub_date',  'year') dates() qs.dates('pub_date',  'month') select_related() qs.select_related() qs.defer('body') defer(),  only() qs.only('body',  'headline') qs.all() none(),  all() qs.none() 32
  • 131. Other QuerySet methods get() e  =  Entry.objects.get(…) create() e  =  Entry.objects.create(…) get_or_create() e,  created  =  Entry.objects.get_or_create(…) count() Entry.objects.count() in_bulk() Entry.objects.in_bulk([1,  2,  3]) latest() Entry.objects.latest('pub_date') 33
  • 132. Raw SQL [1]  >>>  query  =  "SELECT  *  FROM  authors_author  WHERE  first_name  =  %s" [2]  >>>  params  =  ["Jacob"] [3]  >>>  Entry.objects.raw(query,  params) [3]          [<Person:  Jacob  Kaplan-­‐Moss>] 34
  • 137. Exercise: /entries/future/ /entries/past/ 39
  • 138. What else? • Forms, model forms, form sets, ... • File storage - local and remote. • Cookies, sessions, authn/authz. • GeoDjango • Built-in SQLi, XSS and CSRF protection. • i18n and l10n support. • Generic views, • &c! 1