Building a Dynamic
Website Using Django
        Nathan Eror
       Hush Labs, LLC




                        © 2007 Hush ...
Who am I?




            © 2007 Hush Labs, LLC
                               2
Let’s Build
Something!
              © 2007 Hush Labs, LLC
                                 3
Time to Get Started

1. Download and Install Python & Django
2. Install sqlite if you don’t have it yet
3. Crank up your e...
> django-admin.py startproject barcamplive
> cd barcamplive
> ./manage.py startapp liveblog
> mkdir -p templates public/up...
File: settings.py


DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'barcamplive.db'
import os.path, sys
PROJECT_ROOT = os.pat...
Start With the
 Data Model

                 © 2007 Hush Labs, LLC
                                    7
File: liveblog/.py

from django.db import models
from django.contrib.auth.models import User
from datetime import datetime...
postgresql mysql sqlite
                        oracle mssql
>>> u = User.objects.get(username='admin')


       Django Mo...
> ./manage.py syncdb
> ./manage.py runserver




                          © 2007 Hush Labs, LLC
                         ...
The Django
Admin Site

             © 2007 Hush Labs, LLC
                               11
© 2007 Hush Labs, LLC
                  12
Django URLs

              © 2007 Hush Labs, LLC
                                13
File: urls.py


from django.conf.urls.defaults import *
from django.conf import settings

urlpatterns = patterns('',
  # E...
© 2007 Hush Labs, LLC
                  15
File: settings.py


DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'barcamplive.db'
import os.path, sys
PROJECT_ROOT = os.pat...
© 2007 Hush Labs, LLC
                  17
© 2007 Hush Labs, LLC
                  18
File: liveblog/models.py

class Post(models.Model):
  title = models.CharField(blank=False, null=False, maxlength=2048)
  ...
File: liveblog/models.py

class PostItem(models.Model):
  post = models.ForeignKey(Post, related_name='items')
  created =...
File: liveblog/models.py

class PostItem(models.Model):
  post = models.ForeignKey(Post, related_name='items',
           ...
What About Our
   Visitors?




                 © 2007 Hush Labs, LLC
                                   22
File: templates/base.html

<?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?>
<!DOCTYPE html PUBLIC quot;-//W3C//DTD X...
File: urls.py


urlpatterns = patterns('',
  url(r'^$', direct_to_template, {'template': 'base.html'},
      name='index')...
archive_week               archive_day

  redirect_to            object_list

 direct_to_template   object_detail


      ...
File: urls.py


from django.views.generic.simple import direct_to_template

urlpatterns = patterns('',
  url(r'^$', direct...
© 2007 Hush Labs, LLC
                  27
{{ Variables|Filters}}      {% Tags %}


           Templates
              Inheritance
                                  ...
File: templates/base.html

<div id=quot;yui-mainquot;>
   <div class=quot;yui-bquot;>
      {% block content %}{% endblock...
File: urls.py


from django.views.generic.list_detail import object_list

urlpatterns = patterns('',
  url(r'^$', object_l...
<a href=quot;{% url post-detail post.slug %}quot;>{{post.title}}</a>

  File: urls.py


  from django.views.generic.list_d...
© 2007 Hush Labs, LLC
                  32
Views
django.http.HttpRequest




  View Function


django.http.HttpResponse




                           © 2007 Hush La...
File: urls.py


from liveblog import views

urlpatterns = patterns('',
  url(r'^$', direct_to_template, {'template': 'base...
File: templates/liveblog/post_detail.html

{% extends quot;base.htmlquot; %}
{% block content %}
<div class=quot;postquot;...
© 2007 Hush Labs, LLC
                  36
“I want the admin to
 look like the rest of
       the site.”

                     © 2007 Hush Labs, LLC
                ...
File: urls.py


from django.contrib.auth.views import login, logout

urlpatterns = patterns('',
  url(r'^accounts/login/$'...
© 2007 Hush Labs, LLC
                  39
© 2007 Hush Labs, LLC
                  40
File: templates/base.html

<body>
  <div id=quot;docquot; class=quot;yui-t4quot;>
    <div id=quot;hdquot;><h1><a href=quo...
Forms

        © 2007 Hush Labs, LLC
                          42
File: urls.py


urlpatterns = patterns('',
  url(r'^add_post/$', views.add_post, name='add-post'),
)

File: templates/post...
File: liveblog/views.py

from   django import newforms as forms
from   django.contrib.auth.decorators import login_require...
File: urls.py


urlpatterns = patterns('',
  url(r'^post/(?P<slug>.+)/add_item/', views.add_item, name='add-post-item'),
)...
File: liveblog/views.py

class PostItemForm(forms.Form):
  image = forms.ImageField(required=False)
  content = forms.Char...
© 2007 Hush Labs, LLC
                  47
That’s It!

             48
Nathan Eror
 neror@hushlabs.com
http://natuba.com/neror


                          49
Upcoming SlideShare
Loading in...5
×

Building a Dynamic Website Using Django

6,028

Published on

From BarcampHouston2 in August 2007. It covers building a basic web site from scratch with Django 0.96.

Published in: Technology, Business
0 Comments
18 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,028
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
18
Embeds 0
No embeds

No notes for slide

Building a Dynamic Website Using Django

  1. 1. Building a Dynamic Website Using Django Nathan Eror Hush Labs, LLC © 2007 Hush Labs, LLC 1
  2. 2. Who am I? © 2007 Hush Labs, LLC 2
  3. 3. Let’s Build Something! © 2007 Hush Labs, LLC 3
  4. 4. Time to Get Started 1. Download and Install Python & Django 2. Install sqlite if you don’t have it yet 3. Crank up your editor and get ready to code © 2007 Hush Labs, LLC 4
  5. 5. > django-admin.py startproject barcamplive > cd barcamplive > ./manage.py startapp liveblog > mkdir -p templates public/uploads © 2007 Hush Labs, LLC 5
  6. 6. File: settings.py DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = 'barcamplive.db' import os.path, sys PROJECT_ROOT = os.path.abspath(os.path.dirname(sys.argv[0]))) MEDIA_ROOT = quot;%s/publicquot; % PROJECT_ROOT MEDIA_URL = 'http://localhost:8000/public' ADMIN_MEDIA_PREFIX = '/admin/public/' ROOT_URLCONF = 'urls' INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', 'liveblog' ) TEMPLATE_DIRS = ( quot;%s/templatesquot; % PROJECT_ROOT, ) © 2007 Hush Labs, LLC 6
  7. 7. Start With the Data Model © 2007 Hush Labs, LLC 7
  8. 8. File: liveblog/.py from django.db import models from django.contrib.auth.models import User from datetime import datetime class Post(models.Model): title = models.CharField(blank=False, null=False, maxlength=2048) author = models.ForeignKey(User, related_name='posts') created = models.DateTimeField(u'Date Created', blank=False, null=False, default=datetime.now) slug = models.SlugField(prepopulate_from=(quot;titlequot;,)) def __str__(self): return self.title class PostItem(models.Model): post = models.ForeignKey(Post, related_name='items') created = models.DateTimeField(u'Date Created', blank=False, default=datetime.now) image = models.ImageField(upload_to=quot;uploadsquot;, blank=True) content = models.TextField(blank=True) def __str__(self): return quot;Post Item for '%s' created at %squot; % (self.post.title, self.created.strftime('%I:%M %p %Z')) © 2007 Hush Labs, LLC 8
  9. 9. postgresql mysql sqlite oracle mssql >>> u = User.objects.get(username='admin') Django Models (ORM) >>> p = Post(title='Django is fun!',slug='django-is-fun',author=u) >>> p.save() >>> i = PostItem(content='Woo Hoo!') >>> p.items.add(i) >>> Post.objects.all() [<Post: Django is fun!>] >>> p2 = Post.objects.get(slug='django-is-fun') >>> p2.items.all() [<PostItem: Post Item for 'Django is fun!' created at 03:27 PM >] >>> p2.delete() >>> Post.objects.count() 0L >>> PostItem.objects.count() 0L © 2007 Hush Labs, LLC 9
  10. 10. > ./manage.py syncdb > ./manage.py runserver © 2007 Hush Labs, LLC 10
  11. 11. The Django Admin Site © 2007 Hush Labs, LLC 11
  12. 12. © 2007 Hush Labs, LLC 12
  13. 13. Django URLs © 2007 Hush Labs, LLC 13
  14. 14. File: urls.py from django.conf.urls.defaults import * from django.conf import settings urlpatterns = patterns('', # Example: # (r'^barcamplive/', include('barcamplive.foo.urls')), # Uncomment this for admin: (r'^admin/', include('django.contrib.admin.urls')), ) © 2007 Hush Labs, LLC 14
  15. 15. © 2007 Hush Labs, LLC 15
  16. 16. File: settings.py DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = 'barcamplive.db' import os.path, sys PROJECT_ROOT = os.path.abspath(os.path.dirname(sys.argv[0]))) MEDIA_ROOT = quot;%s/publicquot; % PROJECT_ROOT ROOT_URLCONF = 'urls' MEDIA_URL = 'http://localhost:8000/public' ADMIN_MEDIA_PREFIX = '/admin/public/' INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', 'liveblog' ) TEMPLATE_DIRS = ( quot;%s/templatesquot; % PROJECT_ROOT, ) © 2007 Hush Labs, LLC 16
  17. 17. © 2007 Hush Labs, LLC 17
  18. 18. © 2007 Hush Labs, LLC 18
  19. 19. File: liveblog/models.py class Post(models.Model): title = models.CharField(blank=False, null=False, maxlength=2048) author = models.ForeignKey(User, related_name='posts') created = models.DateTimeField(u'Date Created', blank=False, null=False, default=datetime.now) slug = models.SlugField(prepopulate_from=(quot;titlequot;,)) class Admin: list_display = ('title', 'author', 'created') list_filter = ('created', 'author') search_fields = ('title',) date_hierarchy = 'created' © 2007 Hush Labs, LLC 19
  20. 20. File: liveblog/models.py class PostItem(models.Model): post = models.ForeignKey(Post, related_name='items') created = models.DateTimeField(u'Date Created', blank=False, default=datetime.now) image = models.ImageField(upload_to=quot;uploadsquot;, blank=True) content = models.TextField(blank=True) class Admin: list_display = ('post', 'created') list_filter = ('created', 'post') search_fields = ('content',) date_hierarchy = 'created' © 2007 Hush Labs, LLC 20
  21. 21. File: liveblog/models.py class PostItem(models.Model): post = models.ForeignKey(Post, related_name='items', edit_inline=models.TABULAR, num_in_admin=1) created = models.DateTimeField(u'Date Created', blank=False, default=datetime.now) image = models.ImageField(upload_to=quot;uploadsquot;, blank=True, core=True) content = models.TextField(blank=True, core=True) © 2007 Hush Labs, LLC 21
  22. 22. What About Our Visitors? © 2007 Hush Labs, LLC 22
  23. 23. File: templates/base.html <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> <!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.1//ENquot; quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtdquot;> <html xmlns=quot;http://www.w3.org/1999/xhtmlquot; xml:lang=quot;enquot;> <head> <title>BarCamp Houston Live!</title> <link rel=quot;stylesheetquot; type=quot;text/cssquot; href=quot;/public/css/reset-fonts-grids.cssquot;> <link rel=quot;stylesheetquot; type=quot;text/cssquot; href=quot;/public/css/base-min.cssquot;> <link rel=quot;stylesheetquot; type=quot;text/cssquot; href=quot;/public/css/live.cssquot;> </head> <body> <div id=quot;docquot; class=quot;yui-t4quot;> <div id=quot;hdquot;><h1><a href=quot;/quot;>The BarCamp Liveblog</a></h1></div> <div id=quot;bdquot;> <div id=quot;yui-mainquot;> <div class=quot;yui-bquot;> <!-- The main content goes here --> </div> </div> <div id=quot;sidebarquot; class=quot;yui-bquot;> <!-- The sidebar goes here --> </div> </div> <div id=quot;ftquot;><div id=quot;copyrightquot;>&copy;2007 <a href=quot;http://www.hushlabs.comquot;>Hush Labs, LLC</ a><br/>Header image adapted from flickr user <a href=quot;http://www.flickr.com/photos/eschipul/ 254400673/quot;>eschipul's</a>.</div></div> </div> </body> </html> © 2007 Hush Labs, LLC 23
  24. 24. File: urls.py urlpatterns = patterns('', url(r'^$', direct_to_template, {'template': 'base.html'}, name='index'), (r'^admin/', include('django.contrib.admin.urls')), (r'^public/(?P<path>.*)$', 'django.views.static.serve', {'document_root':settings.MEDIA_ROOT}), ) © 2007 Hush Labs, LLC 24
  25. 25. archive_week archive_day redirect_to object_list direct_to_template object_detail Generic Views create_object archive_month delete_object archive_index update_object archive_year © 2007 Hush Labs, LLC 25
  26. 26. File: urls.py from django.views.generic.simple import direct_to_template urlpatterns = patterns('', url(r'^$', direct_to_template, {'template': 'base.html'}, name='index'), (r'^admin/', include('django.contrib.admin.urls')), (r'^public/(?P<path>.*)$', 'django.views.static.serve', {'document_root':settings.MEDIA_ROOT}), ) © 2007 Hush Labs, LLC 26
  27. 27. © 2007 Hush Labs, LLC 27
  28. 28. {{ Variables|Filters}} {% Tags %} Templates Inheritance © 2007 Hush Labs, LLC 28
  29. 29. File: templates/base.html <div id=quot;yui-mainquot;> <div class=quot;yui-bquot;> {% block content %}{% endblock %} </div> </div> File: templates/liveblog/post_list.html {% extends quot;base.htmlquot; %} {% block content %} <div id=quot;post_listquot;> <h1>Current Liveblogs</h1> {% if object_list %} <ul> {% for post in object_list %} <li><a href=quot;{% url post-detail post.slug %}quot;>{{post.title}}</a></li> {% endfor %} </ul> {% else %} <h3>There are no blogs yet!</h3> {% endif %} </div> {% endblock %} © 2007 Hush Labs, LLC 29
  30. 30. File: urls.py from django.views.generic.list_detail import object_list urlpatterns = patterns('', url(r'^$', object_list, {'queryset':Post.objects.all(),'allow_empty':True}, name='index') ) © 2007 Hush Labs, LLC 30
  31. 31. <a href=quot;{% url post-detail post.slug %}quot;>{{post.title}}</a> File: urls.py from django.views.generic.list_detail import object_detail <a href=quot;quot;>Django is fun!</a> urlpatterns = patterns('', url(r'^$', direct_to_template, {'template': 'base.html'}, name='index'), url(r'^post/(?P<slug>.*)/$', object_detail, {'queryset':Post.objects}, name='post-detail'), ) File: templates/liveblog/post_detail.html {% extends quot;base.htmlquot; %} {% block content %} <div class=quot;postquot;> <div class=quot;titlequot;>{{object.title}}</div> <div class=quot;taglinequot;>Started at {{object.created}}</div> <div class=quot;contentquot;> {% for item in object.items %} <div class=quot;post_itemquot;> <div class=quot;item_taglinequot;>Added on {{item.created}}</div> {% if item.image %}<div class=quot;item_imagequot;><img src=quot;/public/{{item.image}}quot;></div>{% endif %} <div class=quot;item_contentquot;>{{item.content|linebreaks}}</div> <br style=quot;clear:both;quot;/> </div> {% endfor %} </div> </div> {% endblock %} © 2007 Hush Labs, LLC 31
  32. 32. © 2007 Hush Labs, LLC 32
  33. 33. Views django.http.HttpRequest View Function django.http.HttpResponse © 2007 Hush Labs, LLC 33
  34. 34. File: urls.py from liveblog import views urlpatterns = patterns('', url(r'^$', direct_to_template, {'template': 'base.html'}, name='index'), url(r'^post/(?P<slug>.*)/$', views.post_detail, name='post-detail'), ) File: liveblog/views.py from models import Post from django.shortcuts import get_object_or_404, render_to_response def post_detail(request, slug): post = get_object_or_404(Post, slug=slug) items = post.items.all() return render_to_response('liveblog/post_detail.html', {'post':post, 'items':items}) © 2007 Hush Labs, LLC 34
  35. 35. File: templates/liveblog/post_detail.html {% extends quot;base.htmlquot; %} {% block content %} <div class=quot;postquot;> <div class=quot;titlequot;>{{post.title}}</div> <div class=quot;taglinequot;>Started at {{post.created}}</div> <div class=quot;contentquot;> {% for item in items %} <div class=quot;post_itemquot;> <div class=quot;item_taglinequot;>Added on {{item.created}}</div> {% if item.image %}<div class=quot;item_imagequot;><img src=quot;/public/{{item.image}}quot;></div>{% endif %} <div class=quot;item_contentquot;>{{item.content|linebreaks}}</div> <br style=quot;clear:both;quot;/> </div> {% endfor %} </div> </div> {% endblock %} © 2007 Hush Labs, LLC 35
  36. 36. © 2007 Hush Labs, LLC 36
  37. 37. “I want the admin to look like the rest of the site.” © 2007 Hush Labs, LLC 37
  38. 38. File: urls.py from django.contrib.auth.views import login, logout urlpatterns = patterns('', url(r'^accounts/login/$', login, name='login'), url(r'^accounts/logout/$', logout, name='logout'), ) File: templates/registration/login.html {% extends quot;base.htmlquot; %} {% block content %} <form action=quot;quot; method=quot;postquot; accept-charset=quot;utf-8quot;> {% if form.username.errors %}{{ form.username.html_error_list }}{% endif %} <p><label for=quot;id_usernamequot;>Username:</label> {{form.username}}</p> {% if form.password.errors %}{{ form.password.html_error_list }}{% endif %} <p><label for=quot;id_passwordquot;>Password:</label> {{form.password}}</p> <p><input type=quot;submitquot; value=quot;Loginquot;></p> </form> {% endblock %} File: templates/registration/logged_out.html {% extends quot;base.htmlquot; %} {% block content %} <h1>You are now logged out</h1> {% endblock %} © 2007 Hush Labs, LLC 38
  39. 39. © 2007 Hush Labs, LLC 39
  40. 40. © 2007 Hush Labs, LLC 40
  41. 41. File: templates/base.html <body> <div id=quot;docquot; class=quot;yui-t4quot;> <div id=quot;hdquot;><h1><a href=quot;/quot;>The BarCamp Liveblog</a></h1></div> <div id=quot;bdquot;> <div id=quot;yui-mainquot;> <div class=quot;yui-bquot;> {% block content %}{% endblock %} </div> </div> <div id=quot;sidebarquot; class=quot;yui-bquot;> <ul> <li><a href=quot;{% url add-post %}quot;>Add a Blog Post</a></li> {% block extralinks %}{% endblock %} {% if user.is_authenticated %} <li><a href=quot;{% url logout %}quot;>Logout</a></li> {% else %} <li><a href=quot;{% url login %}quot;>Login</a></li> {% endif %} </ul> </div> </div> <div id=quot;ftquot;><div id=quot;copyrightquot;>&copy;2007 <a href=quot;http://www.hushlabs.comquot;>Hush Labs, LLC</ a><br/>Header image adapted from flickr user <a href=quot;http://www.flickr.com/photos/eschipul/ 254400673/quot;>eschipul's</a>.</div></div> </div> </body> © 2007 Hush Labs, LLC 41
  42. 42. Forms © 2007 Hush Labs, LLC 42
  43. 43. File: urls.py urlpatterns = patterns('', url(r'^add_post/$', views.add_post, name='add-post'), ) File: templates/post_form.html {% extends quot;base.htmlquot; %} {% block content %} <form action=quot;quot; method=quot;postquot; accept-charset=quot;utf-8quot;> {{form.title.errors}} <p>{{form.title.label_tag}}: {{form.title}}</p> {{form.slug.errors}} <p>{{form.slug.label_tag}}: {{form.slug}}</p> {{form.author.as_hidden}} <p><input type=quot;submitquot; value=quot;Addquot;></p> </form> {% endblock %} © 2007 Hush Labs, LLC 43
  44. 44. File: liveblog/views.py from django import newforms as forms from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse @login_required def add_post(request): PostForm = forms.form_for_model(Post, fields=('title', 'slug', 'author')) if request.method == 'POST': form = PostForm(request.POST) if form.is_valid(): new_post = form.save() return HttpResponseRedirect(reverse('post-detail', args=[new_post.slug])) else: form = PostForm(initial={'author':request.user.id}) return render_to_response('liveblog/post_form.html', {'form':form}) © 2007 Hush Labs, LLC 44
  45. 45. File: urls.py urlpatterns = patterns('', url(r'^post/(?P<slug>.+)/add_item/', views.add_item, name='add-post-item'), ) File: templates/liveblog/post_item_form.html {% extends quot;liveblog/post_detail.htmlquot; %} {% block newitemform %} <form enctype=quot;multipart/form-dataquot; action=quot;quot; method=quot;postquot; accept-charset=quot;utf-8quot;> {{form.content.errors}} <p>{{form.content.label_tag}}: {{form.content}}</p> {{form.image.errors}} <p>{{form.image.label_tag}}: {{form.image}}</p> <p><input type=quot;submitquot; value=quot;Addquot;></p> </form> {% endblock %} File: templates/liveblog/post_detail.html {% for item in items %} <div class=quot;post_itemquot;> <div class=quot;item_taglinequot;>Added on {{item.created}}</div> {% if item.image %} <div class=quot;item_imagequot;><img src=quot;/public/{{item.image}}quot;></div> {% endif %} <div class=quot;item_contentquot;>{{item.content|linebreaks}}</div> <br style=quot;clear:both;quot;/> </div> {% endfor %} {% block newitemform %}{% endblock %} {% block extralinks %} <li><a href=quot;{% url add-post-item post.slug %}quot;>Add an item</a></li> {% endblock %} © 2007 Hush Labs, LLC 45
  46. 46. File: liveblog/views.py class PostItemForm(forms.Form): image = forms.ImageField(required=False) content = forms.CharField(widget=forms.Textarea(), required=True) def save(self, post): uploaded_file = self.cleaned_data['image'] new_item = PostItem(post=post, content=self.cleaned_data['content']) new_item.save_image_file(uploaded_file.filename, uploaded_file.content) new_item.save() return new_item @login_required def add_item(request, slug): post = Post.objects.get(slug=slug) items = post.items.all() if request.method == quot;POSTquot;: form = PostItemForm(request.POST, request.FILES) if form.is_valid(): new_item = form.save(post) return HttpResponseRedirect(reverse('post-detail', args=[new_item.post.slug])) else: form = PostItemForm() return render_to_response('liveblog/post_item_form.html', locals()) © 2007 Hush Labs, LLC 46
  47. 47. © 2007 Hush Labs, LLC 47
  48. 48. That’s It! 48
  49. 49. Nathan Eror neror@hushlabs.com http://natuba.com/neror 49

×