在创建一个最简单的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/即可看到列表了。