创办一个简单的基于MVC的Django项目
在创建一个最简单的Django项目中,我们已经创建了一个项目的骨架,并能够正常访问,在这基础上,我们再接着来创建一个基于MVC的Django项目。
执行以下命令来创建一个entries模块:
python manage.py startapp entries
至此,blogs项目中,包括以下部分:
其中,blogs目录包括以下几项:
entries目录包括以下几项:
接下来,我们需要两个模型,分别对应Category表和Entry表,用来存储博客分类以及博客,每篇博客都会有一个外键标记所属的分类。下面打开entries目录下的models.py文件,按照以下代码进行模型的定义:
from django.db import models from django.contrib import admin import datetime # Create your models here. class Category(models.Model): name = models.CharField(max_length=50, unique=True) def __unicode__(self): return self.name class Meta: ordering = ['name'] class Admin: pass class Entry(models.Model): title = models.CharField(max_length=50) created_at = models.DateTimeField(default=datetime.datetime.now) published = models.BooleanField(default=False) category = models.ForeignKey(Category) def __unicode__(self): return self.title class Meta: ordering = ['-created_at', 'title'] # 符号-表示按照日期倒序排列 class Admin: pass admin.site.register(Category) admin.site.register(Entry)
在类Admin的设置中,允许Django针对当前的Models模型自动生成Django超级用户的后台管理入口。
接下来的工作就是让Django部署并在数据库中生成已经写好的Models模型。
在Django中,与工程全局相关的设置都需要在配置文件settings.py中添加。下面打开blogs目录下的settings.py文件,修改数据库配置如下:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 'NAME': 'blogs', # Or path to database file if using sqlite3. 'USER': 'root', # Not used with sqlite3. 'PASSWORD': '', # Not used with sqlite3. 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 'PORT': '', # Set to empty string for default. Not used with sqlite3. } }
这里要注意的是,如果使用SQLite数据库,Django可以根据数据库的名称自动在SQLite中创建新的数据库,而在MySQL、PostgreSQL或其他的数据库中,则需要先创建与设定名称对应的数据库。在使用MySQL数据库时,需要额外安装MySQL的Python链接库MySQLdb,这个模块可以在http://sourceforge.net/projects/mysql-python/进行下载。
安装MySQLdb的时候,如果遇到下面的错误:
Eric-MacBook-Pro:MySQL-python-1.2.4b4 jsntghf$ sudo python setup.py install sh: mysql_config: command not found Traceback (most recent call last): File "setup.py", line 18, in <module> metadata, options = get_config() File "/Users/jsntghf/Downloads/MySQL-python-1.2.4b4/setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "/Users/jsntghf/Downloads/MySQL-python-1.2.4b4/setup_posix.py", line 25, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found
执行以下命令即可:
sudo ln -s /usr/local/mysql/bin/mysql_config /usr/local/bin/mysql_config
为了使Django识别开发者添加的应用模块,在settings.py文件的INSTALLED_APPS部分中,需要定义Django工程加载的应用列表。默认情况下,列表中已经添加了Django工程运行所需的部分自带模块,我们还需要把刚才编写好的应用模块entries加入其中,同时添加Django自带的django.contrib.admin应用模块:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', # Uncomment the next line to enable the admin: 'django.contrib.admin', 'entries', # Uncomment the next line to enable admin documentation: # 'django.contrib.admindocs', )
添加admin模块后还不能立即使用Django的admin后台管理界面,需要打开blogs目录下的urls.py文件,进行如下修改:
from django.conf.urls import patterns, include, url # Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', 'blogs.views.home', name='home'), # url(r'^blogs/', include('blogs.foo.urls')), # Uncomment the admin/doc line below to enable admin documentation: # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), # Uncomment the next line to enable the admin: url(r'^admin/', include(admin.site.urls)), )
这样访问admin模块时,Django就可以顺利解析访问地址,并转向后台管理界面。
接下来就可以执行python manage.py syncdb指令了。Django会根据模型的定义自动完成ORM的数据库映射工作,屏蔽了底层数据库细节和SQL查询的编写。执行完后,Django已经根据我们刚才在models里定义的映射文件,自动在数据库里创建好对应的表和字段。命令执行的同时会提示用户创建superuser账户,用来登录Django自动创建好的后台管理界面对模型进行管理。
执行python manage.py syncdb的时候,如果遇到下面的错误:
Eric-MacBook-Pro:blogs jsntghf$ sudo python manage.py syncdb Traceback (most recent call last): File "manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "/Library/Python/2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line utility.execute() File "/Library/Python/2.7/site-packages/django/core/management/__init__.py", line 382, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/Library/Python/2.7/site-packages/django/core/management/__init__.py", line 261, in fetch_command klass = load_command_class(app_name, subcommand) File "/Library/Python/2.7/site-packages/django/core/management/__init__.py", line 69, in load_command_class module = import_module('%s.management.commands.%s' % (app_name, name)) File "/Library/Python/2.7/site-packages/django/utils/importlib.py", line 35, in import_module __import__(name) File "/Library/Python/2.7/site-packages/django/core/management/commands/syncdb.py", line 8, in <module> from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal File "/Library/Python/2.7/site-packages/django/core/management/sql.py", line 6, in <module> from django.db import models File "/Library/Python/2.7/site-packages/django/db/__init__.py", line 40, in <module> backend = load_backend(connection.settings_dict['ENGINE']) File "/Library/Python/2.7/site-packages/django/db/__init__.py", line 34, in __getattr__ return getattr(connections[DEFAULT_DB_ALIAS], item) File "/Library/Python/2.7/site-packages/django/db/utils.py", line 92, in __getitem__ backend = load_backend(db['ENGINE']) File "/Library/Python/2.7/site-packages/django/db/utils.py", line 24, in load_backend return import_module('.base', backend_name) File "/Library/Python/2.7/site-packages/django/utils/importlib.py", line 35, in import_module __import__(name) File "/Library/Python/2.7/site-packages/django/db/backends/mysql/base.py", line 16, in <module> raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e) django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: dlopen(/Library/Python/2.7/site-packages/MySQL_python-1.2.4b4-py2.7-macosx-10.7-intel.egg/_mysql.so, 2): Library not loaded: libmysqlclient.18.dylib Referenced from: /Library/Python/2.7/site-packages/MySQL_python-1.2.4b4-py2.7-macosx-10.7-intel.egg/_mysql.so Reason: image not found
执行以下命令即可:
sudo ln -s /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/lib/
使用命令python manage.py runserver来启动Django自带的Web服务器后,在浏览器中访问地址http://localhost:8000/admin/,使用刚才创建的superuser用户的账号和密码登录,漂亮的Django后台管理界面就出现在眼前。
如果想显示成中文界面,修改settings.py中的以下设置即可:
LANGUAGE_CODE = 'zh-cn'
至此,模型层已经完成,接下来要实现的就是控制层以及视图层了。
修改views.py,代码如下:
# Create your views here. from django.shortcuts import render_to_response from entries.models import Category def categories_report(request): listing = [] for category_list in Category.objects.all(): category_dict = {} category_dict['item_object'] = category_list category_dict['item_count'] = category_list.entry_set.count() category_dict['item_name'] = category_list.name category_dict['item_published'] = category_list.entry_set.filter(published=True).count() category_dict['percent_published'] = int(float(category_dict['item_published']) / category_dict['item_count'] * 100) listing.append(category_dict) return render_to_response('categories.html', { 'listing': listing })
Category.objects.all方法返回categories列表中所有的记录项,Django可以根据后台数据库转换成相应的SQL语句,在后台数据库中执行并返回查询结果。
每一个category都有entry_set属性,代表categories中的每一个entry项。如果需要设置查询条件,也可以使用entry_set.filter方法来返回符合特定要求的entry项。
render_to_response函数返回浏览器指定的HTML页面,页面为Django的Template模板,负责展示被请求的页面内容。
接下来就是要创建categories.html这个模板文件了。首先,在entries目录创建一个templates文件夹,然后,在这个模板目录里创建所需的categories.html模板文件:
<html> <head> <meta http-equiv="Content-Type" content="text/html" /> <title>统计列表</title> </head> <body> <h1>统计列表</h1> {% for category_dict in listing %} <ul> <li>分类: {{ category_dict.item_name }}</li> <li>数目: {{ category_dict.item_count }}</li> <li>已发布的数目: {{ category_dict.item_published }} ({{ category_dict.percent_published }}%)</li> </ul> {% endfor %} </body> </html>
接下来要做的就是告诉Django模板的位置, 修改settings.py中的TEMPLATE_DIRS项:
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. './entries/templates', )
接下来就是修改urls.py,在最后加上以下这句:
url(r'^report/$', 'entries.views.categories_report'),
现在,访问http://localhost:8000/report/即可看到列表了。