Building a Dynamic Website Using Django

  • 4,975 views
Uploaded on

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

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

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
4,975
On Slideshare
0
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
0
Comments
0
Likes
17

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Building a Dynamic Website Using Django Nathan Eror Hush Labs, LLC © 2007 Hush Labs, LLC 1
  • 2. Who am I? © 2007 Hush Labs, LLC 2
  • 3. Let’s Build Something! © 2007 Hush Labs, LLC 3
  • 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. > django-admin.py startproject barcamplive > cd barcamplive > ./manage.py startapp liveblog > mkdir -p templates public/uploads © 2007 Hush Labs, LLC 5
  • 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. Start With the Data Model © 2007 Hush Labs, LLC 7
  • 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. 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. > ./manage.py syncdb > ./manage.py runserver © 2007 Hush Labs, LLC 10
  • 11. The Django Admin Site © 2007 Hush Labs, LLC 11
  • 12. © 2007 Hush Labs, LLC 12
  • 13. Django URLs © 2007 Hush Labs, LLC 13
  • 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. © 2007 Hush Labs, LLC 15
  • 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. © 2007 Hush Labs, LLC 17
  • 18. © 2007 Hush Labs, LLC 18
  • 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. 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. 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. What About Our Visitors? © 2007 Hush Labs, LLC 22
  • 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. 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. 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. 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. © 2007 Hush Labs, LLC 27
  • 28. {{ Variables|Filters}} {% Tags %} Templates Inheritance © 2007 Hush Labs, LLC 28
  • 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. 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. <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. © 2007 Hush Labs, LLC 32
  • 33. Views django.http.HttpRequest View Function django.http.HttpResponse © 2007 Hush Labs, LLC 33
  • 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. 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. © 2007 Hush Labs, LLC 36
  • 37. “I want the admin to look like the rest of the site.” © 2007 Hush Labs, LLC 37
  • 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. © 2007 Hush Labs, LLC 39
  • 40. © 2007 Hush Labs, LLC 40
  • 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. Forms © 2007 Hush Labs, LLC 42
  • 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. 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. 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. 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. © 2007 Hush Labs, LLC 47
  • 48. That’s It! 48
  • 49. Nathan Eror neror@hushlabs.com http://natuba.com/neror 49