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

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.

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

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

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.

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.

ATLbeer
Sep 26, 2004
Über nerd

ashgromnies posted:


Okay guys I am having another issue, syncdb isn't syncing the database like it should. I changed the BlogPost model to look like this:

What do I need to do to get it to really sync and add that column to the table?


Yeah.. Thats a knock for Django right now. Especially during rapidly changing developments. It's hard to alter schemas quickly and efficiently.

It's currently an open issue in the dev group of the Django Project - http://code.djangoproject.com/wiki/SchemaEvolution

There also is some community code contribution that helps this out a bit as well - http://code.google.com/p/django-evolution/

ATLbeer
Sep 26, 2004
Über nerd

king_kilr posted:

Take 50 out of quotes, I'm pretty sure it is try to do this int(str("50")).

I dunno if you posted in the right thread or not but, I'm a bit confused at what your trying to do there

"50" itself is a string. There's no reason to cast it into a string str("50") again.
- "50" == str("50") == True

To cast the string "50" into an integer (as you said 'Take 50 out of quotes') you would just int("50") the str part is redundant.

ATLbeer
Sep 26, 2004
Über nerd
http://code.google.com/appengine/

Django support out of the box :hawaaaafap:

It's the only framework supported :holy:
http://code.google.com/appengine/articles/django.html

Grr... Looks like the parts that are supported are only the request handling, and template engine side. No support for the Django ORM. Looks like there's already a problem on the Dev side about BigTable and the Django ORM mixing since BigTable has built in support for joining.

ATLbeer fucked around with this message at 15:50 on Apr 8, 2008

ATLbeer
Sep 26, 2004
Über nerd
Figure I'd post this here first since I'm looking for people that would be reading this thread anyhow.

Any Django programmers in the greater Atlanta area?

I have a pile of programming work on my desk that is going to be impossible for me to do in this lifetime and I need some help doing the heavy lifting in the form of a contractor(s). I'm looking for

Python
Django (If you have good experience working in WebDev with other frameworks but, are learning Django thats fine too)
HTML / CSS Experience
Javascript / AJAX Experience a plus
MySQL experience a necessity.


We are doing very rapid application development for a big company. Not everything you do will see the light of day (public) and you WILL have to sign a NDA. This is a non-negotiable, sorry. Only get in contact with me if you understand what this means and are comfortable working with a NDA. You really have to be based in the ATL area. This can't be a telecommute thing, sorry (unless you live in a really cool exotic local and I can get my company to cover my T&E there... You better be a rockstar though :D) (about 99% kidding there)

GTech students. I know your probably the in the middle of your senior design work or exams. Don't worry, go ahead and shoot me an email and a resume (if you have one) as well. If your work is good enough and I can wait a bit for the semester to be over.

atlbeer (at) gmail.com
Things to include:
- Resume
- Current / previous websites with a short description of what your work for the site was, a bit about it's architecture
- Open Source projects?
- Have you written any Django or Python modules? Include some links.
- Have you worked with other types datastores (BigTable, CouchDB, etc?) mention it
- Have you had any work with Hadoop? mention it.

ATLbeer
Sep 26, 2004
Über nerd

duck monster posted:

Oh hey my perfect Job. Django with posibility of working with "quirky" backends. (Hadoop & Couch.).

pls move the job to Western Australia thanks.

So just humorously I checked to see what it would take to fly out to the underside of the world (never been there before :D)

From Atlanta the cheapest flight (business class :v: )..

Atlanta -> Los Angeles (4hr 52m) (+2hr layover)
Los Angeles -> Bangkok (17hr 30m) (+16hr layover)
Bangkok -> Perth (6hr 15m)

And the return trip
Perth -> Phuket (6h 15m)
Phuket -> Bangkok (1h 25) (+8hr layover)
Bangkok -> New York (17h 30m) (I think that's actually an over the north pole flight, kick rear end)
New York -> Atlanta (2h 41m) (+4 hr layover)

NINETY HOURS OF TRAVEL... for only $9k USD...

My rear end feels sore just thinking about that..

Although for $17kUSD I can fly on Thai Airways...

Sorry man.. It's small planet with airplanes but, that's so far away.. Hahah..

If there's anyone else in this thread that's interested I'd send an email this weekend because Monday I'm going to post a SH/SC thread and start expanding my search options.

ATLbeer
Sep 26, 2004
Über nerd

Larry Horse posted:

Yep, that's exactly how it looks. And it works!

I think it's a testament to how good Django is that whenever I have to do anything somewhat "manually" I wonder if I'm doing it right.
I had the same reaction when I started using Django myself. I found myself implementing something that was already built into Django.

For example if you didn't know. You have a model already pre-built. Need a form for that model?

ModelForm = form_from_model(SomeModel)
ModelForm.as_ul()

Poof..

ATLbeer
Sep 26, 2004
Über nerd
Has anyone seen a clever way to store revisions or changes to data?
(That wasn't a great way to explain it. Basically a have a set of models but, I want to be able to go back and explore the past versions and easily identify the differences between the older version and the current version)

I have a couple of ideas kicking around in my head but, I don't want to reinvent the wheel if someone has already found a clever way to do it.

ATLbeer
Sep 26, 2004
Über nerd

Bonus posted:

Yeah, ummm, do you mean like version control? Like mercurial, git, svn, etc.

The triple post below you got it right...

BTW, how the gently caress do you triple post!

ATLbeer
Sep 26, 2004
Über nerd

Bonus posted:

Ooh, you mean like revisions are stored in wiki pages, kind of like that? Ah, I don't know, but it seems like the cool triple post nailed it. lol

Yeah djnago rcs looks pretty cool actually. It looks fairly beta though. I want to take a peak under the hood to see how hacky it is.

ATLbeer
Sep 26, 2004
Über nerd

duck monster posted:

Its that drat robot again :argh:

He seems to be stuck in a negative incrementing loop. First triple post, then double post, now single post.

I think he's broken now

ATLbeer
Sep 26, 2004
Über nerd
Just want to bump with the 1.0RC Roadmap and Timeline

http://groups.google.com/group/django-developers/browse_thread/thread/5ce124e7526dad

quote:

This is a call for comments on the proposed Django 1.0 roadmap and schedule.
Note that though this is worded in the future perfect tense, it is only a draft;
I'm looking for feedback and comments from the community before the core
developers and I post a the final version of this document (which I will do
over the weekend).
What's will be in 1.0?
======================
The primary reason we've not yet released 1.0 is the long feature
wish-list. We need to balance this list of features against the need
for a timly release and speedy process. To that end, we'll categorize
all the features of 1.0 thusly:
* Must-haves: features that, if not completed, are worth delaying the
release. That is, if the work on this list is not completed by a
release date, we'll push the date.
This of course means that these features are the "A" features, and we'll
ask anyone who can help to focus on these features *first*.
* "Maybe" features: things that *should* be in 1.0 and should be worked on
in the run up to the release. If, however, features on this list aren't
completed, they will be dropped.
* "No" features: things that specifically will *not* be in 1.0, and which
we'll ask developers not to focus on. We need to trim down to hit dates,
after all.
Must-have features
------------------
1. ``newforms-admin``.
It's clear from discussion on this list that most consider a release without
``newforms-admin`` to be a bad idea. Further, ``newforms-admin`` is nearly
done; we've already started talking about merging it to trunk.
2. Replacement of ``oldforms`` throughout Django.
Nothing in Django 1.0 should rely on the deprecated ``oldforms`` package.
We'll need to replace ``oldforms`` usage in generic views, and in
``django.contrib.auth``
``django.contrib.comments`` still uses ``oldforms`` as well, but there's
special situation here; see below.
3. Making Django 100% WSGI compliant.
This simply involves fixing ticket #285. We've delayed doing this to avoid
the backwards-incompatible change, but we must make this change before 1.0.
"Maybe" features
----------------
Again, these are features that *should* be in 1.0. In most cases, they're
actively being worked on by members of the development community and simply need
focus by committers (more about how that process will work below).
These features are arranged in *rough* order of importance.
1. Signal performance improvements (#6814).
2. Large file uploads (#2070).
3. ``INSTALLED_APPS`` refactoring (i.e. ``app()`` objects) (#3591).
4. File storage refactoring (#5361).
5. Model-level validation (#6845).
6. Full ``GenericForeignKey`` support in newforms-admin (#4667).
7. Land GeoDjango as ``django.contrib.gis``.
8. Many-to-many intermediates (#6905).
9. Fix all known bugs preventing Django from running on alternate Python
implementations. In practice this means fixing any bugs filed before 1.0 beta
from people working on running Django on an alternate VM.
10. De-cruftify custom template tag loading (including removing custom template
tag ``__path__`` hacking) (#6587, etc.).
11. Better support for controlling middleware ordering (#3591).
12. Syntax for self-referencing fields in queries (#7210).
13. Finish documentation refactoring.
Features not in 1.0
-------------------
Unfortunately, the only way to get this done is to say no a lot. Let's start
now:
1. Aggregation support. Although this is a Summer of Code project that's looking
*very* promising, the timeline for SoC won't fit with the aggressive schedule
we're setting for 1.0. Further, it's a "dangerous" change in that it modifies
parts of Django's query engine, and that needs to be rock-solid for a 1.0
release.
The good news is that it'll make a kick-rear end 1.1 feature!
2. Any other additions to ``django.contrib``. Though there are many nice
candidates out there, we simply don't have time to roll them into Django
in time for a release. We'll come up with a "contrib process" post-1.0
and start looking at this then.
3. Any additional database backends. Again, the overhead in integrating a new
database backend is too much. These will need to remain external backends
until after 1.0.
4. Any features not on this list.
We want to ship bug-free, so we'll dedicate as much of our time to bug
stomping as possible. This means that feature requests will need to be
deferred.
Schedule
========
Django 1.0 will be released in early September.
The general release process will be:
* An alpha release containing all must-have features, but likely not
bug-free. We'll push hard to have all the must-haves done in time
for ample testing.
The alpha release will also promote any "pending deprecation" warnings to
full-blown deprecation warnings.
* Two beta releases.
All "maybe" features must be completed by the first beta; after that,
Django will enter feature freeze for about a month while we kill bugs.
* At least one -- and hopefully only one --release candidate. The candidate
release will mark a total freeze (as well as a string freeze for
translators); only outright bug fixes will be accepted past this point.
* A final release.
* A big loving party.
We will hold development sprints in between each release to focus on the next
release.
Dates
-----
July 10-12 ``newforms-admin`` sprint in person at EuroPython and around
the world in IRC.
July 18 or 19 Push to 1.0 alpha sprint in the San Francisco area, and in IRC.
July 20 **1.0 alpha.**
August 1 or 2 Push to beta sprint in Lawrence, and etc.
August 5 **1.0 beta 1.**
August 8/9 Push to beta 2 sprint, location TBA.
August 12 **1.0 beta 2.**
August 15/16 Release candidate sprint, location TBA.
August 19 **1.0 rc 1.**
August 22/23 Final release sprint, location TBA.
August 26 Earliest possible 1.0 release date, or perhaps rc2.
September 2 **1.0**
All the releases until 1.0 will be "snapshot" releases: we won't be backporting
fixes -- even security fixes -- but will just be fixing bugs in the next
release.
Process
=======
Each feature on the list (both "must-have" and "maybe") gets a "lieutenant" (to
steal of term from the Linux community) and a committer assigned. It's OK if
this is the same person, but the idea is that one committer can keep an eye and
commit from patches from a number of trusted lieutenants. In most cases, the
features on the todo list have obvious lieutenants; we'll need to assign missing
ones and also committers. I'll start putting together this list tonight; right
now it's mostly in my head.
James, as the release manager, will be in charge of keeping the schedule. He'll
keep track of who's working on what issues so that bug reports can be
efficiently routed; he'll also nag, cajole and (if necessary) berate developers
who are in danger of missing deadlines.
Once 1.0 is out we'll appoint a "version manager" (thanks for the idea, Rob).
This person will be responsible for maintaining the 1.0 release series, which
means backporting security fixes and "important" bugs and releasing 1.0.1, etc.
Similarly, as soon as we have a volunteer we'll appoint a 0.96 version manger
who will do the same with 0.96. We'll continue to support 0.96 until 1.1 ships.
With the 1.0 release, however, we will stop support 0.95 and earlier. This is
somewhat flexible; if someone has a stake in one of those older versions we'll
happily let them continue to maintain those releases, but if nobody steps up the
core team won't be able to do it.
--------------------------------------------
Comments are, of course, highly welcome. Fire away.
Jacob

ATLbeer
Sep 26, 2004
Über nerd

StickBoy posted:

I'm just learning Django. I love it so far. I have been a big fan of python for awhile but never did much with it.
I'm having some problems in the admin class that I was wondering if you guys could help.
I am trying to make a family type model. You have the person, parents, siblings, and kids. The best way I found to do this was have a ManyToManyField("self") in the name Model for each of these.
This works just fine so far. I can add new people on the admin page. But when I try to change a person I get this error:

TypeError at /admin/main/name/4/
Cannot resolve keyword 'name' into field

Here is my model for it:
code:

Are you using .96 or SVN? There was a bug in MTM a long while back that I know has been patched and refactored in SVN. Your model looks correct in syntax.

ATLbeer
Sep 26, 2004
Über nerd

duck monster posted:

For Django hosting, checkout Slicehost. Its just a dirtcheap vHost, and they are pretty cool guys. Select debian (naturally), apt-get up to python 2.5, follow the apache->django setup and serve django like a motherfucker. too easy.

And by cheap I mean 'absurdly cheap'.

Thats exactly the deployment set-up I plan on using +memcache

I'm tagging that with AMZN S3 for static file hosting via a CNAME forward media.mydomain.com so I don't have to run lighttp or a second Apache instance. I'm hoping it flys for a time during my ramp up phase.

Has anyone looked at deploying Django with mod_wsgi instead of mod_python. I've heard there are some performance benefits over mod_python but, it looks like you might have to hack your code base a bit to make it compatible. I've googled but, it's a bit sparse.

ATLbeer
Sep 26, 2004
Über nerd

Sivart13 posted:

This is an epic change. Like, to the level that that trac page should have festive balloons and fireworks following your cursor.

Followed by rewriting all your models.py files :\

It's a great change just breaks a lot.

ATLbeer
Sep 26, 2004
Über nerd
God.. Anyone want to rewrite my OP to update it to 1.0? I probably won't be able to get to it for another month or so...

You get good karma and probably instant gold status. :v:

ATLbeer
Sep 26, 2004
Über nerd

Space Kimchi posted:

You mean like the one you're paying to run your Django application on? :confused:

Offload your statics files to S3 or any other CDN. It's usually cheaper and faster* than either double tasking an app server or by getting another hosting account just for static media.

*cheaper and faster is not universal. As always depends on scale and your costs. In general though it is comparable and efficient.

ATLbeer
Sep 26, 2004
Über nerd

geera posted:

How is the state of Python and Django on Windows? I'd like to use them here at work and I have a free Windows 2003 server to host them on. However, it looks like Windows users have a lot of hoops to jump through and I don't see any information on getting this setup to work with IIS. I've started tinkering with them today and I'm already having issues with the MySQL-python drivers not wanting to install.

Should I just give up now and try to find somewhere to get Linux running?

http://www.vmware.com/products/server/

Your real problems are going to be in the DB bindings (which you've already discovered). I believe Postgres has cleaner bindings in Windows than MySQL but, it's been years since I've played with Python on Windows. (cleaner meaning easier to install)

And IIS.... Wow... I would try Apache2 for Windows. I've used it before and it's not as "friendly" as IIS on Windows but, it still works. I would be hesitant to have it in production though. I know there was PyISAPI bindings and you could probably force Django to work in WSGI mode with it but, I have no idea if it's been done (probably has, there are crazy people everywhere)

ATLbeer
Sep 26, 2004
Über nerd

MetaKnyght posted:

I've searched for information on this, but can't really seem to find anything useful. I think my Google-fu has gotten weak.

What is the best way to run something automatically every so often? I want to go through my database and update it every 15 minutes or so. Is there any way to do this from within the main Django application, or does it need to be a seperate process or cron job? And finally, what is the best method for locking the database while the update is running so anybody accessing the web interface isn't going to receive partially updated data? Thanks!
The first part of your question is easy. You can't do it solely within Django. You'll have to set up a cron job that calls a script to run every 15 minutes. I've done it before and it's quite easy to do really. I use Django Bootstrap so that I can simply just code in my cron script just like you can in a normal view. Import all your models make your DB calls and exit out

Your second question is pretty hard. There are a few ways to skin this cat and the first thing that pops in my head is to have a DB table that has a "lock" boolean to be true when the cron is running and use a decorator around views that alter the DB. So when a view is called alters the DB you can redirect to a polite message to try again in a bit.

Unfortunately this isn't a good user experience. I'm not sure of the exact situation that your working in that needs a full lock on the tables but, there's few options to really use here. If your user experience is critical and you don't want 1 minute down times (which is essentially what your doing) every 15 minutes you need to refactor this somehow. Is there anyway you can simple store up an array of updates that you want to do as your analyzing your data and then run through them while locked as opposed to locking doing all the queries analysis and updating then unlocking, etc...

ATLbeer
Sep 26, 2004
Über nerd

tayl0r posted:

Another question:

I'd like to build a quick and dirty administration tool for 3 database tables with foreign keys to each other. It's a pretty standard relationship.

The database is oracle, and the tables are already created by our database admins. I only have read and write access to it, not any admin permissions.

What do I do at this point, in regards to the data model?
Do I just setup my data model to mimic what already exists?

Will Django just start reading and writing to it without it actually running in any SQL code to modify the tables?

You still have to generate the models.py file for an application then fire up your app.

You can either do it by hand or use a built in Django tool. I recommend a bit of both

Configure all your database settings like normal (DATABASE_NAME, etc) then run python manage.py inspectdb > appname/models.py and Django will automatically construct the models.py file for you in your application. I highly recommend going into that models file and just checking it to make sure that it actually makes sense and has identified the relationships correctly.

If you run syncdb after this thought Django will add some tables to your database for user administration and permissions like it always does for every app.

ATLbeer
Sep 26, 2004
Über nerd

Ansible posted:

Wow, I love Django already. Never programmed in Python before, but was able to setup a linux VM and blow through the OP in under two hours. There are a few changes besides __unicode__ in 1.0 but they weren't a big deal.

I'm glad the tutorial still works. I'm working on the itch to rewrite it all from scratch and I just might start a 'stupid-simple' for beginners Django blog as a motivation to do a whole rewrite.

There's a bunch of little things in the tutorial that need refreshing since .96 -> 1

__str__ -> __unicode__ is an obvious one
template.render(context) instead of render_to_response
Not including all the all powerful context_processors which rock and are mandatory for any real app
Aggregate is a sweet feature
And just an all around refresh with better coding standards

This might be my April project

ATLbeer
Sep 26, 2004
Über nerd

king_kilr posted:

You're fine using render_to_response I think he meant it in the reverse. context processors are basically a way to have a "global" template variable. So say you want a logic form on every page you could put it in a template context processor so every single view didn't have to provide it.

Yep... i inverted it... The shortcut of remder to response is the best practice

ATLbeer
Sep 26, 2004
Über nerd

Mashi posted:

That's where I'm getting the readings from. I don't think its middleware because the same middleware is always run but the page load time can very between 30ms and 160ms. I'm also noticing that the slower pages show many more "context switches". Something to do with threads I think, though my app is single threaded.

Something isn't right. Can you post one of your slow views? Your using the development server currently? MySQL is installed locally? What OS?

ATLbeer
Sep 26, 2004
Über nerd
Not quite ready for the OP but, I want to share this with you all first just to get some feedback and some basic error checking. I'm looking to finish off these tutorials sometime this week and start a new thread for 1.0+ since the OP here is quite old.

http://simpledjango.com/tutorial/

ATLbeer
Sep 26, 2004
Über nerd

geera posted:

I've read through the first couple pages and it seems well enough, but there have been several grammar/spelling/punctuation issues. Just figured you'd want to know so you can polish it up a bit.

Otherwise thanks for the tutorial, I can't get enough of them being the Django newbie that I am :)

That sounds like my writing :D

Yeah, there will probably wind up being about 12 sections in total. They I'm going to fill in some of the Quick Reference material.

This blog isn't meant to replace the formal documentation but, merely augment. It's just going to show a basic tutorial and some normal design patterns for application development

ATLbeer
Sep 26, 2004
Über nerd

slobodan posted:

I was using the jQuery library flot for a while, and it's great. Easy to use, and the API is simple enough.

Flot's the way to go. I tried using Google's Visualization API's but, honestly it's really a mess. I found their methodology to graph construction to to be a bit cumbersome and not intuitive. Flot rocked. I pointed Flot to a URI that spit out JSON and it made a graph and it rocked

ATLbeer
Sep 26, 2004
Über nerd

m0nk3yz posted:

Man if only we had an example

http://sam.bluwiki.com/blog/2008/05/extending-user-model-profiles-in-django.php
code:
from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    karma = models.IntegerField(default=1, core=True)
    url = models.URLField(default="", core=True)
    user = models.ForeignKey(User, unique=True)
settings.py
code:
AUTH_PROFILE_MODULE = 'core.UserProfile'
Signals... Haven't played with them that much yet
http://docs.djangoproject.com/en/dev/topics/signals/

ATLbeer
Sep 26, 2004
Über nerd

Yay posted:

Ok ignore everything below, after spending hours googling, I'm apparently a spaztard, because 'django file uploads' tells me exactly what I needed to know, I needed to pass in request.FILES and POST. you win, Internet.

Don't worry. I can't tell you the number of times I've reinvented the wheel in Django and in Python. When I have a something I'm looking for a solution now the first thing I do is browse through the Python docs for a few minutes then browse the Django docs. Usually something new will stick out at me and usually lead me to a solution and make me learn a new module or builtin

ATLbeer
Sep 26, 2004
Über nerd

king_kilr posted:

Google Summer of Code has announced the selected projects and Django is participating again this year: http://socghop.appspot.com/org/home/google/gsoc2009/django . Last year brought us great stuff like the comments rewrite and aggregation/query expressions. I've been accepted to work on multiple database support so if that's something you need please follow along on django-dev(or ping me here) since I'll be sending an email to -dev every week starting this week to discuss the status of that including the API.

A "bug" (almost) I ran into recently was having to do with date handling in Django. It's great to be able to find all messages from a certain month or day (e.g. Message.objects.filter(DateCreated__month=1, etc) but, the resolution of the search to only days creates a tricky situation when your dealing with more granular data.

You can't do searches for items for the last hour for example
code:
from datetime import datetime
now = datetime.now()
Message.objects.filter(DateCreated__month=now.month, 
                       DateCreated__day=now.day, 
                       DateCreated__year=now.year, 
                       DateCreate__hour=now.hour)
The problem, I believe, has to do with some database dependencies behind the QuerySet abstraction layer. Why I bring this up is that my solution to this problem (which I believe also allows it to be a bit transportable across RDBMS) is to use unix time as a date/time store instead of MySQL Time. If your time is stored as an unix time double it allows you a very fine resolution for queries (to the microsecond?).

I'm not sure what other project dependancies there are in changing the time storage technique or if this should be resolved by a new model type like PreciseDateTimeModel, etc instead of reworking QuerySet to a different date/time format.

Just throwing it out there as something I ran into recently.

ATLbeer
Sep 26, 2004
Über nerd

king_kilr posted:

Hrm, a change like that would almost certainly be rejected for Django itself since it would break backwards compatibility, however you could write your own DateField implementation that looked exactly like the Django one except it stored data as a Unix timestamp, see http://docs.djangoproject.com/en/dev/howto/custom-model-fields/

EDIT: Also, if all the backends actually support extracting the hour out of a datetime field there's no reason you couldn't propose just that addition.

MySQL doesn't support hour in it's datetime implementation. :(

I might write up a custom model. I've basically added the logic adhoc in a model manager off a DecimalField.

ATLbeer
Sep 26, 2004
Über nerd

my stepdads beer posted:

Anyone have any experience/recommendations for django forums?

There's a slightly out of date wiki on Django projects

http://code.djangoproject.com/wiki/ForumAppsComparison

ATLbeer
Sep 26, 2004
Über nerd
n/m

ATLbeer
Sep 26, 2004
Über nerd

mmm... Proxy models look quite useful

Adbot
ADBOT LOVES YOU

ATLbeer
Sep 26, 2004
Über nerd

Mulozon Empuri posted:

'ello django people

I need to do this: users = User.objects.all().order_by("profile__name"), but I need it to be ordered case insensitive. ['A', 'C', 'd', 'F'] instead of ['A', 'C', 'F', 'd']

Any easy way to do this?

Edit: oh, it works the right way in postgre but not in sqlite..

Best way I've seen to do is using the .extra() method in a QuerySet

http://docs.djangoproject.com/en/de...ect-params-none

User.objects.all().extra(select={'lower_name': 'lower(profile__name)'}).order_by('lower_name')

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