Today we are going to populate the database created last time (part 2). For this I'll create small script that is not very clean and optimized, but it works and was created in less than hour. It is a good lesson of Django model API, but do not use it to learn Python :)
I'll show the code first and then comment the most important parts.
#!/usr/bin/env python
# Configuration of db population system.
# It will create about 1000 games, 100 subcategories and 8 categories for defined sites.
SITE_ID = (2,)
CATEGORIES = ('Action', 'Platform', 'Kids', 'Sport', 'Simulation', 'Puzzle', 'Card', 'Board',)
SUBCATEGORIES = ('One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve', 'Thirteen')
GAME_IMGS = ('_init/A.gif', '_init/B.gif', '_init/C.gif')
SUB_IMGS = ('_init/S1.gif', '_init/S2.gif')
GAME_DATA = ('_init/game.swf', '_init/game.dcr', 'http://jonca.vdl.pl/')
GAMES_IN_SUB_MAX = 20
CHARS = 'abcdefghijklmnoprstuwyz'
# Hack to properly initialize Django ORM
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'games4all.settings'
import time
from datetime import date
from random import randint, choice
from django.contrib.sites.models import Site
from games4all.gampor.models import Category, Subcategory, Game, GAME_TYPES
def name_generator(chars=10, variance=5, words=1, multiline=False):
""" Generate random texts. """
def word(length):
r = [choice(CHARS) for x in range(0, length)]
r.append(' ')
return ''.join(r)
result = []
for i in range(0, words):
result.append(randint(chars-variance,chars+variance))
result = [word(x) for x in result]
result[0] = result[0].title()
result[-1] = result[-1].strip()
if words > 1 and multiline:
result[0] = result[0].strip()
result.insert(1, '\n')
return ''.join(result)
def populate_categories(site_id):
""" Create categories for site with passed id. """
s = Site.objects.get(id=site_id)
for cat in CATEGORIES:
c = Category(url_name=cat.lower(), list_name=cat, title_name=(cat+' games'))
c.save()
c.sites.add(s)
print cat
populate_subcategories(c)
def populate_subcategories(c):
""" Create subcategories for passed category object. """
for scat in SUBCATEGORIES:
scatn = c.list_name+' '+scat
scatu=c.url_name+'-'+scat.lower()
s = Subcategory(url_name=scatu, list_name=scatn, title_name=(scatn+' games'))
s.category = c
s.save_screenshot_file(scatu+'.gif',file(choice(SUB_IMGS),'rb').read())
s.save()
print '.',
populate_games(s)
def populate_games(s):
""" Create games for passed subcategory object. """
for i in range(0, randint(1, GAMES_IN_SUB_MAX)):
name = name_generator(words=3)
uname=name.lower().replace(' ','-')
type = randint(0,2)
g = Game(
title=name,
url_name=uname,
active=True,
game_type=GAME_TYPES[type][0],
description=name_generator(words=randint(7,25)),
how_to_play=name_generator(words=randint(7,25),multiline=True),
rating = randint(0,5),
hit_count = randint(0,500)
)
t = time.localtime(time.time()+randint(-10000000,1000000))
g.publish_date = date(t[0],t[1],t[2])
g.save()
if 0 <= type < 2:
g.width = randint(400,500)
g.height = randint(300,400)
if type == 0:
g.save_local_file_file(uname+'.swf',file(GAME_DATA[0],'rb').read())
else:
g.save_local_file_file(uname+'.dcr',file(GAME_DATA[1],'rb').read())
else:
g.url = GAME_DATA[2]
g.save_screenshot_file(uname+'.gif',file(choice(GAME_IMGS),'rb').read())
g.subcategories.add(s)
# Start population of site if run from command line.
if __name__ == '__main__':
for site_id in SITE_ID:
populate_categories(site_id)
You can run the script with following command, but you may have to set PYTHONPATH to folder above games4all to get it work properly.
python populatedb.py
The populating may take some time because it not only inserts database records, but also copies image files in rather not very optimal way.
Lets back to the code. First part contains simple configuration with site id (use id you created in admin tool), names to use for categories and subcategories, and also names of image files etc. for use in generation.
Below configuration we are importing modules but the first thing to do is to set DJANGO_SETTINGS_MODULE to proper value so Django ORM can find the database configuration.
The name_generator() is very simple and stupid function that generate texts with variable word length. It will be used for game titles, game descriptions and game how to play instructions.
The populate_categories() takes site id and then creates all categories and links them with site. For each category it also calls populate_subcategories() to create subcategories. Please look that we have to save category c.save() and then link it to site using c.sites.add(s). The constructor takes most of values.
The populate_subcategories() works very similar to his category brother, but because it uses 1:N with categories, we can simply use s.category = c to link subcategory to category. The s.save_screenshot_file line saves the subcategory screenshot by loading it first and setting the name that is the same as subcategory url name. In this example you may not see it, but s.save() is not really necessary! Django saves new object automatically with save_screenshot_file() call, which seems strange but is reasonable. Writing file in file system when object is not saved and may never be, makes no sense. You must remember about it because you get save error if required fields won't be set.
The last function, populate_games() is the most complicated of the three but only because it has more data to save. The general idea stays the same. Please also look that we are setting different fields for external games (url) and different for Flash and Shockwave games (file, width, height). Notice that this time I'm saving game object before starting to save files for them and assigning to subcategories.
The very last part of file just starts the whole process if we run the module as the main script.
After running the script you may log into admin panel and see the new data. Next tutorial part will be about CSS and HTML for our simple game portal.
0 komentarze:
Post a Comment