Permalink
Browse files

Todo list application with add functionality.

  • Loading branch information...
1 parent 1e53c0c commit 207528951f0a1e2133aa1fa29f39163ccb117d08 @tachang committed Dec 29, 2011
View
@@ -1,198 +1 @@
-Intro
-=====
-* About this section of the class
-* Schedule: https://www.noisebridge.net/wiki/Working_Syllabus
-* Ultimate goal is a long term project: https://www.noisebridge.net/wiki/PyClass_Project_Ideas
-* No pre-existing skills required, but...
-* Feedback
-
-*NOTE*: Unlike the intro to python classes, this section of the course will not have time to pay special attention to windows users. This part focuses on web development in python, which is NOT windows friendly. Of course you may join and I will help as much as possible but in general if you are serious about web development you should borrow a friends computer or pair up with someone else in the class on a nix-like system, which includes Mac OS X. Sorry!
-
-Goals
------
-* Become familiar with web2y
-* Learn and/or solidify working with git
-* Basic skills/methodology for evaluating python frameworks
-* Basic introduction to debugging
-
-Prereqs
--------
-* Install python 2.6 or 2.7. We will NOT be working from python 3. If you are on mac os X, it will help you to install a python that is NOT the built in python. See python.org for instructions. You may also want to install XCode, which can usually be done through the app store as "Apple Developer Tools". Neither of these are required for the first class but you will get there at some point.
-* Find your terminal. That's it. Just know where it is :)
-* Install Git
-
-Further Documentation
----------------------
-* http://www.web2py.com/book/
-
-Steps to your own noiselist
----------------------------
-For this class, we will go through the process of creating a personal TODO list on 3 different frameworks. This is the first. So let's go.
-
-**Get web2py downloaded and running with demo app using buildout**::
-
- > git clone git://github.com/eleddy/web2py-noiselist.git
- > cd web2py-noiselist
- > python bootstrap.py # use the non-local python if you are on mac osx please
- > ./bin/buildout
- > ./bin/web2py start
-
-**Create a new simple app**
-
- - Start at http://127.0.0.1:8000/admin/default/site
- - Create a new simple app named noiselist. web2py will setup a default folder structure for you with basic routing. This app can be viewed at http://127.0.0.1:8000/noiselist/default/index .
- - You can edit your new app through the web or on the filesystem, whichever feels better to you. The following instructions will work for either.
- - Through the web, you can edit your files at http://127.0.0.1:8000/admin/default/design/noiselist
- - On the filesystem, you can edit your app at at web2py-noiselist/web2py/applications/noiselist
-
-**Intro to the file system and templating**
-
-The Model section/folder will have all of your database definitions. The View section/folder will have all of your templates, css, js, and images. The controllers section/folder will have all of your business logic, or for all intensive purposes most of your .py files.
-
-In views > default > index.html, add html to make the front page resemble a list. Replace the boiler plate code with something like::
-
- <ul>
- <li>Tequila</li>
- <li>Pants</li>
- <li>Pre-party</li>
- </ul>
-
-What you add and remove is up to you. Play with adding and removing different tags to see what happens.
-
-**Controllers and sending data**
-
-Here we will see how to use variables in templates, and make the list dynamically populated. We aren't starting right away with database muckery because we want to learn how things fit together nicely and minimize the chance that we have multiple errors. Reload often after each code change to make sure you haven't borked things.
-
-In controllers > default.py, add a function which returns a list::
-
- def get_list():
- """
- Return the current todo list
- """
- return [
- "Go to the store and buy pants",
- "Eat breakfast",
- "Flash mob"
- ]
-
-Still in controllers > default.py, call your new function from the index page. Note that you must return your new variable in a dictionary. This adds the variable to the scope of the template::
-
- def index():
- todo_list = get_list()
- return dict(todo_list=todo_list)
-
-In views > default > index.html, update your html to use the todo_list variable to dynamically display the list::
-
- <ul>
- {{for todo in todo_list:}}
- <li>{{=todo}}</li>
- {{pass}}
- </ul>
-
-Now your app is wired to get a list of todo items from the controller logic and display them. Yay!
-
-**Hook up to a real database**
-
-For this example, we will be working from the default SQLite database. This is a very simple relational database that lives on the filesystem. Later on in the class we will work with more robust databases.
-
-At the very bottom of models > db.py, let's add code to define our todo list model::
-
- db.define_table('todo_list',Field('todo'),)
- db.todo_list.todo.requires=IS_NOT_EMPTY()
-
-This code says: Create a table called "todo_list", and give it one field (or column if you like) called "todo". The second line says: make sure no one enters empty todos. You can add as few or as many restrictions as you like. We are adding the empty check here to demo the way that web2py handles data validation.
-
-Web2py will automatically reload changed code AND database schemas every time you save a file. Neato.
-
-Now that we have a database, we need to get info from that database. Keep in mind that your database is currently empty so the net end result will be an empty todo list on your index page.
-
-In controllers > default.py, update the get_list function to pull from the database instead of a list ([])::
-
- def get_list():
- """
- Return the current todo list
- """
- return db().select(db.todo_list.ALL)
-
-We have one small change to make in the template. The db select above will return rows, and we really just want one item in that row - the todo. Update views > default > index.html to say::
-
- <ul>
- {{for todo in todo_list:}}
- <li>{{=todo.todo}}</li>
- {{pass}}
- </ul>
-
-If you had more fields in your model like 'created_by' for example, you can access that by saying todo.created_by.
-
-**Adding to the db**
-
-Currently we are pulling from the db, but pulling an empty list. Let's put a form on the front page to add list items. Web2py will auto generate and validate forms for you so we will take that approach.
-
-To create a form, add a function in controllers > default.py::
-
- def add_to_list():
- """
- Render and handle response from adding to a todo form
- """
- form=SQLFORM(db.todo_list)
- message = None
- if form.accepts(request,session):
- message = 'Added to list!'
- else:
- message = 'something went wrong'
- if message:
- response.flash=message
- return form
-
-There are a couple things going on there. First, we see that web2py has some whacky globals lying around (SQLFORM) so be careful. Second, given a database table it will auto-generate a form for you. Third, form.accepts will do validation of the form for you. Last but not least is the introduction of flash. response.flash automatically adds a growl style notification to the resulting page which you will see when you violate the "no empty todo's" restraint that we added earlier.
-
-Before leaving that file, make sure to send that form to the index page with::
-
- def index():
- """
- example action using the internationalization operator T and flash
- rendered by views/default/index.html or views/generic.html
- """
- add_form = add_to_list()
- todo_list = get_list()
- return dict(todo_list=todo_list,
- add_list_item_form=add_form)
-
-Last but not least, add the code to render the form to your front page. In views > default > index.html::
-
- {{if 'add_list_item_form' in globals():}}
- {{=add_list_item_form}}
- {{pass}}
-
-Now reload the front page and voila! You should be able to view and add items in your list! Note that if you add an empty item, a error response is flashed.
-
-Packaging
----------
-If you did all of the work through the web (or FS even), you can package up your app and redistribute with the built in tools.
- * Go to http://127.0.0.1:8000/admin/default/site
- * Click "Pack all"
- * Move the w2p export into web2pyapps
- * Update buildout
- * Commit!
-
-Homework
---------
-If you are captivated with web2py, try to do the following at home:
-* Delete an item from a list
-* Configure multiple users
-* Review at the beginning of next class
-
-
-
-
-
-
-Create a project named django_todo. You can't use dashes (only numbers, letters, and underscores)
-
-$ django-admin.py startproject django_todo
-
-
-Inside the django_todo project create a Django application called todo:
-$ django-admin.py startapp todo
-
-
+This is a simple todo application for the Noisebridge Python class.
View
No changes.
View
Binary file not shown.
View
Binary file not shown.
View
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
No changes.
View
Binary file not shown.
View
@@ -0,0 +1,7 @@
+from django.db import models
+
+# Create your models here.
+
+# A single todo item. Only supports a single list.
+class TodoItem(models.Model):
+ name = models.CharField(max_length=256)
View
Binary file not shown.
View
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
View
@@ -0,0 +1,30 @@
+from django.template import Context, RequestContext
+from django.shortcuts import render_to_response, redirect
+from django import forms
+from noiselist.models import *
+
+class TodoForm(forms.Form):
+ name = forms.CharField(max_length=1000, widget=forms.Textarea)
+
+def index(request):
+ todos = TodoItem.objects.all()
+
+ return render_to_response('index.html', { 'todos' : todos }, context_instance=RequestContext(request))
+
+def add_todo(request):
+
+ if request.method == 'POST':
+ form = TodoForm(request.POST)
+
+ if( form.is_valid() == True ):
+ item = TodoItem()
+ item.name = form.cleaned_data['name']
+ item.save()
+ # All saved so return the user to the frontpage
+ return redirect('/')
+ else:
+ return render_to_response('add_todo.html', { 'form' : form}, context_instance=RequestContext(request))
+ else:
+ form = TodoForm()
+
+ return render_to_response('add_todo.html', { 'form' : form}, context_instance=RequestContext(request))
View
Binary file not shown.
View
@@ -0,0 +1,103 @@
+import os, sys
+import django
+# Django settings for django_noiselist project.
+
+# Some custom settings that are useful to be used in the settings file
+DJANGO_ROOT = os.path.dirname(os.path.realpath(django.__file__))
+SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': os.path.join(SITE_ROOT, 'database.sqlite'), # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale
+USE_L10N = True
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'bvhg=-cet&0!6qhx#&@d349+pu!*i+jqt)%wk6(#x2(g$608dd'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+# 'django.template.loaders.eggs.Loader',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+)
+
+ROOT_URLCONF = 'django_noiselist.urls'
+
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ os.path.join(SITE_ROOT, 'templates')
+
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.messages',
+ # Uncomment the next line to enable the admin:
+ 'django.contrib.admin',
+ 'noiselist',
+)
View
Binary file not shown.
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<h1>Add a Todo</h1>
+
+<form method="POST" action="/todo">
+
+ {{ form.as_ul }}
+
+ {% csrf_token %}
+ <input type="submit"/>
+</form>
+
+{% endblock %}
+
Oops, something went wrong.

0 comments on commit 2075289

Please sign in to comment.