summaryrefslogtreecommitdiff
path: root/old/published/Webmonkey/Frameworks
diff options
context:
space:
mode:
Diffstat (limited to 'old/published/Webmonkey/Frameworks')
-rw-r--r--old/published/Webmonkey/Frameworks/django-firstapp.txt381
-rw-r--r--old/published/Webmonkey/Frameworks/django-migrate.txt158
-rw-r--r--old/published/Webmonkey/Frameworks/django-overview.txt87
-rw-r--r--old/published/Webmonkey/Frameworks/django-templates.txt239
-rw-r--r--old/published/Webmonkey/Frameworks/django-website.txt175
-rw-r--r--old/published/Webmonkey/Frameworks/djangoscreen1.jpgbin0 -> 70680 bytes
-rw-r--r--old/published/Webmonkey/Frameworks/djangoscreen2.jpgbin0 -> 59620 bytes
-rw-r--r--old/published/Webmonkey/Frameworks/djangoscreen3.jpgbin0 -> 198661 bytes
-rw-r--r--old/published/Webmonkey/Frameworks/intro.txt58
-rw-r--r--old/published/Webmonkey/Frameworks/vagablogging_submission.txt96
10 files changed, 1194 insertions, 0 deletions
diff --git a/old/published/Webmonkey/Frameworks/django-firstapp.txt b/old/published/Webmonkey/Frameworks/django-firstapp.txt
new file mode 100644
index 0000000..3d01b52
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/django-firstapp.txt
@@ -0,0 +1,381 @@
+Assuming you've had a read through our [Django Overview], you're probably ready to dive into some code. But before we start installing we need to grab a copy of Django and set it up.
+
+As we mentioned in the overview, Django doesn't have a 1.0 release yet. The latest official release was .96, but that version lacks many of the features we're going to use in this project.
+
+In order to use the latest and greatest Django tools (like model inheritance) we're going to checkout a copy of the trunk build using Subversion.
+
+If you don't have [http://subversion.tigris.org/ Subversion] installed, go grab a copy.
+
+Then fire up your terminal and paste in this line:
+
+<pre>
+svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk
+</pre>
+
+Once that finishes downloading all the files, we need to make sure Python is aware of Django. There's a couple ways to go about that, but a symbolic link to your Python site packages directory is probably the easiest.
+
+Assuming you're on a *nix system, this line will do the trick
+
+<pre>
+ln -s `pwd`/django-trunk/django /path/to/python_site_packages/django
+</pre>
+
+If you don't know where your Python site directory is, here's a handy bit of Python that will tell you:
+
+<pre>
+python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
+</pre>
+
+If you're on Windows the easiest thing to do is add Django to your PythonPath environment variable. On Windows you can define environment variables in the Control Panel, see Microsoft's [http://technet.microsoft.com/en-us/library/bb491071.aspx Command Line Reference] for more details.
+
+The excellent Django [http://www.djangoproject.com/documentation/install/ installation docs] suggest creating a symbolic link to the file django-trunk/django/bin/django-admin.py in a directory on your system path, such as /usr/local/bin. I find that I don't use django-admin.py all that often, but you can create the link if you like, just paste this code in your shell:
+
+<pre>
+ln -s `pwd`/path/to/django-trunk/django/bin/django-admin.py /usr/local/bin
+</pre>
+
+So we've got Django installed and Python knows where it lives, let's get started.
+
+Remember that we have a Subversion checkout so if you ever want to update to the latest release, just head to the django-trunk folder and run <code>svn update</code>.
+
+== Set up our First Project ==
+
+Okay, let's get started. From the command line switch to your web development directory, something like this:
+
+<pre>
+cd ~/sites/dev
+</pre>
+
+Now we're going to run the <code>django-admin</code> tool we mentioned earlier. If you created the symlink, you don't need the full path, but if you didn't here's the code:
+
+<pre>
+python /path/to/django-trunk/django/bin/django-admin.py startproject djangoblog
+</pre>
+
+Yes, we're going to build a blog.
+
+Now cd over to the new folder:
+
+<pre>
+cd ~/sites/dev/djangoblog
+</pre>
+
+This is going to be our project folder into which we will add various apps, some we'll create and some we'll be downloading from Google code projects. I like to keep my Python import statements clean and free of project specific module names, so I always make sure my root project folder (in this case djangoblog) is on my python path. To do that just add the path to your PythonPath variable.
+
+That way we can write statements like:
+
+<pre>
+import myapp
+</pre>
+
+rather than
+
+<pre>
+import myproject.myapp
+</pre>
+
+It's not a huge thing, but it does make your code more portable.
+
+Okay, we're getting there. The next step is to fill out our project settings file. Fire up your favorite text editor and open up the settings.py file inside the djangoblog directory.
+
+The core of what we need to set up is at the top of the file. Look for these lines:
+
+<pre>
+DATABASE_ENGINE = 'sqlite3' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+DATABASE_NAME = '/path/to/djangoblog' # Or path to database file if using sqlite3.
+DATABASE_USER = '' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+</pre>
+
+Note that we're using SQLite as a database for development purposes. Assuming you have Python 2.5 installed you don't need to do anything to use SQLite. If you're on either Python 2.3 or Python 2.4, you'll need [http://oss.itsystementwicklung.de/trac/pysqlite/ pysqlite] -- make sure you install version 2.0.3 or higher. If you have MySQL or PostgreSQL already installed, feel free to use them.
+
+The other settings are well documented in the settings.py file and most of them can be ignored for now. But there is one other thing we need to do. If you look at the bottom of the settings.py file you'll notice this bit of code:
+
+
+<pre>
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+)
+</pre>
+
+This where we tell our django project, which apps we want to install. In a minute we'll add our blog app, but for now let's just add Django's built-in admin section. Paste in this line, just below the sites app:
+
+<pre>
+'django.contrib.admin',
+</pre>
+
+Before we finish with settings.py, here's a handy trick for the template directories. I generally keep all my templates in a folder named templates within my project folder (in this case djangoblog). But I generally move between development and live servers quite a bit and I hate having to change the path to the templates folder. This trick takes care of that:
+
+<pre>
+import os.path
+TEMPLATE_DIRS = (
+ os.path.join(os.path.dirname(__file__), 'templates'),
+)
+</pre>
+
+Instead of hard coding the path to our templates folder this is dynamic -- and it showcases how easy it is to tweak django using Python. We just import the <code>os.path</code> Python module and then find the path to the directory where settings.py is and then appends 'templates' to that path.
+
+Now when we push the site live, there's no need to change the settings.py file. (Actually you'd probably want to change to a more robust database, but we'll get to that much later).
+
+So now let's use one of the tools included in manage.py, the <code>syncdb</code> tool. Paste this line in your terminal:
+
+<pre>
+python manage.py syncdb
+</pre>
+
+The <code>syncdb</code> tool tells Django to translate all our installed apps' models.py files into actual database table. In this case they only thing we have installed are some of the built-in Django tools, but fear not, we'll get to writing our own models in just a minute.
+
+Once you enter the line above, you'll get some feedback from Django telling you you've just installed the auth system and walking you through setting up a user. The output looks like this:
+
+<pre>
+sng: /djangoblog/ $ python manage.py syncdb
+Creating table auth_message
+Creating table auth_group
+Creating table auth_user
+Creating table auth_permission
+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): no
+Installing index for auth.Message model
+Installing index for auth.Permission model
+sng: /djangoblog/ $ python manage.py syncdb
+Creating table auth_message
+Creating table auth_group
+Creating table auth_user
+Creating table auth_permission
+Creating table django_content_type
+Creating table django_session
+Creating table django_site
+Creating table django_admin_log
+
+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 'luxagraf'):
+E-mail address: none@none.com
+Password:
+Password (again):
+Superuser created successfully.
+Installing index for auth.Message model
+Installing index for auth.Permission model
+Installing index for admin.LogEntry model
+sng: /djangoblog/ $
+</pre>
+
+Once you've created your username and password, it's time to fire up Django's built-in server:
+
+<pre>
+/djangoblog/ $ python manage.py runserver
+Validating models...
+0 errors found
+
+Django version 0.97-pre-SVN-6920, using settings 'djangoblog.settings'
+Development server is running at http://127.0.0.1:8000/
+Quit the server with CONTROL-C.
+</pre>
+
+Now open up your browser and head to [http://127.0.0.1:8000/ http://127.0.0.1:8000/]. You should see a page like this:
+
+[djangocreen1.jpg]
+
+It works! But that isn't very exciting, let's check out the admin. However, before we do that, we need to tell django about the admin url. Fire up your text editor and open the file urls.py in your djangoblog folder. You should see some code like this:
+
+<pre>
+urlpatterns = patterns('',
+ # Example:
+ # (r'^djangoblog/', include('djangoblog.foo.urls')),
+
+ # Uncomment this for admin:
+# (r'^admin/', include('django.contrib.admin.urls')),
+)
+
+</pre>
+
+Go ahead and uncomment the admin url line (just delete the hash mark at the beginning of the line) and now head to [http://127.0.0.1:8000/admin/ http://127.0.0.1:8000/admin/]. Login with the user/pass combo you created earlier and you should see something like this:
+
+[djangocreen2.jpg]
+
+Now that's pretty cool. If you've ever labored over creating an admin system in Ruby on Rails or, god forbid, PHP, you're going to love Django's built-in admin.
+
+But at the moment there isn't much to see in the Admin, so let's get started building our blog.
+
+Now we could just throw in some code that creates a date field, title, entry and other basics, but that wouldn't be a very complete blog would it? What about tags? An RSS feed? A sitemap? Maybe some [http://daringfireball.net/projects/markdown/ Markdown] support for easier publishing?
+
+Yeah, let's add all that. But remember Django's DRY principles -- sure someone else has already created a Feed app? A Sitemap app?
+
+As a matter of fact Django ships with those built-in.
+
+Nice. But what about tags? Well there's one of those available as well -- the cleverly named [http://code.google.com/p/django-tagging/ django-tagging]. Grab the source from Google code and drop it in your djangoblog folder. There's also a handy [https://sourceforge.net/project/showfiles.php?group_id=153041 Python implementation of Markdown], so grab that as well (of course Markdown is entirely optional, feel free to skip it).
+
+Got all that stuff stashed in your djangoblog folder? Good.
+
+Now let's go ahead and create our first Django application.
+
+To do that we'll use Django's app creating script, which lives inside manage.py in our project folder. Paste this line into your shell:
+
+<pre>
+python manage.py createapp blog
+</pre>
+
+If you look inside djangoblog you should now see a new "blog" folder. Open that up and find the models.py file. Open models.py in your favorite text editor and paste in this code:
+
+<pre>
+from django.db import models
+from django.contrib.syndication.feeds import Feed
+from django.contrib.sitemaps import Sitemap
+
+import markdown
+from tagging.fields import TagField
+from tagging.models import Tag
+
+# Create your models here.
+
+class Entry(models.Model):
+ title = models.CharField(max_length=200)
+ slug = models.SlugField(
+ unique_for_date='pub_date',
+ prepopulate_from=('title',),
+ help_text='Automatically built from the title.'
+ )
+ body_html = models.TextField(blank=True)
+ body_markdown = models.TextField()
+ pub_date = models.DateTimeField('Date published')
+ tags = TagField()
+ enable_comments = models.BooleanField(default=True)
+ PUB_STATUS = (
+ (0, 'Draft'),
+ (1, 'Published'),
+ )
+ status = models.IntegerField(choices=PUB_STATUS, default=0)
+
+</pre>
+
+
+Let's step through the code line by line and we'll talk about what's going on. First we import the basic stuff from django, including the model class, the Feed class and the Sitemap class.
+
+Then we import the tagging and markdown files we just saved in our project folder.
+
+Once we have all the modules we're going to use, we can create our blog model. I elected to call it Entry, you can change that name if you like, but remember to substitute your name everywhere I refer to Entry.
+
+Entry extends Django's built-in model.Model class, which handles all the basic create read update and delete (CRUD) tasks. In other words all we have to do is tell Django about the various elements of the database table (like the title field, the entry slug, etc) and all the hard work is handled behind the scenes.
+
+The first bit of our Entry class definition just defines all our various blog entry components. Django will use this information to create our database tables and structure, and also to generate the Admin interface.
+
+Note that we're using Django's various model fields. Most of it should self explanatory, but if you want to learn more about each type check out the [http://www.djangoproject.com/documentation/model-api/ Django documentation]. Also be aware that there are quite a few more field types available.
+
+One thing worth mentioning is the <code>body_html = models.TextField(blank=True)</code> line. What's up with that <code>blank=True</code> bit? Well that information is part of Django's built-in Admin error checking.
+
+Unless you tell it otherwise all fields in your model will create NOT NULL columns in your database. To allow for null columns, we would just add <code>null=True</code>. But adding <code>null=True</code> only affects the database, Django's admin would still complain that it needs the information. To get around that we simple add the <code>blank=True</code>.
+
+In this case what we're going to do is fill in the <code>body_html</code> field programatically, after we hit save in the admin and before Django actually writes to the database. So we need the Admin section to allow <code>body_html</code> to be blank, but not null.
+
+== Check Your Head ==
+
+Now we need to tell Django about our new apps. Open up settings.py again and add these lines to your list of installed apps:
+
+<pre>
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.admin',
+ 'djangoblog.tagging',
+ 'djangoblog.blog',
+)
+</pre>
+
+
+Okay, head over to the terminal and run <code>manage.py syncdb</code>. Refresh your admin section and you should see the tagging application we downloaded. Very cool.
+
+But where's our blog model? Well, even though Django knows about our blog app, we haven't told the app what to do in the Admin section.
+
+So head back over to your text editor and add these lines to bottom of the model definition:
+
+<pre>
+class Entry(models.Model):
+ """
+ ...earlier stuff omitted...
+ """
+
+ class Meta:
+ ordering = ('-pub_date',)
+ get_latest_by = 'pub_date'
+ verbose_name_plural = 'entries'
+
+ class Admin:
+ list_display = ('title', 'pub_date','enable_comments', 'status',)
+ search_fields = ['title', 'body_markdown']
+ list_filter = ('pub_date', 'enable_comments', 'status')
+ fields = (
+ (None, {
+ 'fields': (('title', 'status'), 'body_markdown', ('pub_date', 'enable_comments'), 'tags', 'slug')
+ }),
+ )
+
+
+ def __unicode__(self):
+ return u'%s' %(self.title)
+
+ def get_absolute_url(self):
+ return "/%s/%s/" %(self.pub_date.strftime("%Y/%b/%d").lower(), self.slug)
+
+ def save(self):
+ self.body_html = markdown.markdown(self.body_markdown, safe_mode = False)
+ super(Entry, self).save()
+
+</pre>
+
+Okay, what does all that do? Well let's start with the Meta class. Meta handles things like how Django should order our entries and what the name of the class would be. By default Django would refer to our class as 'Entrys', and that offends my grammatical senses so we just explicitly tell Django the plural name.
+
+The next class, 'Admin,' as you might suspect, controls how the admin interface looks. Now these customizations are entirely optional. You could simple write <code>pass</code> and go with the default admin layout. However I've customized a few things and added some filters to the admin list view so we can sort and filter our entries.
+
+Then we have a few function definitions. All Python objects should return their name. Django recently added unicode support so we'll return our name in unicode. Then there's <code>get_absolute_url</code>. As you might imagine this refers to the entry's permalink page.
+
+When we get to creating templates we'll use this to put in our permalinks. That way if you ever decide to change your permalinks you only have to change one line and your entire site will update accordingly -- very slick.
+
+The last function simply overrides Django's save function. Every Django model has a save function and since we didn't expose the bogy_html field we need to fill it in. So we grab the text from our <code>body_markdown</code> field (which is exposed in the admin), run it through the markdown filter and store it in <code>body_html</code>.
+
+That way we can just call this field in our templates and we'll get nicely formatted html and yet still keep the process transparent -- write in markdown, display html.
+
+Now we're going to add a few more line to our models.py file and then we're done:
+
+<pre>
+ def get_previous_published(self):
+ return self.get_previous_by_pub_date(status__exact=1)
+
+ def get_next_published(self):
+ return self.get_next_by_pub_date(status__exact=1)
+
+ def get_tags(self):
+ return Tag.objects.get_for_object(self)
+
+</pre>
+
+So what's going on here? Django includes a bunch of built-in methods for common tasks, like displaying next and previous links. The function is called <code>get_previous_by_</code> with the last bit of the function being the name of your datetime field, in our case <code>pub_date</code>. However, we included the ability to save drafts in our model, unfortunately Django's built-in function doesn't know about our drafts and will include them in our next/previous links which isn't what we want.
+
+So what to do? How about just wrapping the Django function with a one-liner? That's what we've done here.
+
+<pre>
+ def get_previous_published(self):
+ return self.get_previous_by_pub_date(status__exact=1)
+</pre>
+
+All we do is wrap the django function with a new name <code>get_next_published</code>, call the original <code>get_previous_by_</code> function, but add a filter so that only published entries are included in the results.
+
+The last function is just a time saver. There's a good chance you'll want to list all the tags you've added to your entry, so I've included a convenience method that does just that.
+
+Whew. That's a lot of code to sort through and we've glassed over a few things, but when you look at the models.py file and consider that from these 49 lines of code Django is going to create an entire blog website, it doesn't seem like so much code at all does it.
+
+So save the file and head back over to your browser. Refresh the admin page and click "add new." Feel free to create a few entries -- blog monkey blog!
+
+So now we've got our back-end blogging system set up and everything in in place to create a public site. Feel free to take a well deserved break. When you're ready, head over to the next section and we'll [build the public facing side of our blog].
+
+
diff --git a/old/published/Webmonkey/Frameworks/django-migrate.txt b/old/published/Webmonkey/Frameworks/django-migrate.txt
new file mode 100644
index 0000000..9cfe49f
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/django-migrate.txt
@@ -0,0 +1,158 @@
+If you started following our Django tutorials back when they first started you may be wondering about the recent news that the [http://code.djangoproject.com/wiki/NewformsAdminBranch NewForms Admin branch] of Django was recently merged to trunk.
+
+What does that mean? Well it means that, if you update your svn checkout of Django, it's going to break all the code we wrote earlier. But don't worry, the changes aren't too radical and adjusting our code takes only a few minutes.
+
+The goal of the NewForms Admin branch was two-fold. First the developers wanted to make sure that the admin app (which is a standalone app that ships with Django) used the latest Django froms code (hence the NewForms bit of the name). The other goal was to decouple the admin and make it much easier to customize.
+
+We're not going to dive into customizations today (see the [http://www.djangoproject.com/documentation/admin/ updated Django docs] if you're itching to know more details), but let's take a look at what we need to do to port our code over to the latest version of Django.
+
+But first make sure you have the latest version of Django: fire up your terminal and cd over to your Django folder. Then run <code>svn up</code> and Django will update itself.
+
+== Decoupling ==
+
+The first thing we need to do is create a new file in our blog app folder named admin.py. As part of the decoupling, a model's admin definitions now live in seperate file, which makes sense since the old Admin class really had nothing to do with the model.
+
+So open up the admin.py file and we'll re-write our admin class definition. Our old code, where the <code>Admin</code> class lived in model.py looked something like this (I've left out a few things for clarity):
+
+<pre>
+class Entry(models.Model):
+ """
+ ...all the field definitions omitted...
+ """
+
+ class Meta:
+ ordering = ('-pub_date',)
+ get_latest_by = 'pub_date'
+ verbose_name_plural = 'entries'
+
+ class Admin:
+ list_display = ('title', 'pub_date','enable_comments', 'status',)
+ search_fields = ['title', 'body_markdown']
+ list_filter = ('pub_date', 'enable_comments', 'status')
+ fields = (
+ (None, {
+ 'fields': (('title', 'status'), 'body_markdown', ('pub_date', 'enable_comments'), 'tags', 'slug')
+ }),
+ )
+</pre>
+
+Now the <code>Meta</code> class remains part of the models.py file, since it controls model-related behavior. But the <code>Admin</code> class really doesn't relate directly to the model, so open up blog/models.py and we're going to cut all that data out, so our models.py file now looks like:
+
+<pre>
+class Entry(models.Model):
+ title = models.CharField(max_length=200)
+ slug = models.SlugField(
+ unique_for_date='pub_date',
+ help_text='Automatically built from the title.'
+ )
+ body_html = models.TextField(blank=True)
+ body_markdown = models.TextField() #note, if you're using Markdown, include this field, otherwise just go with body_html
+ pub_date = models.DateTimeField('Date published')
+ tags = TagField()
+ enable_comments = models.BooleanField(default=True)
+ PUB_STATUS = (
+ (0, 'Draft'),
+ (1, 'Published'),
+ )
+ status = models.IntegerField(choices=PUB_STATUS, default=0)
+
+ class Meta:
+ ordering = ('-pub_date',)
+ get_latest_by = 'pub_date'
+ verbose_name_plural = 'entries'
+
+ def __unicode__(self):
+ return u'%s' %(self.title)
+
+ def get_absolute_url(self):
+ return "/%s/%s/" %(self.pub_date.strftime("%Y/%b/%d").lower(), self.slug)
+
+ def save(self):
+ self.body_html = markdown.markdown(self.body_markdown, safe_mode = False)
+ super(Entry, self).save()
+
+</pre>
+
+Note that we also deleted the prepopulate_from field in the slug definition. That's another thing that's moved over to the new admin.py file.
+
+Okay, now we need to define our <code>Admin</code> class according to the new conventions. Jump back to the new admin.py and paste in this code:
+
+<pre>
+from django.contrib import admin
+
+from djangoblog.blog import Entry
+
+class EntryAdmin(admin.ModelAdmin):
+ list_display = ('title', 'pub_date','enable_comments', 'status')
+ search_fields = ['title', 'body_markdown']
+ list_filter = ('pub_date', 'enable_comments', 'status')
+ prepopulated_fields = {"slug" : ('title',)}
+ fields = (
+ (None, {'fields': (('title', 'status'), 'body_markdown', ('pub_date', 'enable_comments'), 'tags', 'slug')}),
+ )
+
+admin.site.register(Entry, EntryAdmin)
+</pre>
+
+So what's different? Well, first off we import the admin module and new extend the ModelAdmin class with our own <code>EntryAdmin</code> class. Then we brought over the same definitions we use above to control <code>list_display</code>, <code>search_fields</code> and <code>list_filter</code>. Then we use one brand new bit of syntax. Remember in our original model we used <code>prepopulate_from</code> to automatically fill our slug field with whatever is typed in our title field?
+
+Well the new name is <code>prepopulated_fields</code> and instead of a string, it's now a dictionary. The key is the field to fill and the value is where to pull from. Obviously, since it's a dictionary you could add several fields if need be.
+
+The fields customizations remain the same in our case, though there is a new fieldsets option if you want to have several, uh, sets of fields.
+
+The last line of our code just registers our new Admin class and lets Django know that whenever it's displaying info about our Entry model it should follow the rules we set up in EntryAdmin.
+
+See that wasn't so bad.
+
+== New URL structures ==
+
+As I said earlier one of the main goals with NewForms Admin ws to make the Django admin more flexible. Part of the way that's achieved is through the urls.py file. So open up our project level urls.py file and you should see something like this:
+
+<pre>
+urlpatterns = patterns('',
+ # Example:
+ # (r'^djangoblog/', include('djangoblog.foo.urls')),
+ (r'^admin/(.*)', include('django.contrib.admin.urls')),
+)
+
+</pre>
+
+We're going to change that to this:
+
+<pre>
+from django.conf.urls.defaults import *
+from django.contrib import admin
+
+admin.autodiscover()
+
+
+urlpatterns = patterns('',
+ (r'^admin/(.*)', admin.site.root),
+ ... the rest stays the same...
+)
+
+</pre>
+
+Notice that we're no longer simply handing off all the admin urls to an mysterious include statement. That means we could concievably create all sort of urls and pass them to our own custom views. In fact you could have several different admin sites if you so desired.
+
+== Updating Tagging ==
+
+The last step in our transition to NewForms Admin is to update our django-tagging application. As of this writing, django-tagging hasn't caught up to the newforms admin update yet, so we're actually going to need to checkout the Newforms Admin branch of the django-tagging codebase.
+
+To do that we'll grab the files using Subversion. Paste this code into your terminal window:
+
+<pre>
+svn checkout http://django-tagging.googlecode.com/svn/branches/newforms-admin django-tagging
+</pre>
+
+Now cd into the new django-tagging folder and type:
+
+<pre>
+python setup.py install
+</pre>
+
+After that just delete the old version (if you're good with Subversion, there are other ways to do this).
+
+== Other Changes ==
+
+There are quite a few other changes to the admin section, and if you have a lot of old code to port definitely head over and [http://www.djangoproject.com/documentation/admin/ check out the new documentation]. Also highly recommended is [http://oebfare.com/blog/2008/jul/20/newforms-admin-migration-and-screencast/ Brian Rosner's very informative screencast] which covers inlines and some other more complicated things our project isn't using. \ No newline at end of file
diff --git a/old/published/Webmonkey/Frameworks/django-overview.txt b/old/published/Webmonkey/Frameworks/django-overview.txt
new file mode 100644
index 0000000..7856231
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/django-overview.txt
@@ -0,0 +1,87 @@
+Django is web framework written in Python and design to help you build complex web applications simply and quickly. If you're familiar with Ruby on Rails, think of Django as Rails for Python. It might not be technically correct, but it captures the basic idea.
+
+Django was designed from the ground up to handle two common web developer challenges: intensive deadlines and strict adherance to the [http://c2.com/cgi/wiki?DontRepeatYourself DRY principle].
+
+The results are framework that's fast, nibble and capable of generating full site mockups in no time at all. Django's slogan captures it's essence quite nicely: The web framework for perfectionists with deadlines.
+
+Bu quick doesn't mean sloppy, Django comes with a very slick built-in Admin section for administering sites, support for a variety of cacheing options, including memcached, and a host of other stable, scalable tools.
+
+But perhaps the best part about Django is its outstanding documentation. Unlike many open source projects, Django has [http://www.djangoproject.com/documentation/ very thorough and readable docs available online]. If you have any problems with our tutorials head over to the Django site for additional reading. Also consider joining the [http://groups.google.com/group/django-users django-users Google Group] which is full of helpful folks who can point you in the right direction.
+
+== Why Isn't Django a 1.0 Release? ==
+
+As of this writing Django has not yet released an official 1.0 version. The tenative schedule calls for Django 1.0 to arrive in September 2008, though that is subject to change. However both Django .95 and .96 are stable -- if not feature-complete -- releases.
+
+That said, the best way to use Django is working off the current trunk by doing a Subversion checkout. This will give you access to the latest and greatest tools and improvements and, unlike many projects, the Django trunk is remarkably stable.
+
+I've been using Django for two years on a number of production sites all built using Django trunk checkouts and have yet to encounter a bug or other issue.
+
+Of course the fact that Django doesn't have a 1.0 release will make some developers nervous and the Django team is aware of that. Django is close to 1.0 and work is progressing everyday toward that release, but remember all that stuff about perfectionists? It isn't just a slogan.
+
+The Django devs are probably tired of explaining themselves by now, but on the bright side you can rest assured that when 1.0 does arrive it's going to be rock solid.
+== Background ==
+
+Before we dive in it's worth pausing for a moment to understand where Django comes from, which has influenced both what it is and what it is not.
+
+Django was developed over a two year period by programmers working for an online-news operation (World Online in Lawrence Kansas). Eventually the team realized that they had a real framework on their hands and released the code to the public under an open source BSD license.
+
+Once it became a community project the development took off and Django began to pop up all over the web. For a complete list of Django sites check out [http://www.djangosites.org/ Django Sites], but notable examples include [http://pownce.com/ Pownce, [http://projects.washingtonpost.com/congress/ The Washington Post] and [http://everyblock.net/ Everyblock].
+
+Perhaps the most common misconception is that Django is a content management system. It's not. It's a [http://www.webmonkey.com/tutorial/Get_Started_with_Web_Frameworks framework] and it can be used to build a CMS, but it isn't like Drupal or other CMS systems.
+
+Django is designed to work in slightly modified Model-View-Controller (MVC) pattern. The original Django developers refer to Django as an "MTV" framework — that is, "model", "template", and "view."
+
+The central difference is that in Django's version of MVC development the view refers to the data that gets presented to user -- not ''how'' it looks, but ''which data''. In other words, to quote the Django documentation, "the view describes which data you see, not how you see it."
+
+It's a subtle, but important difference and it explains the additional element -- templates -- which handle how the data looks.
+
+
+== Overview ==
+
+Django was designed to make web development fast and easy, dare I even say fun. And when I say fast I mean it, once you're comfortable with Django it's not hard to go from simple wireframe to working demo site in an hour or so.
+
+For development purposes Django is entirely self-contained. It includes a command line interface, a web server and everything you need to get up and running without installing anything other than Django.
+
+That said, the web server included with Django is not intended to be used in a production environment. For that the prefered method is to run Django through mod_python or mod_wsgi. Don't worry we'll get to that in a minute, but first let's look at how you might go about building a Django application.
+
+As it turns out, building a Django app actually takes much less time than explaining how to build it.
+
+Before we dive in though, it's worth asking, what do you mean by Django app? Django's official documentation and many of its built-in tools are set up to create projects (think of this a container for your whole site) and then within projects you have many apps (section of your site).
+
+Note that apps don't need to be in projects though and in many cases it's better not to put them there.
+
+For the sake of example here's a very high-level overview of building a Django app:
+
+# Create a project using the built in command line tool (<code>python django-admin.py startproject projectname</code>). This will generate a new folder containing the project's base settings file which you can use to specify database connections, template locations and more, urls.py which defines your base urls, manage.py which contains a standard set of command line tools.
+# The next step is to create an app using the built in command line tool <code>python manage.py startapp appname</code>.
+
+Once the app folder is in place, it you look inside you'll see three files: models.py, urls.py and views.py. These are the files you'll use to actually build the app:
+
+# design your model (models.py)
+# write your URLs (urls.py)
+# create your views (views.py)
+# build your templates
+
+Django includes it's own template language, although, as with many elements of Django, it's entirely optional. You can drop in another template language if you like, though you might want to give Django's a try first. It's simple, fast and already there.
+
+The other thing to keep in mind is that Django is written in Python and requires Python 2.3 or higher. Mac OS X and most Linux distros ship with Python 2.5 so that isn't a problem. Windows users may need to install Python.
+
+== So just how does Django work? ==
+
+The simplest way to look at Django is to break it down into it's component parts. First off there's a models.py file which defines all your data model and extrapolates your single lines of code into full database tables and a pre-built (totally optional) administration section to add content.
+
+The next element is the urls.py file which uses regular expressions to capture url patterns for processing.
+
+The actual processing happens in your views, which, if you haven't seen the pattern yet, live in views.py. This is really the meat of Django, since views are where you grab the data that that you're presenting to the visitor.
+
+Here's what happens when a visitor lands on your django page:
+
+First Django consults the various URL patterns you've created and uses that information to retrieve a view. The view then processes the request, querying your database if necessary and passes the requested information on to your template. The template then renders the data in layout you've created and displays the page.
+
+== Dive in ==
+
+Now that you have at least some idea of how Django works, it's time to dive in and get your hands dirty. For the sake of example we'll be building a blog-type site. It makes a nice intro to Django and takes advantage of some of Django's handy shortcuts and other features.
+
+But don't worry we aren't going to just build a blog, we'll also walk through adding a contact form, static pages (like an 'about' page) and even integrate Django with del.icio.us web services to display all your del.icio.us links on your new Django blog.
+
+So head on over to part two of our intro to Django [Installing Django and Building Your First App] \ No newline at end of file
diff --git a/old/published/Webmonkey/Frameworks/django-templates.txt b/old/published/Webmonkey/Frameworks/django-templates.txt
new file mode 100644
index 0000000..8ded612
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/django-templates.txt
@@ -0,0 +1,239 @@
+When we left off last time we had defined some URLs for our blog and even wrote a custom view to handle displaying posts by tag. But if you point your browser to our development url (http://127.0.0.1:8000/blog/) you'll still see a Django error page complaining that the template blog/list.html does not exist, which is true since we haven't created it yet.
+
+It's time to tackle the last aspect of Django -- the template syntax.
+
+If you look back through the code we've written so far you'll find that we've point Django to a number of templates (look in the urlpatterns code and the custom view we wrote). The templates we've defined need to be created as follows:
+
+djangoblog
+ - templates
+ -blog
+ list.html
+ detail.html
+ -tags
+ list.html
+
+You can go ahead and create that directory structure -- just create a folder in your main djangoblog folder and name it templates. Then inside that create two folders, blog and tags. Then create your list and detail.html files (note that the .html extension is totally optional, I use it because it turns on the syntax highlighting in my text editor, but you can use any extension you like).
+
+== Inheritance ==
+
+If we step back for a minute and think about our blog and what our templates need to display, the first thing that jumps out at you is that there's a whole bunch of stuff that's common to every page -- a header, site navigation, sidebar, footer, etc.
+
+It would be silly (and a egregious violation of the DRY principle) if we wrote that code more than once. Luckily, like most good template languages, Django provides a way to extend a single template file. We can define our site-wide components once and then simple inherit from that file, adding in the aspects of the site that do change.
+
+So before we dive into the detail pages, let's first create a base file. Being the creative type I generally call the file base.html. So inside the templates folder you created above, add a new file, base.html.
+
+Now open that file in your text editor and let's sketch out some of the site-wide html we might need. For the sake of this tutorial I've kept things pretty simple, but feel free to get as fancy as you want with your HTML. Here's a basic starting point:
+
+<pre>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+ <head>
+ <title>My Site - {%block pagetitle %}{% endblock %}</title>
+ </head>
+ <body>
+ <div id="header">My Site</div>
+ <div id="nav">
+ <ul>
+ <li><a href="/">home</a></li>
+ <li><a href="/blog/">Blog</a></li>
+ <li><a href="/links/">Links</a></li>
+ <li><a href="/about/">About</a></li>
+ </ul>
+ </div>
+ <div id="content">
+ <div id="primary">
+ <h1>{% block title %}{% endblock %}</h1>
+ {% block primary %}{% endblock %}
+ </div>
+ <div id="secondary">
+ <h3>Recent Entries:</h3>
+ <div>
+ </div>
+ </body>
+</html>
+</pre>
+
+That should be pretty self explanatory, save perhaps the curious things enclosed in curly brackets, the <code>{% %}</code> bits. What up with that stuff?
+
+That is Django's template syntax for creating blocks which other templates can plug data into. In this case we're creating a base template with a few blocks (think of them as holes) and our other templates will extend this and fill in the holes.
+
+To see what I mean let's create the blog/list.html template. Add a new blog folder in the templates folder (if you haven't already) and create a file list.html. Now open that up and past in the line <code>{% extends 'base.html' %}</code>.
+
+Now if you revisit [http://127.0.0.1:8000/blog/ http://127.0.0.1:8000/blog/] the template not found error should be gone and in its place you should see everything we just put in base.html -- not much I'm afraid.
+
+But fear not, now that we're extending base.html we can start plugging in some values for those blocks we created earlier.
+
+Add this below the extends statement:
+
+<pre>
+{% block pagetitle %}Tumblelog{% endblock %}
+{% block title %}My Page Headline{% endblock %}
+{% block primary %}
+{% for object in latest %}
+ <h2>{{ object.title }}</h2>
+ <p>{{ object.pub_date }}</p>
+ {{ object.body_html|truncatewords_html:"20"|safe }}
+ <p>tags: {% for tag in object.get_tags%}<a href="/blog/tags/{{tag.name|slugify}}/">{{tag}}</a>{% endfor %}</p>
+ <p><a href="{{object.get_absolute_url}}">read more</a></p>
+{% endfor %}
+{% endblock %}
+</pre>
+
+Okay, first off we fill in our page title block in the head tags and then we do the same for the displayed title. The next block we fill in is the primary content block. Here's where we display the data that our generic view grabbed for us.
+
+The Django template syntax is fairly Pythonic in that your define loops using the same <code>for x in dataset</code> syntax. In this case the generic view function object_detail passes in a variable named latest (by default the fifteen latest entries, though you can go back to the urls.py and increase that number using the num_latest param).
+
+So all we do is construct a loop using the <code>latest</code> variable. Then within that loop we pull out some of our data -- again accessing an objects attributes uses the python-like dot accessor methods.
+
+The only part that requires additional explaining is the <code>object.body_html</code> section where we've applied two built-in Django template filters, <code>truncatewords_html</code> and <code>safe</code>.
+
+Truncatewords_html should be fairly obvious, this clips the the body of our post after twenty words, but also preserves the structure of the html by appending any closing tags to make sure the html is intact.
+
+The <code>safe</code> filter simply tells Django that it's okay to display HTML. Without the safe filter Django will automatically escape all HTML entities and tags. Autoescaping is a nice feature for avoiding nefarious XSS attacks and the like, but in this case, since we trust the source, we'll let the HTML through.
+
+Okay, cool, but what about tags? We do after all have tags on our entries, might as well display them which is what we do in the next line. Here we have a loop within a loop. Remember when we created our models we added a get_tags method to return all the tags for each entry? Well here it is in action.
+
+That will loop through all the tags for each entry and display them along with a link to that tag's permalink page. And note that we've used the slugify filter to make sure than any multiword tags will be hyphenated in the URL (if you remember back when we wrote our custom tag view we used a string replace function to "unslugify" the url for lookup in the datebase).
+
+The last line calls the <code>get_absolute_url</code> function that we defined when we built our model in the last lesson. This provides a link to the permalink page for each entry in the list.
+
+So click that link and what happens? Error page. You need to define the detail.html template. That's not to hard, just create the file, add the extends base.html instruction at the top and fill in the blank blocks like title and primary. This time there's no need to loop through anything since there's only one object. Just call it directly like we did inside the loop on the archive page: <code>{{object.title}}</code> etc.
+
+The code might look something like this:
+
+<pre>
+{% block pagetitle %}{{object.title}}{% endblock %}
+{% block title %}{{object.title}}{% endblock %}
+{% block primary %}
+ <ul class="page-nav">
+ {% if object.get_previous_published%}
+ <li>
+ <a href="{{ object.get_previous_published.get_absolute_url }}" title=" {{object.get_previous_published.title}}">&laquo; previous</a>
+ </li>
+ {%endif%}
+ {% if object.get_next_published%}
+ <li>
+ <a href="{{ object.get_next_published.get_absolute_url }}" title=" {{object.get_next_published.title}}">next &raquo;</a>
+ </li>
+ {%endif%}
+ </ul>
+ <h2>{{ object.title }}</h2>
+ <p>{{ object.pub_date }}</p>
+ {{ object.body_html|safe }}
+ <p>tags: {% for tag in object.get_tags%}<a href="/blog/tags/{{tag.name|slugify}}/">{{tag}}</a>{% endfor %}</p>
+ <p><a href="{{object.get_absolute_url}}">read more</a></p>
+{% endblock %}
+</pre>
+
+Note that I've made use of those <code>get_next_published</code> and <code>get_previous_published</code> functions that we defined way back when wrote our models. That way, users have some handy next and previous links for navigating through your permalink pages.
+
+Naturally you can get much more sophisticated with your HTML than this simple example.
+
+To create the templates for the tag pages you'll essentially do the same thing. In our custom tag view we returned a list of all the entries in an object named <code>object_list</code>. So in order to display them, just loop through <code>object_list</code> like we did with the <code>latest</code> variable above.
+
+==Built-in Template Filters==
+
+Before we move on, it's worth paying a visit to the [http://www.djangoproject.com/documentation/templates/ Django documentation on template filters and tags]. There's a whole bunch of useful stuff built in. You can use <code>{% if %}</code> tags to narrow and filter results, and there's also <code>{% else %}</code>, <code>{% ifequal var1 var2 %}</code>, <code>{% ifnotequal var1 var2 %}</code> and most other common programming structures.
+
+Then there's a host of template filters, like the truncatewords_html and safe filters we used above. For instance there's a handy date filter if you'd like to display your post date in something a little sexier than a UNIX timestamp.
+
+Here's what that would look like using the "date" filter:
+
+{{object.pub_date|date:"D d M Y"}}
+
+Another great filter is the "timesince" filter which will automatically convert a date into syntax like "1 week, 2 days ago" and so on.
+
+There are also filters for escaping ampersands, escaping javascript, adding linebreaks, removing HTML, converting to upper/lowercase and dozens more. In fact in two and a half years of building sites with Django I've only needed to write a custom filter once. Naturally your mileage may vary somewhat.
+
+==Roll Your Own Template Tags==
+
+One thing I do frequently do is write custom template "tags." Template tags are perhaps one of the more confusing aspects of Django since they still have a little bit of "magic" in them, but luckily it isn't too hard to work with.
+
+Template tags are a way of extending the Django template system to use it in project specific ways. For instance, custom template tags are a perfect way to handle things that don't make sense in a view, but do require some database logic.
+
+Perhaps the best example is something like a sidebar. So far ours is empty, but we can easily add a list of our most recent blog posts.
+
+Now we could write a filter that specifically fetches blog entries, but then what happens when we add links in the next lesson and want to display the most recent links? Write another template filter? That's not very DRY so let's just write a filter that fetches the most recent entries from any model with a date field.
+
+In fact we don't even need to really write it. James Bennett has already [http://www.b-list.org/weblog/2006/jun/07/django-tips-write-better-template-tags/ written some great reusable code] so we'll just use that. I strongly recommend that you have read through James' tutorial so you can see how and why this code works.
+
+Open a new file and paste in this code:
+
+<pre>
+from django.template import Library, Node
+from django.db.models import get_model
+
+register = Library()
+
+class LatestContentNode(Node):
+ def __init__(self, model, num, varname):
+ self.num, self.varname = num, varname
+ self.model = get_model(*model.split('.'))
+
+ def render(self, context):
+ context[self.varname] = self.model._default_manager.all()[:self.num]
+ return ''
+
+def get_latest(parser, token):
+ bits = token.contents.split()
+ if len(bits) != 5:
+ raise TemplateSyntaxError, "get_latest tag takes exactly four arguments"
+ if bits[3] != 'as':
+ raise TemplateSyntaxError, "third argument to get_latest tag must be 'as'"
+ return LatestContentNode(bits[1], bits[2], bits[4])
+
+get_latest = register.tag(get_latest)
+
+</pre>
+
+Now save that file in a new folder within the blog app, named templatetags. The folder name and location are important since Django only looks up template tags in specific locations.
+
+One thing to note about this code, if you look closely you'll notice that our template tag is going to fetch all entries, not just the public ones. In other words, our model allows for draft posts, but our template tag doesn't.
+
+This is the line in question:
+
+<pre>
+self.model._default_manager.all()
+</pre>
+
+There are two ways around this, one is quick and dirty: just change that line to filter only published entries. In other words:
+
+<pre>
+self.model._default_manager.filter(status=1)
+</pre>
+
+The better and cleaner way to do it would be overwrite the default manager for our Entry model. However, that's a little beyond the scope of this article, so for now we'll just use the quick and dirty method.
+
+Now open up base.html again and add this line at the top:
+
+<pre>
+{% load get_latest %}
+</pre>
+
+That tells Django to load the template tag, but then we need to grab the actual data, so head down to the sidebar section and replace it with this code:
+
+<pre>
+<div id="secondary">
+ <h3>Recent Entries:</h3>
+ {% get_latest blog.Entry 5 as recent_posts %}
+ <ul class="archive">
+ {% for obj in recent_posts %}
+ <li>
+ <a href="{{ obj.get_absolute_url }}" title="Permanent Link to {{ obj.title}}">{{ obj.title}}</a>
+ </li>
+ </ul>
+<div>
+</pre>
+
+Now if you want to override that in templates that are inheriting from base.html, just wrap that code in a {% block %} tag and then replace it with something else in the new template.
+
+== Conclusion ==
+
+The Django template system is quite vast in terms of capabilities and we've really just scratched the surface. Make sure you [http://www.djangoproject.com/documentation/templates_python/ read through the documentation for Python programmers] as well as [http://www.djangoproject.com/documentation/templates/ the documentation for template authors] and familiarize yourself with all the various built in tags and filters. Another great article is Jeff Croft's [http://jeffcroft.com/blog/2006/feb/21/django-templates-an-introduction/ Django Templates: An Introduction].
+
+It's worth noting that there's an extensive collection of useful filters and template tags on the [http://www.djangosnippets.org/ Django Snippets site], so if you ever find yourself needing a custom tag or filter, have a look through there and see if anyone has already written something that works for your project.
+
+I should also point out that if you just don't for whatever reason like Django's template system, it's possible drop in your template language, like [http://cheetahtemplate.sourceforge.net/ Cheetah] or others.
+
+Be sure to stop by for our next installment when we'll tackle a plan to import, store and display our del.icio.us bookmarks.
+
diff --git a/old/published/Webmonkey/Frameworks/django-website.txt b/old/published/Webmonkey/Frameworks/django-website.txt
new file mode 100644
index 0000000..a207154
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/django-website.txt
@@ -0,0 +1,175 @@
+Last time around we installed Django and started building a blog application. We got Django's built-in admin system up and running and explored some third-party libraries like the django-tagging project.
+
+So far we have some cool administrative tools, but no website for the rest of the world to see. This time around we'll look at building the url patterns and some "views" to sort and display our content to the world.
+
+Everything we're going to do will make more sense if you understand how Django processes your visitor's request. We went over some of this in our introduction, but here's a quick refresher course.
+
+The flow is something like this:
+
+1) Visitor's browser asks for a URL
+2) Django matches the request against its urls.py files.
+3) if a match is found Django moves on to the view that's associated with the url. Views are generally found inside each app in the views.py file.
+4) The view generally handles all the database manipulation. It grabs data and passes it on. 5) A template (specified in the view) then displays that data.
+
+With that in mind, let's start building our public site by creating some url patterns. Remember the urls.py file where we set up our admin urls in the last lesson? Open that file in your favorite text editor.
+
+Now we could define all our URLs in this file. But then what happens if we want to reuse this blog in an entirely separate project?
+
+A far better idea is to define all your app-specific URLs in a file that lives inside the app itself. In this case we're going to use a file inside the blog app, which will also be named urls.py.
+
+However, before we start with that file, we need to tell Django about it. So add this line to the project-wide urls.py file, just below the line that defines the admin urls, like so:
+
+<pre>
+from django.conf.urls.defaults import *
+urlpatterns = patterns('',
+ (r'^admin/', include('django.contrib.admin.urls')),
+ (r'^blog/', include('djangoblog.blog.urls')),
+)
+</pre>
+
+Okay, now head into the blog app folder and create a new urls.py file, which we'll use to hold all the URLs related to our blog application.
+
+==Thoughts on URLs==
+
+One of the nice things about Django is that it forces you to think about your URL designs, something many people don't spend much time considering. If perchance you've never spent too much time thinking about URLs, now is good time to [http://www.w3.org/Provider/Style/URI read the W3C guide on the subject].
+
+As the W3C points out, good URLs don't change, in fact, URLs never change, people change them. But change your URLs and you break everyone's bookmarks. So spend a bit of time designing a good URL scheme from the beginning and you shouldn't need to change things down the road.
+
+I would add one thing to the W3Cs guidelines, good URLs are hackable. So what do I mean by hackable? Let's say our blog has urls like:
+
+<pre>
+http://mysite.com/blog/2008/jul/08/post-slug/
+</pre>
+
+That would display the post whose slug is "post-slug" and was published on July 8, 2008. Ideally, if the user heads up to their url bar and chops off the <code>post-slug/</code> bit they would see all the entries from July 8, 2008. If they chop off <code>08/</code> they would see all the posts from July 2008 and so on.
+
+In other words, the url is hackable. Now, most people probably won't do that, but in addition to being useful for those that do, it also creates an easy to use structure around which to build your site. In this case the date-based structure was probably already obvious, but what about tags?
+
+<pre>
+http://mysite.com/blog/tags/tag-slug/
+</pre>
+
+This url accomplishes the same idea, but one ups it. Not only can you hack the url to get to list of all tags (provided you create such a page), it should be obvious that you could plug just about any word into the url and it effectively functions like a tag-based search engine.
+
+Okay, that's all good and well, how do we actually build the URLs?
+
+==Being Generic is Good==
+
+Let's get started, paste this code into your blog/urls.py file:
+
+<pre>
+from django.conf.urls.defaults import *
+from djangoblog.blog.models import Entry
+from tagging.views import tagged_object_list
+
+info_dict = {
+ 'queryset': Entry.objects.filter(status=1),
+ 'date_field': 'pub_date',
+}
+
+urlpatterns = patterns('django.views.generic.date_based',
+ (r'(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', 'object_detail', dict(info_dict, slug_field='slug',template_name='blog/detail.html')),
+ (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', 'object_detail', dict(info_dict, template_name='blog/list.html')),
+ (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$','archive_day',dict(info_dict,template_name='blog/list.html')),
+ (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month', dict(info_dict, template_name='blog/list.html')),
+ (r'^(?P<year>\d{4})/$','archive_year', dict(info_dict, template_name='blog/list.html')),
+ (r'^$','archive_index', dict(info_dict, template_name='blog/list.html')),
+)
+
+</pre>
+
+Now remember when I said that the url patterns determine which view Django will use to grab data from our database? In that scheme we would write our regular expressions and then point each pattern to a function in views.py.
+
+But we're cheating a little bit here by taking advantage of some built in views that Django provides, known as generic views.
+
+The developers of Django wisely figured that date-based archives were likely to be a common problem that just about every site has at least some use for, so they baked in some generic data-based views.
+
+What we've done here is take advantage of the built in views to construct our urls.
+
+Let's start with <code>info_dict</code>, which is just a Python dictionary that holds two things: a queryset that contains all our public blog entries and the name of our date field in the database.
+
+It's important to realize that Django querysets are lazy, that is Django only hits the database when the queryset is evaluated, so there's no performance penalty for defining a queryset that looks for everything and then filtering it on a case by case basis, which is essentially what we've just done.
+
+Passing the queryset to the generic view enables Django to automatically do whatever date sorting we need, for instance, to show all the entries from a single month or year. For more info on querysets, check out the [http://www.djangoproject.com/documentation/db-api/ database API docs] on the Django site.
+
+That's all the URL patterns list is, a regular expression that looks at the URL, figures out what view to use and then the view determines which entry or list of entries to show.
+
+Let's break it down and go through each part of the url pattern; we'll use the first line as an example:
+<pre>
+(r'(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$', 'object_detail', dict(info_dict, slug_field='slug',template_name='blog/detail.html')),
+</pre>
+
+The first bit:
+
+<pre>
+(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$
+</pre>
+
+is the regular expression. In this case the expression will match our permalink urls and capture the year, month, day and slug of a particular entry. That information will then be passed to the next bit <code>object_detail</code> which is the name of the generic view that will pull out a single entry.
+
+The full path to object_detail is actually <code>django.views.generic.date_based.object_detail</code>, but since we started our urlpattern definition by including the <code>django.views.generic.date_based</code> bit, there's no need to retype it every time, we just need to call the individual function, in this case object_detail.
+
+After we grab the URL info and pass it to the <code>object_detail</code> function, we also pass along a dictionary of data. Most of the time you can just pass <code>info_dict</code> here. The <code>object_detail</code> generic view is something of an exception because it needs to pass along the slug_field variable as well.
+
+I wanted to show some of the other data you can include as well, so I wrapped it in the <code>dict</code> your see above. In this case we've passed <code>info_dict</code>, the slug_field and the name of the template that Django should use to display the data.
+
+The rest of the patterns just work their way back up the url using ever-shortening regular expressions until we get to nothing, which would be the url: http:/mysite.com/blog/. We'll be using that as our archive page, so I guess you can think of this as a tumblelog rather than a traditional blog, which would probably have separate archive and home pages. Naturally you can tweak the url patterns to fit whatever design you'd like.
+
+Django's generic views are incredibly powerful and there are quite a few other options beyond just the date-based ones we've used here (there's also a super-handy built-in pagination system for some generic views). Be sure to read through the [http://www.djangoproject.com/documentation/generic_views/ documentation on the Django website] and also have a look at [http://www.b-list.org/weblog/2006/nov/16/django-tips-get-most-out-generic-views/ James Bennett's excellent guide to the various ways you can wrap and extend generic views].
+
+== Go Your Own Way ==
+
+Django's generic views can save you quite a bit of time, but you will probably encounter some situations where they don't quite do what you want. When that happens it's time to write your own views.
+
+Fear not, writing a custom view isn't hard.
+
+We've pretty much covered our blogs URLs, from date-based archives to the detail pages, but what about the pages that display our entries by tag?
+
+The tagging application actually includes some views that we could use, but for the sake of example we'll write some custom views. Rather than overwriting what's already in the tagging application, we're just going to create a views file that lives on its own in our main project folder.
+
+So, inside the djangoblog folder create a new file named tag_views.py. Now remember, before we get started there we need to tell Django about the tag_views file, so open up djangoblog/urls.py and add the last line below what's already there:
+
+
+<pre>
+urlpatterns = patterns('',
+ (r'^admin/', include('django.contrib.admin.urls')),
+ (r'^blog/', include('djangoblog.blog.urls')),
+ (r'^tags/(?P<slug>[a-zA-Z0-9_.-]+)/$', 'djangoblog.tag_views.tag_detail'),
+)
+</pre>
+
+Okay, now here we haven't included another url.py file like we did with the lines above. You could argue that we should, but just to show that you don't ''have'' to, we'll just point directly to our tag_views.py file which will soon have a function named <code>tag_detail</code>. Note that in the tag URL, we're capturing the slug param; we'll use that in just a minute to filter our blog entries by tag.
+
+Now it's time to create the tag_detail function in the tag_views.py file, so open up that file in your text editor and paste in this code:
+
+
+<pre>
+from django.views.generic.list_detail import object_detail
+
+from tagging.models import Tag,TaggedItem
+from blog.models import Entry
+
+def tag_detail(request, slug):
+ unslug = slug.replace('-', ' ')
+ tag = Tag.objects.get(name=unslug)
+ qs = TaggedItem.objects.get_by_model(Entry, tag)
+ return object_list(request, queryset=qs, extra_context={'tag':slug}, template_name='tags/detail.html')
+</pre>
+
+Okay, so what's going on here? Well, ignore the first line for now, we'll get to that in a minute. We import all the things we need, in this case the Tag and TaggedItem classes from django tagging and then our own Entry class. Then we define the <code>tag_detail</code> function, which is just an ordinary Python function that take two parameters. The first is <code>request</code> which Django passes to all view functions and the second it the slug param we defined in our URL pattern above.
+
+Now because we're using a slug (a slug is an old newspaper term, which is this context refers to the last bit of the URL and can contain letters and dashes rather than space) for our tag URLs, but words with spaces for our tags we need to get rid of the dashes and replace them with spaces. Because our slug parameter is just a string, we can use the normal Python string function to make that replacement.
+
+In the next line we look up our tag name in the database using the <code>objects</code> manager. Then we take advantage of django-tagging's built in function <code>get_by_model</code> to grab all the entries with the given tag.
+
+The last step is to return something so that Django can load our template and display the entries to our visitor. To do that we're going to use another of Django's generic view functions -- <code>object_detail</code> from the generic list views. Object detail requires a few things, first of the request object, then the queryset of results and then I've added an extra context variable named tag, so our template will be aware not just what entries to display, but also the current tag. And then the last item simple tells Django which template to use.
+
+Now we haven't created a URL for http://mysite.com/blog/tags/ to list all our tags, but that's a good way to practice writing a view function on your own. Here's a hint, you can use pretty much the same code we used for the tag_detail function, but you don't need to worry about the <code>slug</code> param. And instead of looking up TaggedItems, just grab all the tags (i.e. <code>qs = Tag.objects.all()</code>)
+
+== Conclusion ==
+
+And there you have it, a quick and dirty overview of how url patterns and view work in Django.
+
+If you point your browser to our development url (http://127.0.0.1:8000/blog/) you should see a Django error page complaining that the template blog/list.html does not exist, which is true since we haven't created it yet (visiting the tag pages will give you "list index out of range" error, also due to the missing templates).
+
+But don't worry in the next lesson well dive into Django's template system and explore all the cool things we can do, including how to write custom template filters and more. \ No newline at end of file
diff --git a/old/published/Webmonkey/Frameworks/djangoscreen1.jpg b/old/published/Webmonkey/Frameworks/djangoscreen1.jpg
new file mode 100644
index 0000000..fe7fb34
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/djangoscreen1.jpg
Binary files differ
diff --git a/old/published/Webmonkey/Frameworks/djangoscreen2.jpg b/old/published/Webmonkey/Frameworks/djangoscreen2.jpg
new file mode 100644
index 0000000..67e08d2
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/djangoscreen2.jpg
Binary files differ
diff --git a/old/published/Webmonkey/Frameworks/djangoscreen3.jpg b/old/published/Webmonkey/Frameworks/djangoscreen3.jpg
new file mode 100644
index 0000000..07c5678
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/djangoscreen3.jpg
Binary files differ
diff --git a/old/published/Webmonkey/Frameworks/intro.txt b/old/published/Webmonkey/Frameworks/intro.txt
new file mode 100644
index 0000000..e28504e
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/intro.txt
@@ -0,0 +1,58 @@
+If you've built a few websites from scratch chances are you've noticed that you have to solve some of the same problems over and over again. Doing so is tiresome and violates one of the core tenants of good programming -- Don't Repeat Yourself (DRY).
+
+Luckily for you other people long ago noticed that web developers face similar problems when building a new site. Sure, there are always edge cases which will vary from site to site, but for the most part there are four general tasks we developers have to handle -- Create, Read, Update and Delete, otherwise known as CRUD.
+
+To help you out, a number of web application frameworks have emerged over the years. You might have heard of some of the more famous frameworks -- [http://www.rubyonrails.com/ Ruby on Rails], [http://www.cakephp.org/ CakePHP] and [http://www.djangoproject.com/ Django].
+
+== What is a Web Framework? ==
+
+A web framework is a software framework designed to simply your web development life. Frameworks exist to save you from having to re-invent the wheel and help alleviate some of the overhead when you're building a new site. Typically frameworks provide libraries for accessing a database, managing sessions and cookies, creating templates to display your HTML and in general, promote the reuse of code.
+
+It's important not to confuse a framework with a content management system. While a framework deals with many of the same issues and, in some cases, may make it very easy to build a content management system, a framework is much more general.
+
+In fact a framework isn't really anything at all. Think of a framework as a collection of tools, rather than a specific thing.
+
+==What Can You Do With a Web Framework==
+
+Frameworks exist to make building a website faster and easier. Typically frameworks provide tools to cover the common CRUD cases. For instance you'll likely find libraries for accessing a database, managing sessions and cookies, creating templates to display your HTML pages and more.
+
+Frameworks also promote the reuse of code. With a good framework you only need to design, for instance, a contact form once. Then you can drop your generic contact form code into all your projects and save yourself some time and effort.
+
+Nearly any site you're going to build will have to interact with a database. Frameworks generally offer some means of doing so without having to delve into writing your own SQL every time you want to create, read, update or delete a record.
+
+Similarly, most frameworks either provide a template system, or make it easy to add on your own templating system so that common chunks of HTML that rarely change, for instance, the header and footer of your page, need only be written once.
+
+==How Do You Choose A Framework==
+
+Although having a wide range of framework choices is definitely good, it can also be a source of confusion for inexperienced developers. With all of the possibilities out there, choosing one can be a daunting task the newcomer, so how do you decide?
+
+That's something of a religious question, but a good place to start is to see if your favorite scripting language has a framework available. The Ruby in Ruby on Rails refers to the fact that Rails is a Ruby framework. So if you're a Ruby fan, Rails might be the framework for you, but there's also [http://www.nitroproject.org/ Nitro] and [http://www.merbivore.com/ Merb].
+
+Python fans have a few to choose from. Django is fast becoming the Python framework of choice, but there are other options like [http://pylonshq.com/ Pylons] and [TurboGears http://turbogears.org/]. PHP lovers can check out [http://www.cakephp.org/ CakePHP], [http://www.symfony-project.org/ Symfony] and [http://framework.zend.com/ Zend]. There are also Perl and Java frameworks for those that enjoy Perl or Java.
+
+However, just because there's a framework available in your favorite programming language doesn't mean it's the ideal choice. Each of the frameworks mentioned has its strengths and weaknesses and you'll have to evaluate each to see which is the best fit for your site's needs.
+
+Although none of these should be the sole criteria, each of these frameworks are noted for certain things.
+
+For instance, Ruby on Rails offers tight integration with JavaScript, making it a popular choice for Ajax heavy sites. Ruby on Rails even includes the Prototype Javascript Library which you can integrate directly.
+
+Django was developed for a very large newspaper website and offers a fantastic auto-generated site administration section for your site's users to create, edit and update content. It also includes built-in tools for caching data and building flexible URLs.
+
+CakePHP borrows many conceptual ideas from Ruby on Rails but applies them to PHP. Given the widespread availability of PHP on shared web hosting servers, and the fact that Cake supports PHP4, it might be the most widely usable framework.
+
+There are literally dozens, if not hundreds, of more web frameworks in all sorts of programming languages, but there just isn't room to cover them all. Perhaps the best way to choose a framework is to simply dive and and try building a site with each one. That way you can see which frameworks fits the best with your style and goals.
+
+==Popular Frameworks==
+
+**Note: I thought this section could just be a list on frameworks with link to the corresponding detail page in the webmonkey wiki.**
+
+# [Ruby on Rails http://www.rubyonrails.com/] (Ruby) (Dive in with the webmonkey tutorial)
+# [Django http://www.djangoproject.com/] (Python) (webmonkey intro)
+# [Symfony http://www.symfony-project.org/] (PHP)
+# [CakePHP v] (PHP)
+# [Zend http://framework.zend.com/] (PHP)
+# [Nitro http://www.nitroproject.org/] (Ruby)
+# [Merb http://www.merbivore.com/] (Ruby)
+# [Pylons http://pylonshq.com/] (Python)
+# [TurboGears http://turbogears.org/] (Python)
+
diff --git a/old/published/Webmonkey/Frameworks/vagablogging_submission.txt b/old/published/Webmonkey/Frameworks/vagablogging_submission.txt
new file mode 100644
index 0000000..4c6e8be
--- /dev/null
+++ b/old/published/Webmonkey/Frameworks/vagablogging_submission.txt
@@ -0,0 +1,96 @@
+Vagablogging Editors-
+
+Hello, my name is Scott Gilbertson and I'm applying for the travel blogger opening at Vagablogging.
+
+I've read Rolf's book Vagabonding, in fact it was the one of the two books that was key to my own 11 month trip around Southeast Asia (the other was Edward Hasbrouck's, The Practical Nomad) and I think it would be fun to give back to the source and perhaps inspire someone else to attempt the same.
+
+I've been a freelance writer for five years now. I'm under a full-time contract with Wired.com, though that's limited to technical/computer topics. I also write about internet technology, Linux and more for theregister.co.uk, as well as some other smaller publications.
+
+I have, when the opportunity presented itself, written about travel for Wired, for instance a how to on recharging gadgets abroad <http://howto.wired.com/wiki/Stay_Plugged_In_While_Traveling> (that's a wiki page, so anyone can edit it).
+
+I also run my own travel blog at luxagraf.net to keep friends and family abreast of my adventures.
+
+I would have to say that my travel highlight thus far was a five day camel trek through the Thar desert in India. On the third night, in the middle of nowhere, we finally hit the dunes and made camp. It had been at least 18 hours since we'd seen another living soul. While our guides were cooking dinner, the four of us on the trip decided to climb up to the top of the tallest sand dune and watch the sunset. We were sitting atop the crest of the dune, trying to avoid the rather persistant black beetles that infested all of the scrub bushes on the leeward side of the dune, when an Indian man on a camel came riding slowly over the dune below us. He dismounted and without so much as a hello began selling us beer. To me it was the perfect reminder that no matter how far you go, no matter how much you want to leave "it" all behind, it's just not possible anymore. On one hand that's sort of depressing, but on the other hand it's not -- there is afterall, nothing wrong with "it," us or the world we live in.
+
+Anyway, here's a couple of unpublished pieces. The first is my take on a newsy item about train travel in the United States, and the second is a bit more personal, some thoughts on travel and life. I've also included a narrative piece from a recent trip to Nicaragua (though I recognize that that's not the focus of Vagablogging.net).
+
+-------------
+
+America's train system was once a model for the world -- fast, luxurious and a model of efficiency. Now, if anyone bothered to ride the train, they would find it an absolute nightmare. American trains are expensive, constantly delayed and almost always slower than every other mode of transportation.
+
+Of course, if you're looking to go on a journey as opposed to just getting somewhere, the last bit might be a good thing. Sometimes it's fun to get stuck,to get off of the train in the middle of nowhere and chat with your fellow passengers while engineers tinker -- to make the old cliche about journeys being more important than destinations into a practical reality.
+
+For many though, the romance and appeal of rail travel is seriously hindered by the delays and almost inevitable late arrivals. But that's really just train travel in the U.S. In Europe and Asia the trains systems are the lifeblood of travel. In India trains aren't just romance and slow travel, the train system is vital to the economy. Not only do millions of Indians use the train to get around, the Indian Railway system is the largest commercial employer in the world.
+
+So why do the American railways suck so bad? Ben Jervey over at Good Magazine recently rode the rails from New York to San Francisco to find out. The article is worth a read in its entirety, but from the people he talks to Jervey hears about "stories of 12-hour delays on routes that would take six hours to drive; of breakdowns in the desert; of five-hour unexplained standstills in upstate New York," and worse, a train that spent two days stopped on the tracks in California. In short, riding the rails isn't the smooth, seamless process of Europe and Asia.
+
+But Jervey also find some signs that things may be improving, especially with gasoline on the rise and people increasingly fed up with air travel in the U.S. Unfortunately some of the bright spots Jervey points to aren't much, like the mag-lev train between LA and Las Vegas, which developers have been talking about ever since I was kid -- and there's still no mag-lev line.
+
+For now anyway the train in America seems limited to enthusiasts -- people chasing the old North by Northwest romance -- or those of us who don't mind arriving late, so long as the journey proves worth the undertaking.
+
+
+-------------
+
+
+Everywhere I go I think, I should live here... not just travel too and enjoy for a visit, but really inhabit. I should know what it's like to work in a cigar factory in Leon, fish in the Mekong, living in a floating house on Tonle Sap, sell hot dogs at Fenway Park, trade stocks in New York, wander the Thar Desert by camel, navigate the Danube, see the way Denali looks at sunset, the smell the Sonora Desert after a rain, taste the dust of a Juarez street, know how to make tortillas, what Mate tastes like, feel autumn in Paris, spend a winter in Moscow, a summer in Death Valley.
+
+There is, so far as I know, only one short life. And in this life I will do very few of these things.
+
+Sometimes I think that's very sad.
+
+
+---------------
+
+The bells are a constant cacophony, not the rhythmic ringing out of the hours or tolling from mass that the human mind seems to find pleasant; no, this is constant banging, the sort of atonal banging that only appeals to the young and dumb. The firecrackers bursting back over behind the cathedral add an off rhythm that only makes the whole mess more jarring.
+
+But Francisco seems entirely unperturbed and only once even glances over at toward the other side of the park, the source of all the noise and confusion. He's too fascinated with the tattoo on Corrinne's shoulder to bother with what slowly just becomes yet another sound echoing through León.
+
+Francisco is a shoe shiner, but since we're both wearing sandals he's out of luck and has reverted to the secondary universal appeal of travelers — a chance to practice English.
+
+We're sipping Victorias in a cafe just off the main park in León, Nicaragua. It's our fourth day here — with an extra day spent at the nearby Pacific beaches — in what is, so far, my favorite city in Nicaragua.
+
+Architecturally León is a bit like Granada, but since it lacks the UNESCO stamp it's somewhat less touristy and a bit more Nicaraguan, whatever that means.
+
+It's a city of poets and painters, philosophers and political revolutionaries. In fact, Nicaragua as a whole is full of poets and artists, all the newspapers still carry at least one poem everyday (U.S. newspapers used to do that too), but León is perhaps the pinnacle of Nicaraguan writing and painting, if for no other reason than it's a college town — the constant influx of youth always brings with it vitality and art.
+
+There are three separate Nicaragua universities in León and even though none of them are in session right now, as with Athens, GA the fomenting imprint of students lingers even when they are gone — political graffiti dots the cafes, bars are open later, people seem more active, the bells clang, the fireworks explode on an otherwise ordinary Sunday evening.
+
+In short, León has something that most of the rest of Nicaragua (and the U.S. for that matter) lacks — a vibrant sense of community.
+
+Of course in relation to the States nearly everywhere seems to have a much stronger sense of community and togetherness.
+
+The irony though is that just writing those words together fills me with dread and loathing, a sure sign of my own inherent Americanism.
+
+But the truth is community doesn't have to mean over-priced "organic" markets, war protests round the maypole and whatever other useless crap passes itself off as community in Athens and elsewhere in America.
+
+Every time I go abroad, not just Nicaragua, but Asia, Europe, the Caribbean, just about anywhere, the communities are somehow more vibrant, more alive, more sensual — full of bright colors, playing children, people walking to work, to the market, to the gym, to wherever. There is life in the streets.
+
+In Athens there's mainly just cars in the streets. Big, fast cars.
+
+For instance, in León the houses are not the stolid tans, boring greys and muted greens you find in Athens, but brightly colored — reds, blues, yellows, crimson, indigo, chartreuse even — the doors are not shuttered and double-bolted, there are no lawns, no barriers between the life of the home and life of the street, everything co-mingles, a great soup of public and private with each overlapping the other.
+
+The clatter of the Red Sox game drifts out the window, along with the smell of fresh roasted chicken that mingles with the dust of the street, the kids gathering in the park, the declining light of the day, the first streetlights, the evening news, the women in curlers walking in the shadows just behind the half-open wooden doors….
+
+And it makes the streets more fun to walk down, there's something to experience, things to see and hear and smell and taste.
+
+Which isn't to say that León is Paris or New York, but in its own way it sort of is. Certainly it's better than my own neighborhood where I know exactly what color the houses will be before I even step out the door — and not because I know the neighborhood, but because I know what colors comprise the set of acceptable options in the States — where the children are staked in the front yard on leashes (invisible for the most part, but it won't surprise me when the leashes can be seen), neighbors wave, but rarely stop to talk and certainly no one walks anywhere unless it's for exercise.
+
+Why are American neighborhoods so dull? Why no happy colors? Why make things more lifeless than they already are, given that our neighborhoods are set up in such away that we abandon them all day and return only at night to sleep?
+
+Dunno, but I can tell you this, León, Paris, Phnom Phen, Prague, Vientiane and just about everywhere else is far more exciting to walk around than the average American town. And it isn't just the exotic appeal of the foreign; it's about architecture, design and the sharp division of public and private those two create to make our neighborhoods into the rigid anti-fun caricature that the rest of the world sees.
+
+Do I sound like a transcendentalist-inspired, anti-american crank? Sorry about that. I like America, really I do. And I hold out hope. One day my house will be vermillion — my own small step.
+
+Plus, that's a big part of what I enjoy about traveling — seeing how other people construct their house, their neighborhoods, their cities, their way of life… see not just how it differs from our own, but perhaps see some ways you could improve our lives.
+
+Like hammocks. We desperately need more hammocks. Lots of hammocks.
+
+But León isn't perfect. In fact it fails on several levels — take that butt ugly radio/microwave/cell tower on the horizon — why the hell would you put that in the middle of otherwise majestic 18th century Spanish colonial city?
+
+León, I'll miss you, you're just about perfect as far as Central America goes, maybe just see about moving that radio tower….
+
+
+--------------------
+
+
+