Some interesting Django related links:
Installation of Python Image Library (PIL)
It will be a problems with PIL installation on Windows 7 64 bit, so you will need to install library from source code:
cd c:\PIL python setup.py install
This will install library, but without support for TKINTER, JPEG, ZLIB (PNG/ZIP) and FREETYPE2 (i.e. actually without anything )
So let’s add support for at least JPEG and PNG. To do this, you will need to download following libraries:
Following blog posts will help you to continue with installation:
Notes:
include <unistd.h>
from some *.h source files as this needed to be included only on Unix (ok, at least not on Windows) For example you will need to delete such line from zconf.h in zlib sources before try to run nmake for zlib.
ZLIB_ROOT = './zlib'
OK, in Part #1 we already figure out what Models we need to create. Because Django support concept of “applications” inside one project, we can actually start creating models for 3 applications:
Django internally support following concepts that will be used in Accounts application:
cd c:\evejob\EvejobDJ python manage.py startapp accounts
The same way, you can create now “common” and “companies” applications in EvejobDJ project.
Let’s take a look into possible simple “accounts” application model.py file:
from django.db import models from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ class UserProfile(models.Model): # required field - user that own profile user = models.ForeignKey(User, unique=True) # optional Job Title job_title = models.CharField(_("Job Title"), max_length=128, null = True, blank = True) # optional Phone Number phone = models.CharField(_("Phone"), max_length=16, null = True, blank = True) # Boolean stored as tinyint in MySQL database, but it's ok for now allow_site_to_contact_by_email = models.BooleanField(_("Allow site to contact me by email")) allow_site_partners_to_contact_by_email = models.BooleanField(_("Allow site partners to contact me by email")) allow_site_to_contact_by_phone = models.BooleanField(_("Allow site to contact me by phone")) allow_site_partners_to_contact_by_phone = models.BooleanField(_("Allow site partners to contact me by phone")) def __unicode__(self): return self.user.username
Let’s review now most important aspects of this code:
from django.contrib.auth.models import User
Line above import already defined in Django User Model. We not going to create our own User Model and will try to reuse as much as possible from what is available in Django framework. But because we need to hold additional user details (like job title or phone for example), we create “UserProfile” model, that reference User as Foreign Key:
# required field - user that own profile user = models.ForeignKey(User, unique=True)
Also we are going to use “Internationalization” (I18N) build in into Django functionality to made our site available in few languages:
from django.utils.translation import ugettext_lazy as _
After such import, to translate string from one language into another we need just use _(”String to translate”) pattern (sure and also define translations some way – more about it in dedicated article)
Other code just define different fields of UserProfile that we want actually to store in Database (some of them are strings, some booleans).
Last two lines used to get a “string” representation of the model that will be used in Django Admin for example (same idea like you can “override ToString()” in C#):
def __unicode__(self): return self.user
That’s it for accounts application regarding models!
For “common” application we will have to define two model classes (City and Country):
from django.db import models from django.contrib.auth.models import User import EvejobDJ.settings as settings from django.utils.translation import ugettext_lazy as _ class Country(models.Model): # required Unique Company Name name = models.CharField(_("Name"), max_length=255, unique = True) def __unicode__(self): return '%s' % (self.name) class Meta: verbose_name = _('Country') verbose_name_plural = _('Countries') class City(models.Model): # required Unique Company Name name = models.CharField(_("Name"), max_length=255, unique = True) country = models.ForeignKey(Country, unique = False) def __unicode__(self): return '%s' % (self.name) class Meta: verbose_name = _('City') verbose_name_plural = _('Cities')
Exactly same logic like for Profiles, with small addition to made correct “plural” name for entity using definitions for “verbose_name_plural” field on Meta class. This will allow to see “Cities” or “Countries” in Admin, instead of automatic “Citys” or “Countrys”
class Meta: verbose_name = _('City') verbose_name_plural = _('Cities')
And last models that we need to produce in Sprint #1 is for Companies – Company and CompanyLogo. Let’s review following code:
from django.db import models from django.contrib.auth.models import User import EvejobDJ.settings as settings from django.utils.translation import ugettext_lazy as _ class Company(models.Model): # required Unique Company Name name = models.CharField(_("Name"), max_length=255, unique = True) # user that create this company first time. creation_by = models.ForeignKey(User, unique = False) # when user create this company first time. Django Automatically set the field to now when Company created for the first time creation_date = models.DateTimeField(_("Create Date"), auto_now_add = True) city = models.ForeignKey('common.City', unique = False, null = True, blank = True) country = models.ForeignKey('common.Country', unique = False, null = True, blank = True) # logo = models.OneToOneField('CompanyLogo', related_name='logo', verbose_name = "company logo") # But this is not needed, as you always can get access to logo using something like # (read more http://docs.djangoproject.com/en/dev/topics/db/queries/#one-to-one-relationships) # e = Company.objects.get(id=2) # e.companylogo def __unicode__(self): return '%s' % (self.name) class Meta: verbose_name = _('Company') verbose_name_plural = _('Companies') class CompanyLogo(models.Model): company = models.OneToOneField(Company, primary_key=True) # user that create this logo first time. creation_by = models.ForeignKey(User, unique = False) # when user create this logo first time. Django Automatically set the field to now when logo created for the first time creation_date = models.DateTimeField(_("Create Date"), auto_now_add = True) caption = models.CharField(blank=True, null = True, max_length=100) image = models.ImageField(upload_to=settings.COMPANY_LOGO_RELATIVE_ROOT) def __unicode__(self): return '%s' % (self.company.name) class Meta: verbose_name = _('Company Logo') verbose_name_plural = _('Companies Logos')
Let’s take a look into some interesting things here… First of all, we will store currently company logo images in file system (but later we can use another storage provider). Thanks to Django, it have special field type for this: “ImageField”. Ones we add field with this type, we need to make sure that we install PIL library. You can read about some installation issues of it on dedicated post). Second take a look into “auto_now_add” parameter in creation_date field – this will instruct Django to automatically set the field to current date when user create new company logo! And last most important thing in this models is One To One relation (using models.OneToOneField) between CompanyLogo and Company entities! You can read more information about Django support of “One To One” relations” if you interesting in details.
That’s all regarding Models itself. Let me know if have any questions!
Notes: To run code that you see above (at least to be able to create database using ‘python manage.py syncdb’ command), you need to made some settings in settings.py file. At minimum you need to add “accounts”, “companies” and “common” into Django Applications list:
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.flatpages', 'common', 'accounts', 'companies', )
Also you probably need to define some settings like COMPANY_LOGO_RELATIVE_ROOT in same settings.py file. In any case, I recommend to wait a little and read next post to get more information how to actually run EvejobDJ models and create views! So keep reading!
P.S. And last thing: I want to let you know that Python is NOT my “primary language of choice”. Means that I DON’T do everyday coding on it (instead of C# for example), so if you see (and feel) that I do something wrong, or that it can be done in Python better please let me know!