Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
ATLbeer
Sep 26, 2004
Über nerd


============================================================
Experienced Django programmers click here and skip the basic tutorial below
============================================================


So what is Django?
  • Django is a python based web framework that was originally designed as a CMS for a newspaper. The CMS that was originally developed is called Ellington which is not open source but, the framework that built it is (that is Django)
What comes with Django?
  • Object-relational mapper. A drat fun one I might add if your coming from a PHP world. You'll soon see
  • Automatic Admin Interface. If there is a 'killer' component of Django, this is it. This is the biggest time saver I've ever used in web development
  • Elegant URL design. Do you know regex? Good you make any URL you want. If you don't, like me.. Fake it. It's still pretty easy
  • Template System. Some people love it. Some people hate it. Good thing? If you really hate you don't have to use it
  • Internationalization. I've never used it but, it's there I guess
So why do I want to use Django then?

    I'll quote Jacob Kaplan-Moss here, one of the creators of Django to answer that
  • Django works - right now
  • Deployment is a breeze (it can be a bit tricky though, I take a bit of qualms with this one which I'll discuss later)
  • Your site won't go down (obviously it can.. If you build it wrong)
  • Django is fast
  • Django admin will blow your mind (100% agreed!)
  • You don't need to go whole-hog
  • Django plays will with designers
  • Django comes from the real world
  • We're here to help (thats what this thread is for too!)

---------------------------------------------------------------------------------------------------------------------

Ok.. Enough fluffing... Lets get to the links.

If you don't want to read the rest of the thread and just want to start coding here are your links.

Django Website - http://www.djangoproject.com/
Django Download - http://www.djangoproject.com/download/
Django Install - http://www.djangoproject.com/documentation/install/
Django Book (best starting guide) - http://www.djangobook.com/en/1.0/
Reference Materials (always have these in an open window when your starting)
- Django Model Refernce - http://www.djangoproject.com/documentation/model-api/
- Django DB API - http://www.djangoproject.com/documentation/db-api/

---------------------------------------------------------------------------------------------------------------------

I'm going to teach you the power of Django and show you how to write a quick piece of blog software at the same time

First off. This thread is not about Python. Sorry. If you need to learn Python I highly recommend Dive Into Python a free web based book that will easily give you enough information to start programming in Django.

Second off. This thread isn't a primer or a teaching thread about MVC designs. Hopefully you at least already know what it is and why you should be using them. If you are still writing raw SQL code, that looks like SELECT * FROM articles WHERE ID=$_GET['article_id'] in a PHP file that also contains HTML code then you have some reading to do outside this thread. Your welcome to stay and follow along but, you may get lost along the way. If you post questions surrounding a topic like this please don't be shocked when people either: don't respond to you, mock you mercilessly, or just give you links and don't answer your question.

Thirdly. I'm gonna dump you off the the Django Installation instructions (Recommended install instructions for Windows Users). Sorry.. I don't really need to rehash everything thats included in the links. I (and other people in this thread) will be glad to help you out in getting the framework installed and running.

So you have a functioning and running version of Django up.. Good

1) Lets create a project
code:
 
django-admin.py startproject blog
#This creates the a directory called blog and places in it the basic files for a django project
cd blog/
# Lets change directories 
django-admin.py startapp main
#This creates a directory called main that is an application in our project.
Now we have the basic directory structure for a Django project and application
code:
blog/
	__init__.py
	main/
		__init__.py
		models.py
		views.py
	manage.py
	settings.py
	urls.py
Lets talk about the parts here.
  • manage.py
    - This is the script you'll run from the command line that does all sorts of neat stuff like start your development server, sync your database with your defined models, start-up your admin interface, etc
  • settings.py
    - Your basic config file. Contains your DB connection data, directory to your templates, what apps and extra Django modules you want the framework to load, etc.
  • urls.py
    - This is the file where you define what specific URLs do when called by your application.
  • models.py
    - This is a fun file. This is really where you conceive your web application. You merely define your models and Django can build almost the rest of the app for you
  • views.py
    - This is where all the real work happens. This is where you control and gather the information to send to the browser

So lets make sure you configured Django correctly. In the command lets type the following and you should see the following
code:
$python manage.py runserver
Validating models...
0 errors found.

Django version 0.97-pre, using settings 'blog.settings'
Development server is running at [url]http://127.0.0.1:8000/[/url]
Quit the server with CONTROL-C.
See that? It worked and you rock. Goto your browser and goto http://127.0.01:8000. You should see the following


Now lets do what it says. We need to configure Django to use a DB to actually do really useful things. Let's open settings.py and look at the DATABASE_* information. I'm going to use SQLite just for ease of use here but, your welcome to use whatever RDBMS you wish. Django supports postgre, mysql, sqlite3, oracle, and maybe MSSQL soon (I know it was in discussion). Here's what my settings.py looks like now (just the DATABASE_* section)
code:
DATABASE_ENGINE = 'sqlite3'       
DATABASE_NAME = './blog_test.db'          
DATABASE_USER = ''           
DATABASE_PASSWORD = ''
DATABASE_HOST = ''          
DATABASE_PORT = '' 
Now that we've defined our database we also want to add one of Django's best features. It's automatic admin interface.
Scroll down a bit in the settings.py file and we'll find the section called "INSTALLED_APPS". We are going to add the folowing line to that tuple: django.contrib.admin to make our INSTALLED_APPS look like the following
code:
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
)
So we've so far altered our settings file to tell Django what DB we are using and how to get it. We also added the magic line django.contrib.admin to the installed apps base. But, why did we have to add that line if it's Django's coolest feature? Why isn't it just built in? Because Django doesn't want to DO EVERYTHING for you. It's a minimal framework that you build up to do what you need it to do and no more. You only include the things you need and it only does exactly what you tell it to do. But, I digressed... Back to the blog.

We need to now sync the database that we told Django about (Django won't create the DB so create it if you haven't already) At the command line
code:
$ 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):
WOH!.. What's all this jazz. Well Django has a built in user authentication system (in the installed apps: django.contrib.auth) and since this is the first time we are syncing the database we need to tell Django who God is... So lets type yes at that command prompt and fill in the blanks. If you can't do this then I have no idea how you actually got this far anyhow
code:
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 'ATLBeer'): ATLBeer
E-mail address: [email]atlbeer@gmail.com[/email]
Password: 
Password (again): 
Superuser created successfully.
Installing index for auth.Message model
Installing index for auth.Permission model
Installing index for admin.LogEntry model
Loading 'initial_data' fixtures...
No fixtures found.
And we're all done... You've created a super-user and created the basic tables in your DB that Django uses as a "base"... Really.. Go check your DB you'll find stuff there now. Now lets go see this admin interface. At the command line again we're going to start the development server (really.. you can have multiple terminals open and just keep the dev server running in the background. It doesn't really matter)
code:
$ python manage.py runserver
Validating models...
0 errors found.

Django version 0.97-pre, using settings 'blog.settings'
Development server is running at [url]http://127.0.0.1:8000/[/url]
Quit the server with CONTROL-C.
Lets go back to http://127.0.0.1:8000 and check it out. Hmm.. pretty much the same isn't it... That's because you don't want your admin interface to show up for everyone on the front page of your website. We need to define a specific web address to goto to see it. That's going to be urls.py so lets open that file
code:
from django.conf.urls.defaults import *

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

    # Uncomment this for admin:
#     (r'^admin/', include('django.contrib.admin.urls')),
)
Pretty straight forward here. Uncomment that line there so your urls.py looks like this
code:
from django.conf.urls.defaults import *

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

    # Uncomment this for admin:
    (r'^admin/', include('django.contrib.admin.urls')),
)
If you noticed when you saved that file your Django development server restarted itself. It does this because it's monitoring all the files of your project. Whenever something changes it reloads for you to ease development. Now lets goto the URL we just defined
http://127.0.0.1:8000/admin

Pretty huh... Go ahead and log in with the superuser that you told Django about earlier.

Go ahead and poke around and come back when you smiling. If you've developed a web application before you'll soon understand just how drat cool this backend really is in a bit.

OK.. So I have a admin screen. Lets actually do something here. Remember when we first started we typed in django-admin.py startapp main? That's an application and our Django project (blog) needs to be told that the application 'main' exists. We do that simply in the settings.py file in the INSTALLED_APP tuple that we added 'django.contrib.admin' to earlier. So lets open settings.py again and add 'main' to the tuple
code:
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'main',
)
Now that Django knows about the application 'main' we need to do something with it. Lets go into the main/ directory and open the models.py file. Your going to really want to read the model API either before or directly after this section. It will tell you so much about all the things you can define here. We're going to be REALLY simple for the sake time and my head typing this all out. Our blog is going to have categories and posts... Nothing else more. If you want to add other stuff, go for it.

quote:

NOTE: MY EXAMPLE USES DEPRECATED CODE READ BELOW
Django is a pre-1.0 framework. Due to this things do change from time to time. One of this that changed since I learned Django was the model __str__ function. Django no longer prefers to return Strings from models but, unicode instead. Therefore instead of defining the function as
code:
def __str__(self):
     return self.Name
It should be
code:
def __unicode__(self):
    return self.Name
All examples of __str__ throughout this document should be __unicode__.

Thank you king_kilr for reminding me.

Now lets define our data here for our blog. In models.py I'm going to add the following.
code:
class Category(models.Model):
	Name		= models.CharField(maxlength=255)

	def __str__(self):
		return self.Name
	class Admin:
		pass
	class Meta:
		pass
Ok... Lets walk through this real quick since this was alot real fast. We are defining a class called Category that is extending a Django class called models.Model. If you want to dive into the Django source and figure out what it does go for it but, thats out of scope here. Once in the class Category we are going to the one and only attribute of the class called Name. That attribute is of type models.CharField which is a basic character field. It is going to have the properties of 'maxlength=255' which means it can't be longer than 255 characters. See.. This is where you should be reading the model-api linked before. It goes over this much better. Now the next part of the function __str__. If you've never seen this before it might not make sense but, this is best described as a human readable output of the object. When we actually have an object this should be what is printed out. We'll see this later. Now the sub class Admin. Defining this basically just tells Django that we want this model to show up in the Admin interface and we'll be getting back here later. The sub class Meta is somewhat similar to Admin. It just defines some odd stuff about the model that we also will be getting back to later. Don't worry... I know what I'm doing... I think :)

We have a real simple data model but, I want to wow you before we get into the nitty gritty here so go back to the command line and lets update our database with our new fancy model! (we're going to run python manage.py syncdb again)
code:
$ python manage.py syncdb
[b]Creating table main_category[/b]
Loading 'initial_data' fixtures...
No fixtures found.
Sweet. Django created the table for category for us. Lets go back into the Admin interface

Click on the humorously named "Categorys". See this? A pre-built CRUD interface. For any type of model that we define. You have a semi-yet? Ok.. It's not quite that cool but, it's gonna be. I promise. First lets fix that stupid "Categorys" things. Django will automatically pluralized all your model names but, doesn't quite work well with 'y' to - 'ie' yet but, we can fix that. Open up models.py again and add the following line to make your models.py looks the same as mine
code:
class Category(models.Model):
	Name		= models.CharField(maxlength=255)
	def __str__(self):
		return self.Name
	class Admin:
		pass
	class Meta:
		[b]verbose_name_plural = "Categories"[/b]
When you save your models.py and reload your admin interface you'll see the name has been changed. The Meta class does alot of stuff (since you've already read through the models-api, right?) this is by far the simplest thing it does.

If you haven't already go ahead and create a Category in the admin interface. Heck create 2. We're going to take a quick dive into the python shell and talk about the DB API before we create a more complex model. (You've created 2 categories by now I hope)

Let's open the python shell a bit differently than normally here since we want to make sure we get all the needed Django bits. At the command line we are going to type in "python manage.py shell". A normal python shell has popped up but, it has some namespace stuff preloaded in it for our convenience. (Side note.. My copy and pastes are going to look a bit different here since I'm using the iPython interactive shell. I'm note going to use any commands that aren't included in the basic shell.. It just looks different.. Imagine the In[1] is actually >>> and it'll be normal again)

In the shell the first thing we want to do is load up the model that we just defined
code:
In [3]: from main.models import Category
In [4]: Category
Out[4]: <class 'main.models.Category'>
Sweet. We've loaded in the Category name. Now this is probably a good time to just peruse the DB api. I'm going to try to explain this best as possible but, I'm not as good as the general documentation

There's a lot of stuff in the Category class that Django put there for us but, most of the time we are going to use the 'objects' part. It has all sorts of real cool functionality. Lets get all of our Categories.
code:
In [6]: Category.objects.all()
Out[6]: [<Category: Simple Category>, <Category: Other Category>, <Category: BEEESS!!!>]
See? There's all the Categories that I typed in at my admin interface (Yours are going to be different unless your a Desmond Hume like character and I am your anchor). Lets grab one of these objects and play for a second
code:
In [7]: all_categories = Category.objects.all()
In [8]: one_category = all_categories[0]
In [9]: one_category
Out[9]: <Category: Simple Category>
In [10]: print one_category
Simple Category
So what I've done here is load all of the Categories that we printed out above into the all_categories variable. Category.objects.all() returns a list so I'm taking the first (index 0) item from the list and copying it to the variable one_category. You can see that one_category is of an object of 'Category' class (we defined that remember!) and when I print one_category it gives me text. That is the return of the __str__ function that we defined earlier. If you recall the __str__ function returned the variable self.Name. "Simple Category" is the Name attribute for the object that one_category is.. Make sense?

Let's play with this object real quick.
code:
In [11]: one_category.Name
Out[11]: u'Simple Category'
In [12]: one_category.Name = "Some New Name"
Now go refresh your Category listing in your admin interface? Anything change? No.. Good..
code:
In [13]: one_category.save()
Check it again now. Now it's changed. The .save() method is quite important and pretty useful since it handles some of the work of deciding whether to UPDATE and object or INSERT a new one which we'll do now.

code:
In [14]: new_category = Category()
We're going to define a variable called new_category of class Category. Now lets set the attributes of the new_category
code:
In [15]: new_category.Name = "Brand New Category"
Yeah... So our first model wasn't too exciting but, baby steps... ok! Now lets create that object and check out all our categories again
code:
In [16]: new_category.save()
In [17]: Category.objects.all()
Out[17]: [<Category: Some New Name>, <Category: Other Category>, <Category: BEEESS!!!>, [b]<Category: Brand New Category>[/b]]
Now go refresh the admin interface and see the new objects there.

Now.. All you PHP programmers. I just defined a data structure. Created an admin interface. Managed a list of objects. Altered an object. Created a new object. All without really writing one line of complex code or one smidgin or SQL. You should have a semi-by now. If you don't then your probably a girl and your nipples should be hard then...

Lets go define our second model for our blog here.

Go back to models.py and we're going to make one quick addition first before defining the new model. We want to able to tell what user wrote what post but, we need to first load the user model into the scope we're working in. Like I mentioned a while back Django won't do some things because it doesn't want to be overbearing and just be everywhere all the time. It's actually quite polite like that. We're going to add the following line to the top of the models.py file
code:
from django.db import models
[b]from django.contrib.auth.models import User[/b]
If you noticed in the Admin interface there is a 'Users' part already there. This is part of the built in Auth package that Django has (django.contrib.auth) and we're loading the User model from that package so we can reference the same User that shows up in the Admin interface. Now lets get back to the model though.
code:
class BlogPost(models.Model):
	Title		= models.CharField(maxlength=255)
	Category	= models.ForeignKey(Category)
	Slug		= models.SlugField(prepopulate_from=('Title',))
	Author		= models.ForeignKey(User)
	PostText	= models.TextField()
	PublishDate	= models.DateTimeField(auto_now_add=True)
	
	def __str__(self):
		return self.Title
	class Admin:
		pass
	class Meta:
		pass			
Again.. Of course the Django Model API is going to explain this better but, I'm going to walk you through the important bits here. SlugField is another pre-defined class in Django that when used by the admin interface you can pre-populate it from well.. The Title field. The Author bit is fun though. Here we are referencing the Django User class and called it as a Foreign Key. Hopefully that made sense. If you don't know what a Foreign Key is you need to read a bit about relational databases because that's out of scope right now. DateTimeField is a field that contains both the date and time and auto_now_add is a flag that says the value of this attribute should be the date and time when the object is first created. And Category being a foreign key. Again we're just making a foreign relation to another table. No lets goto the command line and sync our DB with our new model.
code:
$ python manage.py syncdb
[b]Creating table main_blogpost[/b]
Installing index for main.BlogPost model
Loading 'initial_data' fixtures...
No fixtures found.
And go back to the admin interface

Yeah... I guess we're used to this by now. Make a model and sync the DB and wow.. It show up here. Well click into Blog Posts and go create a new one

Thats pretty cool right? You start typing in the Title field and the slug gets pre-built. Choose your category pre-populated from a drop down. Choose your author from a pre-populated drop down. Push save! Blog post... All your did was define the data models. Imagine how much time you had spent building back ends to your data models before. Lets create one or two posts here so we have some data. Place them in different categories so there's some differentiation.

Lets go back into the Python shell and play for a bit ($ python manage.py shell)
We need to load the models that we defined first off
code:
In [1]: from main.models import BlogPost, Category
In [2]: BlogPost.objects.all()
Out[2]: [<BlogPost: new blog post here>, <BlogPost: second blog post>]
Just the same way we loaded all the Categories above we can load all the BlogPost objects we have. Now lets take a look at one post and dive into the object a bit
code:
In [3]: all_posts = BlogPost.objects.all()
In [4]: one_post = all_posts[0]
In [5]: one_post
Out[5]: <BlogPost: new blog post here>
In [6]: one_post.Category
Out[6]: <Category: Some New Name>
In [7]: one_post.Category.Name
Out[7]: u'Some New Name'
In [8]: one_post.Author
Out[8]: <User: ATLBeer>
In [9]: one_post.Author.username
Out[9]: u'ATLBeer'
Let's step through this here and just realize how cool it is. (The numbers below are the line numbers above)
[3] We are loading all of the objects in BlogPost into the variable all_posts (this is a list) (it's a list of BlogPost objects)
[4] We are taking the first object (index 0) from all_posts and putting it into one_post
[5] We can see that the one_post variable is a BlogPost object
[6] one_post.Category is a Category object instance (that foreign key reference in the model description)
[7] one_post.Category.Name... we can go right into that object and get any attribute we want. This is a very powerful feature. Name was defined in the Category model
[8] In the same way we can go into the foreign object Category we can go into the Foreign User object here too
[9] Same thing... we can access all the attributes of the foreign related object

Let's change the category that the BlogPost one_post lives in. Walking through the code here, we are going to get a new category (BEEES!) and assign it to Category attribute of one_post and save it.
code:
In [11]: all_categories = Category.objects.all()
In [12]: all_categories
Out[12]: [<Category: Some New Name>, <Category: Other Category>, <Category: BEEESS!!!>, <Category: Brand New Category>]
In [13]: all_categories[2]
Out[13]: <Category: BEEESS!!!>
In [14]: one_post.Category = all_categories[2]
In [15]: one_post.save()
In [16]: one_post.Category
Out[16]: <Category: BEEESS!!!>
If we reload the admin interface and goto the post that we were playing with we can see that the category has been changed to "BEESS!!!"

We've been able to get all the blog posts with the objects.all() method but, what if we just wanted the posts in the category "bees" that would be useful for our software
code:
In [17]: all_categories
Out[17]: [<Category: Some New Name>, <Category: Other Category>, <Category: BEEESS!!!>, <Category: Brand New Category>]
In [18]: a_category = all_categories[2]
In [19]: a_category
Out[19]: <Category: BEEESS!!!>
In [20]: posts_in_category = BlogPost.objects.filter(Category=a_category)
In [21]: posts_in_category
Out[21]: [<BlogPost: new blog post here>, <BlogPost: second blog post>]
[17] listing out all the categories
[18] lets assign a_category to the objects in the all_categories list with the index 2 (which is the beess!! category)
[19] just make sure I got that right
[20] assign posts_in_category all the posts in 'a_category' using the objects.filter method.
--- We are telling BlogPost to find all posts in which the Category is the same as 'a_category'
[21] print out posts_in_category

Now Python loves lists... Even lists of objects and we can use a for loop to interate through all these.
code:
In [22]: for post in posts_in_category:
   ....:     print post.Title
   ....:     
   ....:     
new blog post here
second blog post
Cool huh? I haven't written one line of SQL yet... And I'm not going to. You almost never will with Django unless your models are really complex or you need a very weird query.

Lets hop back to the Admin interface real quick and look at the list of BlogPost objects.

That's not very helpful. Just listing the name there. We have a lot of information in the model but, it's only displaying the name. Well, like I've said before. Django is will only do what you tell it to. How do we get more information here? Lets go back to the models.py and to the BlogPost Model
code:
class BlogPost(models.Model):
	Title		= models.CharField(maxlength=255)
	Category	= models.ForeignKey(Category)
	Slug		= models.SlugField(prepopulate_from=('Title',))
	Author		= models.ForeignKey(User)
	PostText	= models.TextField()
	PublishDate	= models.DateTimeField(auto_now_add=True)
	
	def __str__(self):
		return self.Title
	class Admin:
		pass
	class Meta:
		pass
We've talked about the Meta class but, we skipped over the Admin class. Let's add the following lines to the Admin class and save
code:
class BlogPost(models.Model):
	Title		= models.CharField(maxlength=255)
	Category	= models.ForeignKey(Category)
	Slug		= models.SlugField(prepopulate_from=('Title',))
	Author		= models.ForeignKey(User)
	PostText	= models.TextField()
	PublishDate	= models.DateTimeField(auto_now_add=True)
	
	def __str__(self):
		return self.Title
	class Admin:
		[b]list_display = ['Title', 'Category', 'Author', 'PublishDate']
		list_filter = ['Category', 'Author', 'PublishDate'][/b]
	class Meta:
		pass	
Now these of course, again, are described in depth in the model api but, in short the list_display array tells the Django Admin interface what attributes of this object you want to display. The list_filter array is very cool. It makes those attributes filterable in the right hand side of the interface. Stop reading about it... Refresh your admin page and check it out

Check out the filters... Especially the date filters. I love that...

Ok.. We have all of this but, we still don't have a webpage.. Lets get started on that. This is where we start getting to the meat of a web app.
For people who already know Django, I'm skipping generic views here for teaching sake.. Yeah. I know we should use them but, they can be confusing when your first learning.

Let's make a really stupid 3 HTML page website. Django's view system and template system can do MUCH MUCH more but, we just want HTML output for right now and this is a really fast way. I HIGHLY recommend you now add basic Django view and urls.py documentation and the Django template reference to your ever growing reading list. Don't worry.. You won't use everything in there at first but, it's good to have a mile-high view before diving in.

I'm going use this ridiculously simple HTML example as a basic template for my front page
code:
<html>
	<title>My stupid Django Blog</title>
	<body>
		<center>
			Category 1 | Category 2 | Category 3
		</center>
		
		<hr>
		Blog post 1
		<hr>
		Blog post 2
	</body>
</html>
I'm a coder.. Not a web designer.. shoot me. You can do better I'm sure.
This file is going to be created in our blog project root in a new directory called templates and be called front page
code:
blog/
	__init__.py
	__init__.pyc
	blog_test.db
	main/
		__init__.py
		__init__.pyc
		models.py
		models.pyc
		views.py
	manage.py
	settings.py
	settings.pyc
	templates/
		frontpage.html
	urls.py
	urls.pyc
(Ignore the files with .pyc extensions... These are merely compiled python files. They aren't bothering anyone.

This following topic is a bit like skinning a cat. I've never heard anyone tell me, this is the proper way to do this. It's listed as one of the methods in the official documentation and it's the method that I find most flexible but, it's certainly not the only way. Also note that you don't even need to use the built in template system. Just import your own in and use that. Django doesn't care. But, caveat empor..This is my personal method and may not be for everyone.

First lets open up urls.py and add a line to make our front page
code:
from django.conf.urls.defaults import *

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

    # Uncomment this for admin:
    (r'^admin/', include('django.contrib.admin.urls')),
	(r'^$', 	'main.views.front_page'),
)
The line that we added (r'^$', 'main.front_page') has two parts. The first part r'^$' is a regex to match the root of our website / and the second part loads the view from the module main called front_page. If we goto http://127.0.0.1:8000 we'll see an error message ViewDoesNotExist. Well.. Lets fix that error and go create our view

Open up main/views.py and define the front_page view
code:
def front_page(request):
	pass
When we refresh the page again we get a different error now... Does not return an HttpResponse object. A what now? Well you can read all about those in the Request and Response objects documentation but, just follow along here for a bit and it's not that big of a hurdle we need to jump

First we need to import the objects that we need. We're going to add these lines to the top of our views.py file
code:
from main.models import *
from django.http import HttpResponse
from django.template import Context, loader
The first line there is loading in all of the models that we defined before (BlogPost and Category), then we load in the HttpResponse object that DJango was bitching a bout before. Then we load in 2 template functions Context and loader. Simply put loader grabs a bunch of HTML code (like what we created earlier) and Context allows us to take variables we load up here and push them to the HTML code and allow HttpResponse and the Django template to render the finalized HTML

Lets take care of that HttpResponse error that Django is still yelling about. We're going to make the function front_page return a HttpResponse object. Here is my views.py file now
code:
from main.models import *
from django.http import HttpResponse
from django.template import Context, loader


def front_page(request):
	return HttpResponse()
When we reload the page it's just blank now but, we don't have an error. That's a good first step. If you want to be funny change the function return to "return HttpResponse('hey yeah!')" and you can see exactly how this is all working.

We want to load the HTML file that we created before as a template so we need to tell Django where to find our templates (remember that subdiectory we created). So open up settings.py and scroll down to TEMPLATE_DIRS. You must use absolute directories and remember when you deploy your app to change this. I've forgotten that a few times and it's a little detail that is easy to overlook. Here's what the TEMPLATE_DIRS portion of my settings.py looks like
code:
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.
    '/Volumes/Storage/Work/Projects/TestProjects/blog/templates/',
)
Now lets go back to views.py and make a few changes to load this template up
code:
def front_page(request):
	[b]template = loader.get_template('frontpage.html')
	context = Context()
	
	return HttpResponse(template.render(context))[/b]
You don't really need to know what these functions are actually doing 90% of the time. Read the documentation for a detailed idea here. We won't be focusing on any of the inner workings of any of them and the only one we'll really be dealing with is the Context object in the future. So go ahead and reload your front page and you should see the crappy HTML frame we have there. Now we want to get rid of the "Category 1" | "Category 2" place holders there. We're going to replace those with the live objects from our database and just like we did in the shell we're going to access them the exact same way. This is why I showed you the shell. It's an easy way to learn how to manipulate the objects and try out different things before you place code in your view. I usually try, test, evaluate and refactor code a half dozen times before it ever goes into my view. Because of this the code in my view is very well tested and vetted before it ever even enters my application. Just like the shell we're going to load all the categories with Category.objects.all(). Then we're going to put it into the context variable. Notice we're passing this into our template render function. This is how the objects we work with here reach our HTML
code:
def front_page(request):
	template = loader.get_template('frontpage.html')
	
	all_categories = Category.objects.all()
	
	context = Context(
			{
				'all_categories'	:	all_categories,
			}
			)
	
	return HttpResponse(template.render(context))
You recognize that first line but, that context variable just got all sorts of funky. You can read all about in the docs but, in a simple manner look at it like this: The name in 'quotes' on the left is the variable name that is getting passed to the template engine. The name on the right side of the colon is the variable name in the view. The names on the right and the left can be different or the same. I usually prefer the same unless common sense dictates otherwise, makes it less confusing.

So the template is now getting feed the categories we need to replace them so they show up. Lets open back up frontpage.html. This is where pre-reading the Django Template Reference is going to come in handy :v:

Remember.. the 'all_categories' variable we are passing the template is a list of objects just like in the DB API (remember that for loop?). We can reference that objects in the same way (pretty much, in most cases) in the template engine. So in the HTML code I can say a_category.Name and it prints the name or a_category.id and prints the ID. I can also use the same for loop and loop through the list. So here's my modified frontpage.html now
code:
<html>
	<title>My stupid Django Blog</title>
	<body>
		<center>
			{% for category in all_categories %}
				<a href="/category/{{category.id}}/">
					{{category}}
				</a>
				|
			{% endfor %}
		</center>
		
		<hr>
		Blog post 1
		<hr>
		Blog post 2
	</body>
</html>
In that for loop in between the <center> tags: Each iteration I get an object from the all_categories list and in Django the {{ }} braces basically mean export those contents into the HTML. So I'm dumping out each categories ID into the a href link so we can link to each category and then printing it's name in the link.

Now we want to print the last 5 posts on the front page (we are going to skip pagination since I'm tired at this point... But, this is just a simple example and I'm running into the 50,000 character limit on a single post... oh god I've written too much)
Back into views.py I'm going to load 5 blog posts.
code:
def front_page(request):
	template = loader.get_template('frontpage.html')
	
	all_categories = Category.objects.all()
	first_posts = BlogPost.objects.all().order_by('-PublishDate')[:5]
	
	context = Context(
			{
				'all_categories'	:	all_categories,
				'first_posts'		:	first_posts,
			}
			)
	
	return HttpResponse(template.render(context))
Now the line first_posts = BlogPost.objects.all().order_by('-PublishDate')[:5] This is where Django being lazy (remember not loading things unless you ask them) is actually a benefit. Django has a lazy query method. It doesn't actually execute most queries until you really need them, so you can manipulate most queries and Django won't execute them until you actually need the data out. So here when I slice the array down to the first 5 elements [:5] Django is actually only fetching 5 items from the DB. Neat huh? I'm also ordering the posts with the modifier method .order_by(). Going back to frontpage.html I'm going to do the same iteration that I did for the categories.
code:
<html>
	<title>My stupid Django Blog</title>
	<body>
		<center>
			{% for category in all_categories %}
				<a href="/category/{{category.id}}/">
					{{category}}
				</a>
				|
			{% endfor %}
		</center>
		
		{% for post in first_posts %}
			<a href="/post/{{post.Slug}}/"> {{post.Title}} </a><br>
			<i>Written By: {{post.Author}} posted {{post.PublishDate|timesince}}</i><br>
			{{post.PostText}}
			<hr><br>
		{% endfor %}
	</body>
</html>
Walking through the additions here. I'm iterating through my list of posts again and in the same was as the categories making a link but, using the Slug that is defined in our model instead of ID. Hopefully everything here should make sense except for the {{post.PublishDate|timesince}}. Django's template system has some exceptionally fun filters for things. the "timesince" filter make it print "2 hours ago" instead of just the time.

Some of the more powerful simple features of Django.

Let's quickly go through the next two pages, since hopefully you've caught on here. I'm only going to stop to explain new things from now on

The Category page.

Alter urls.py to add the line
code:
(r'^category/(?P<cat_id>\d+)/$', 'main.views.category_filter'),
Unlike in the front page example I am passing the category ID in the URL string here and need to fetch it out. That is the <cat_id> portion of the regex part and I'm going to send this URL to the view category_filter in the main app. Here's my function category_filter in views.py
code:
def category_filter(request, cat_id):
	template = loader.get_template('category_filter.html')
	all_categories = Category.objects.all()
	this_category = Category.objects.filter(id=cat_id)[0]
	posts_in_category = BlogPost.objects.filter(Category=this_category)
	
	context = Context(
			{
				'all_categories'	:	all_categories,
				'posts'				:	posts_in_category,
			}
			)
	return HttpResponse(template.render(context))
The category ID is passed from urls.py to the function parameter cat_id. With cat_id I can query the Category objects and find the category the ID is the primary key to (NOTE: THERE IS NO ERROR CHECKING IN MY CODE, YOU SHOULD DO ERROR CHECKING). I then load all the posts that are in that category and pass both the categories and the posts in the categories to the template that's listed below (it's near identical to the front page)
code:
<html>
	<title>My stupid Django Blog</title>
	<body>
		<center>
			{% for category in all_categories %}
				<a href="/category/{{category.id}}/">
					{{category}}
				</a>
				|
			{% endfor %}
		</center>
		
		{% for post in posts %}
			<a href="/post/{{post.Slug}}/"> {{post.Title}} </a><br>
			<i>Written By: {{post.Author}} posted {{post.PublishDate|timesince}}</i><br>
			{{post.PostText}}
			<hr><br>
		{% endfor %}
	</body>
</html>
Now for the post view I'll add this to my urls.py
code:
(r'^post/(?P<slug_url>[-\w]+)/$', 'main.views.post_view'),
Now create the view called post_view for this URL
code:
def post_view(request, slug_url):
	template = loader.get_template('post_view.html')
	all_categories = Category.objects.all()
	blog_post = BlogPost.objects.filter(Slug=slug_url)[0]
	
	context = Context(
			{
				'all_categories'	:	all_categories,
				'post'				:	blog_post,
			}
			)
	return HttpResponse(template.render(context))
And the related post_view.html

code:
<html>
	<title>My stupid Django Blog</title>
	<body>
		<center>
			{% for category in all_categories %}
				<a href="/category/{{category.id}}/">
					{{category}}
				</a>
				|
			{% endfor %}
		</center>
		
		<hr>
		
			<a href="/post/{{post.Slug}}/"> {{post.Title}} </a><br>
			<i>Written By: {{post.Author}} posted {{post.PublishDate|timesince}}</i><br>
			{{post.PostText}}
			<hr><br>
		
	</body>
</html>
Now to everyone that is just now learning Django or just went through this for the very first time, like I said previously there are many ways to skin a cat and I left out a few of Django's powerful features (such as Generic Views, Extending Templates, and many many more). This was merely just a very basic overview of the simplest functionality that Django has to offer. Basically it's throwing you into the deep end with instructions on how to tread water. NONE of the code listed above I would trust in production. There's no error checking or sanity checking for any of the parameters. Django has some built in escaping and SQL injection functionality but, as with every framework you shouldn't blindly trust it.

It's a very powerful, and very open framework. You can mostly pull out any component and replace it with whatever you want.

ATLbeer fucked around with this message at 23:39 on Mar 7, 2008

Adbot
ADBOT LOVES YOU

ATLbeer
Sep 26, 2004
Über nerd
Official Django Resources:
Blogs about Django Development:
Django Powered Websites:
Django Modules:
  • Django Tagging (for all your Web 2.0 tagging needs, also a great example of GenericRelations which is wicked cool)
  • Django Comments (Extension of the built in comments system)

ATLbeer fucked around with this message at 02:40 on Mar 6, 2008

Git
Aug 21, 2004

That's one hell of an OP. I'll kick off the stupid questions:

I've been coding small Django apps mostly for personal use for a while now and it's awesome. However, I don't think I've ever had cause to use anything other than render_to_response from django.shortcuts. Am I an idiot for using it exclusively? If so, what should I be doing instead?

ATLbeer
Sep 26, 2004
Über nerd

Git posted:

That's one hell of an OP. I'll kick off the stupid questions:

I've been coding small Django apps mostly for personal use for a while now and it's awesome. However, I don't think I've ever had cause to use anything other than render_to_response from django.shortcuts. Am I an idiot for using it exclusively? If so, what should I be doing instead?

Like mentioned in the OP... There's a dozen different ways to render out in Django. Or just use an entirely different render engine entirely...

So far I've seen
- My method of loading the template, loading a context object, using template.render to parse and return to HttpResponse
- render_to_response passing in the template and a tuple of objects
- the RequestContext handler passing the request, a tuple of objects, and then use the template.render again

Honestly.. It doesn't really matter. The variables all get passed to the template in the same manner. I went through all the manners and even though my method is MUCH MUCH more verbose than render_to_response I prefer it merely because it is verbose. I can easily understand the code mostly because I'm a visual person and I tab out my tuples to line them up vertically for easy visual reference.

Any way is OK and I have not heard of a "best practices" method around the topic.

hey mom its 420
May 12, 2007

Git posted:

That's one hell of an OP. I'll kick off the stupid questions:

I've been coding small Django apps mostly for personal use for a while now and it's awesome. However, I don't think I've ever had cause to use anything other than render_to_response from django.shortcuts. Am I an idiot for using it exclusively? If so, what should I be doing instead?

Yeah mostly you'll use render_to_response, but what you can also do is return 404 errors or 403 redirects. A nice thing to take advantage of is that you can return other views, just with different parameters, which can be very useful sometimes.

bitprophet
Jul 22, 2004
Taco Defender
Yes, render_to_response() will be used in the majority of situations, especially since you can give it a RequestContext in order to use context processors (although I do this often enough that I tend to write my own render() which is just a 2-line shortcut to doing so). The rest of the time I tend to be returning a Response subclass generated in some non-template-related fashion such as a simple CSV output, or an HttpResponseRedirect; or aforementioned 404/403 via 'raise Http404' or 'raise Http403' (if there is no 403 then I must've made my own at some point, heh).

rotor
Jun 11, 2001

classic case of pineapple derangement syndrome

quote:

The 'D' is silent dumbass

Then why didn't they just name it "Jango"?? :argh:

bitprophet
Jul 22, 2004
Taco Defender

rotor posted:

Then why didn't they just name it "Jango"?? :argh:

Ask this guy

king_kilr
May 25, 2007
A note about the OP, you define __str__ in your models, however when you query the db using the api it's attributes are unicode, which I believe means you are using svn, and therefore you should have defined __unicode__ instead, let me know if I'm wrong, either way: yay django, and use trunk :D

<deleted user>

rotor posted:

Then why didn't they just name it "Jango"?? :argh:

I'm going to laugh if it has to do with the jazz guitarist Django. I forget his full name.

ATLbeer
Sep 26, 2004
Über nerd

king_kilr posted:

A note about the OP, you define __str__ in your models, however when you query the db using the api it's attributes are unicode, which I believe means you are using svn, and therefore you should have defined __unicode__ instead, let me know if I'm wrong, either way: yay django, and use trunk :D

Yes.. I screwed up.. Old habits die hard. I literally typed this up in a hurry during a 2 hour lull at work. You are correct. The SVN trunk defines it as __unicode__ I'll edit it to reflect that.

genericadmin posted:

I'm going to laugh if it has to do with the jazz guitarist Django. I forget his full name.
Yep.. Django Reinhart

Scaevolus
Apr 16, 2007

Wikipedia posted:

His name is pronounced [dʒɑ̃ŋgo ʀeˈnɑʀt].
Wait the D is silent? :psyduck:

bitprophet
Jul 22, 2004
Taco Defender

genericadmin posted:

I'm going to laugh if it has to do with the jazz guitarist Django. I forget his full name.

Already posted the Wiki link, but, yup. It's because Adrian Holovaty, one of the core dev group members and arguably the founder, really has a thing for gypsy jazz and thought it'd be a neat name v:shobon:v

Sgt. Raisins
Oct 21, 2007
Damnit
Don't forget This week in django. An awesome weekly podcast about everything django.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
I was having a lot of trouble getting Django running on windows until I found this guide which sped things up. The official guide just wasn't saying how to do this installation on windows very well.

I am a product of Rails and have been running through a few tutorials here. I am new to this so I'll be back with a few questions later on once I've finished exploring a little more. Impressed with some of the things it does and unimpressed with the difficulty involved in doing them. Perhaps I don't understand the purpose in Django's complexity yet but maybe some alias' are in order, those are just my first impressions.

Nolgthorn fucked around with this message at 20:11 on Mar 6, 2008

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Is there any reason to put your template files outside of the project directory?

Specs seem to encourage this, but they also mention that each app of your project is checked for a templates folder just in case.

I am for some reason having trouble using generic views with app/templates folders. My project seems to be looking at app/templates/app/template.html, where the second /app shouldn't be there.

OP, the admin interface is cool and all but it reminds me of scaffolding in Rails. It's nothing nearly as fascinating as Django's generic views, the automatically generated authentication and permissions system or Django's development web server never needing to be restarted.

It's awesome :v:

hey mom its 420
May 12, 2007

Putting them in separate folders decouples your application from your templates a bit more. For instance, you can release a new version of your application and people who are using it just replace the application folder and the templates stay intact if they are using their own or something.

Have you tried explicitly telling Django where the templates are located by adding an entry to TEMPLATE_DIRS in settings.py?

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Yes, I have. I was curious as to when you would want to use the app/templates folder instead of using the one referenced in settings... Also I was just bringing it up for discussion how generic views don't seem to support the app/templates folders, only the settings referenced ones.

The other really cool feature about Django, does it actually go through to figure out exactly what data will be needed then gets it all at once? I don't have to explicitly tell the application ahead of time what all will be needed?

I just want to check with you guys to see if that's true, it seems too good.

hey mom its 420
May 12, 2007

If you mean what I think you mean then yeah, because querysets are lazy. They are only evaluated when evaluating them is absolutely necessary (see QuerySets are lazy)

So if you have
code:
my_results = YourModel.objects.all() #not evaluated, no DB access
my_results = my_results.filter(something='blah') #not evaluated, no DB access
my_results = my_results.filter(something_else='foo') #not evaluated, no DB access
result = my_results[0] #evaluated, DB is hit
all_results = list(my_results) #evaluated, DB is hit

hey mom its 420 fucked around with this message at 16:11 on Mar 7, 2008

king_kilr
May 25, 2007
You can also use select_related() to be more efficient(for example if you have an Entry model that is fkeyed to a Category model, you can use this to get the categories with the entries, that way you won't have an extra query whenever you access the category attr on the entry).

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

Bonus posted:

So if you have
code:
my_results = YourModel.objects.all() #not evaluated, no DB access
my_results = my_results.filter(something='blah') #not evaluated, no DB access
my_results = my_results.filter(something_else='foo') #not evaluated, no DB access
result = my_results[0] #evaluated, DB is hit
all_results = list(my_results) #evaluated, DB is hit

In your example would Django not look ahead and see that you wanted 'all_results', therefore only have to hit the database once to get it and return the value of 'result' from that?

What if you have
code:
my_results = YourModel.objects.all() #not evaluated, no DB access
my_results = my_results.filter(something='blah') #not evaluated, no DB access
my_results = my_results.filter(something_else='foo') #not evaluated, no DB access

all_results = list(my_results)
result = my_results[0]
Would the DB get hit twice, or only once? Is what I'm saying too complex for a framework to be able to do... If you derived 'result' from 'all_results[0]' instead of 'my_results[0]', then it wouldn't have to hit the DB twice correct?


Edit: Wait, I think I'm getting it, the reason is that 'my_results' is a model object. As soon as that model is dumped into another variable then the model object needs to contain data. So, it's not as if Django looks ahead to find out what all you are going to be using entirely before hitting the DB.

Nolgthorn fucked around with this message at 16:58 on Mar 7, 2008

bitprophet
Jul 22, 2004
Taco Defender
The deal with the per-app template loader is that it throws all the templates into one big namespace (no other way around this given that every request for a template is a single string, e.g. 'index.html' or 'appname/index.html') so if you have two different apps, both with an 'index.html', it'll only pick up the first one it sees. So this basically forces you to 'namespace' your templates no matter which template loader you use.

Also, as you saw, the generic views assume this setup by default (i.e. 'appname/templatename.html') so if you're using the per-app loader, you either need to make the extra folder, or override every generic view call with the correct template location (you can do this, by the way - you can just pass 'template_name=blah' to any generic view to override the template it uses).

Hope that makes sense, typing this in a hurry :)

bitprophet
Jul 22, 2004
Taco Defender

Nolgthorn posted:

Would the DB get hit twice, or only once? Is what I'm saying too complex for a framework to be able to do... If you derived 'result' from 'all_results[0]' instead of 'my_results[0]', then it wouldn't have to hit the DB twice.

Absolutely not - how could it? That's asking the Python interpreter to start making guesses about what you're doing with your code...doesn't make any sense. Put another way, the 'my_results[0]' call comes before the other one - having that line change its behavior when you remove a line farther down the file would just be :psyduck:

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
My psychic nerd head exploder beams are in full effect!

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.
Has anyone here with Django experience also used Pylons? I'd previously always written my pages as mod_python extensions and then moved on to using Pylons. Now, after I have my site all set up again using Pylons, I've heard a lot about Django being the better choice for a framework. Reading through this example, I've seen some things I like and dislike about doing things the Django way instead, but the one thing I noticed the most was that it seemed to be a lot more work to set up from scratch.

So, any insight as to why Django is a better choice of framework or whether it does take more time to set up?

ashgromnies
Jun 19, 2004
This post makes me want to learn Django... anyone know of a good cheap webhost that supports using it?


edit: oh, this place looks solid http://www.webfaction.com/services/hosting

anyone have experience?

ashgromnies fucked around with this message at 20:22 on Mar 7, 2008

ATLbeer
Sep 26, 2004
Über nerd

ashgromnies posted:

This post makes me want to learn Django... anyone know of a good cheap webhost that supports using it?

I know MediaTemple has a beta up
- http://www.mediatemple.net/labs/grid/gc-django-beta.htm

The Django website has a decent list as well
- http://code.djangoproject.com/wiki/DjangoFriendlyWebHosts

SmirkingJack
Nov 27, 2002

ashgromnies posted:

This post makes me want to learn Django... anyone know of a good cheap webhost that supports using it?

If it is just for learning purposes then I always vote for a local virtual machine. Install VMware Server (free) and slap your favorite *nix OS (free) and set it up. If you already know what you are doing then it's a breeze, if you don't then it will give you good knowledge of how a web server works that will be valuable later on. The ability to take snapshots of your system and roll it back if you royally screw something up is also really nice.

No Safe Word
Feb 26, 2005

ashgromnies posted:

This post makes me want to learn Django... anyone know of a good cheap webhost that supports using it?

It works on Dreamhost, but a lot of goons hate dreamhost. And it's also not super-easy to get working on Dreamhost either.

But I've got my little ToME monster search app hosted on there and it runs just fine for the low volume it has to handle.

ashgromnies
Jun 19, 2004

SmirkingJack posted:

If it is just for learning purposes then I always vote for a local virtual machine. Install VMware Server (free) and slap your favorite *nix OS (free) and set it up. If you already know what you are doing then it's a breeze, if you don't then it will give you good knowledge of how a web server works that will be valuable later on. The ability to take snapshots of your system and roll it back if you royally screw something up is also really nice.

Nah, I want to write my personal site to run on a Django backend so other people can view it...

http://www.webfaction.com/services/hosting looks like they have what I want, but I don't know if I could set up some sort of version control system on there.

edit: oooh One-click webdav and subversion repositories (over SSL)
this is getting a little off-topic though but they look like they'd be a good Django webhost :)

ashgromnies fucked around with this message at 20:34 on Mar 7, 2008

hey mom its 420
May 12, 2007

How about going with a VPS? I hear slicehost are really good and also I think legalcondom is offering good and cheap VPS hosting for gunes.

ashgromnies
Jun 19, 2004

Bonus posted:

How about going with a VPS? I hear slicehost are really good and also I think legalcondom is offering good and cheap VPS hosting for gunes.

Slicehost costs more than I'd like to pay for, though... I can get Webfaction hosting with ssh and svn and all sorts of fun stuff for like $70 a year versus $240/yr for Slicehost... considering my site is just personal and won't have any advertising or anything on it to make money I want a cheap solution :)

csammis
Aug 26, 2003

Mental Institution

ATLbeer posted:

Django Web Framework: The 'D' is silent dumbass

You umbasses :argh:

No Safe Word
Feb 26, 2005

Although I would prefer something that didn't use the negative-space version of the logo, you can buy t-shirts and hoodies with the django logo on it here: http://django.spreadshirt.com/us/US/Shop/

If it was just the text in white I'd totally buy it :(

ATLbeer
Sep 26, 2004
Über nerd

No Safe Word posted:

If it was just the text in white I'd totally buy it :(

I'm going to be at PyCon next week. If I run into any of the Django guys I'll mention it because I want a shirt that looks decent too.

king_kilr
May 25, 2007

ATLbeer posted:

I'm going to be at PyCon next week. If I run into any of the Django guys I'll mention it because I want a shirt that looks decent too.

See you there! Are you sprinting?

ATLbeer
Sep 26, 2004
Über nerd

king_kilr posted:

See you there! Are you sprinting?

No.. I'm doing SXSW the first part of the week so I can't take a full 2 weeks off work. Although if anyone has a sprint that is just sickly amazing and I have to, I can probably get permission to stay in the frigid north for a bit more but, it's very unlikely.

qwertyasdf
Nov 11, 2003

csammis posted:

You umbasses :argh:

I am using this famework for a project now, and all this time I have been pronouncing it with a D. Duh-Jango :(

However this framework blows everything out of the water in terms of making a content based website. I just wish the template language was a little looser and allowed recursion.

Habnabit posted:

Has anyone here with Django experience also used Pylons? I'd previously always written my pages as mod_python extensions and then moved on to using Pylons. Now, after I have my site all set up again using Pylons, I've heard a lot about Django being the better choice for a framework. Reading through this example, I've seen some things I like and dislike about doing things the Django way instead, but the one thing I noticed the most was that it seemed to be a lot more work to set up from scratch.

So, any insight as to why Django is a better choice of framework or whether it does take more time to set up?

I also looked at pylons. Pylons stuff is a bit more modular, while django has a tendency to slowly bleed together in the deployment stages. However for the minor inconvenience you get a actively developed framework, some of the best documentation on a project I have ever seen for free, and the amazing admin interface (thats surprisingly easy to extend). Pylons seems to want to be more like Ruby on Rails, and more for making webapps, as well as being a framework you kind of pick and choose different parts of to piece together your own framework.

FUN DEBUGGING TIP: if you throw a print statement into your pages, and you are running the webserver using the manage.py runserver, it will print out to that window what ever you printed.

qwertyasdf fucked around with this message at 00:29 on Mar 8, 2008

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

ATLbeer posted:

I'm going to be at PyCon next week. If I run into any of the Django guys I'll mention it because I want a shirt that looks decent too.

Nice, I think there's going to be more than a few of us there.

Adbot
ADBOT LOVES YOU

bitprophet
Jul 22, 2004
Taco Defender

Addict posted:

I just wish the template language was a little looser and allowed recursion.

It does support recursion, just not straight out of the box. I'm doing it on one of my personal apps and I am reasonably sure I or someone with a similar approach has an item up on djangosnippets.org (which is down right now or I'd try to find it for you).

My approach is not well abstracted nor will it gracefully fail if you get it into an infinite recursion scenarion, but is still pretty simple - it simply renders the template given to it, re-binds a single object in the sub-template's context dict, and returns the output.

It's the first templatetag in this file and is used on todo item objects (hence the re-setting of 'item' in the new template's context).

Needs a 'kickoff' template which calls it the first time, then a 'sub' template which calls it the 2nd through the Nth times, at least in my usage, although I can't think of any obvious reason why they couldn't be the same one (but it has been a while since I whipped that up so I could be wrong).

Also, a big :fuckoff: to you lucky bastards going to PyCon, I'd love to go (and should go, since we have a Django book coming out soonish which I should be trying to hype) but don't have enough vacation days due to using some of this year's, last year (for my honeymoon though, so it was worth it).

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply