Django是一个全面的Python Web开发框架,具有丰富的功能,和众多开箱即用的接口。
简单使用
我们使用Django的django-admin工具创建项目:
Python
django-admin startproject project1
cd project1
django-admin startapp app1
以后,一个简单的Web项目框架就搭建起来了。
在project1目录(即app1的上层目录)中,有一个manage.py,可以实现大量的管理功能。
如使用python manage.py runserver
,即可以启动一个支持热加载的Web服务,可以实时看到开发效果。
这之后,如果我们需要开发一些基本功能,只需要在app1目录中做一些定制。
如:在models.py中,重载models.Model,可以实现模型的定义;
在views.py中,实现一些视图层的任务。
在urls.py中定义urlpatterns列表,实现Url路由的管理。
manage.py的子命令
manage.py的runserver子命令,支持再增加一个地址与端口,表示让测试Web运行在什么地址上。
如:python manage.py runserver 192.168.1.1:8088
,则会运行在192.168.1.1的8088端口上。
manage.py支持的子命令非常丰富:
Shell
python manage.py --help
Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[auth]
changepassword
createsuperuser
[contenttypes]
remove_stale_contenttypes
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
optimizemigration
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
[sessions]
clearsessions
[staticfiles]
collectstatic
findstatic
runserver
只简单记录几个:
- creatsuperuser - 初始化超级管理员,当使用runserver启动之后,可以登录进入后台管理。
- migrate - 初始化数据库。如果有使用了数据库的模型,这个命令将创建相应的数据表结构。
- collectstatic - 收集静态文件。如果配置使用了静态资源,这个命令将把各个应用的静态资源复制到一起。
manage.py定制命令
如果我们需要实现一些自己的命令,可以在相应的项目配置目录中(对应上文创建的项目配置目录,就是project1/project1),新建一个management/commands目录,在这个目录中实现命令就行了。
实现的方法是:派生django.core.management.base import BaseCommand类,重载它的handle方法。
如:
Python
from django.conf import settings
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "test user list in settings.py"
def add_arguments(self, parser):
pass
def handle(self, *args, **options):
user_list = settings.USER_LIST
if len(user_list) == 0:
print("USER_LIST is empty !!!")
这个文件命名为test_user.py,回到project1目录,就可以调用:
python manage.py test_user
了。
自定义manage.py的子命令,可以实现一些非运行期的初始化操作。
但是,怎样在运行期间执行一些初始化操作呢?
使用AppConfig的ready()方法
在应用目录中,有一个apps.py,它的内容大致如下:
Python
from django.apps import AppConfig
class DemoConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'demo'
这个类会在Django执行django.setup()
的时候,执行它的ready()
方法。
所以,我们可以重载这个类的ready()
方法,加一些自己的代码:
Python
from . import Action
class DemoConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'demo'
def __init__(self, app_name, app_module):
super().__init__(app_name, app_module)
self.action = Action()
def ready(self):
self.action.run()
需要注意的是,这种方法在使用manage.py runserver
执行的时候,会被执行两次
在urls.py中执行初始化任务
因为Django在处理浏览器的请求之前,需要加载应用内的urls.py
,取得里面的urlpatterns列表,设定路由。所以,可以把要执行的代码放入urls.py
中。
使用这种方法,简单方便,而且因为urls.py
文件不是在django.setup()中被加载的,所以没有使用AppConfig的ready()
方法的两次执行问题。
但是,使用url.py来做初始化也有弊端。因为url.py在我们加载路由的时候触发,所以我们调用manage.py执行非runserver子命令的时候,url.py里的代码也会执行。
当然这种需求很容易解决,在urls.py里面,判断sys.argv的变量是否是manage.py与runserver就行。
使用Admin
django.contrib里面,包含很多可以直接使用的应用,最典型的就是admin:一个开箱即用的后台管理界面。
使用admin应用只需要三步:
- settings.py中包含django.contrib.admin应用:
Python
INSTALLED_APPS = [
'django.contrib.admin',
# 省略部分
]
- 执行manage.py的createsuperuser子命令:
Shell
python manage.py createsuperuser
- 在浏览器中访问
/admin
扩展Admin
默认地,Admin只能管理用户、组以及权限相关的模型。对于我们自己实现的模型,就需要注册之后才能使用。
假设我们实现了一个Service类:
Python
from django.db import models
class Service(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
key = models.CharField(max_length=255)
url = models.CharField(max_length=1024)
在admin.py中,需要这样注册:
Python
from django.contrib import admin
@admin.register(Service)
class ServiceAdmin(admin.ModelAdmin):
list_display = ('name', 'key', 'url', 'is_active')
之后,访问/admin
的时候,就会看到Service模型了,可以添加、更改、删除。
admin.ModelAdmin支持很多属性,用于定制管理页面。
除了上面列出的list_display,用于控制在管理页面按列表显示的列以外,还有list_display_links
、list_filter
、list_select_related
、list_editable
等等。
另外,如果想让模型的权限被灵活控制,还可以重载admin.ModelAdmin的has_add_permission、has_change_permission以及has_delete_permission。
比如以下代码,就定义了一个只能删除的模型:
class DeleteOnlyAdmin(admin.ModelAdmin):
def has_add_permission(self, request):
return False
def has_change_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return True