自定义Django管理命令
Django中的Manage.py是一个命令行工具,其工作原理类似于django-admin命令。不同的是,它指向项目的settings.py文件。这个manage.py工具提供了你在使用Django时必须具备的各种命令。一些最常用的命令是:
- python manage.py startapp
- python manage.py makemigrations
- python manage.py migrate
- python manage.py runserver
有趣的是,我们可以创建我们自己的自定义管理命令来满足各种各样的要求,从使用命令行与我们的应用程序互动到作为执行Cron作业的接口。我们将创建一个自定义管理命令,为我们提供某一天发表的新文章和这些文章的评论的统计数据或指标。
开始
按照Django介绍和安装来设置一个虚拟环境并安装Django
第1步:通过以下命令初始化**** 一个项目
django-admin startproject geeks_site
第2步:创建一个名为博客的应用程序
python manage.py startapp blog
第3步:将你的应用程序添加到settings.py中。
In geeks_site/settings.py
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
]
第四步:在blog*应用程序中创建名为Article和Comment**的模型。
模型文章 :
- Fields :
- 标题:存储文章的标题
- 正文:该文章的内容
- created_on : 创建该文章的日期和时间
模型评论 :
- Fields :
- 文章。创建评论的文章
- 文本:实际评论
- created_on : 创建该文章的日期和时间
In blog/models.py
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE)
text = models.CharField(max_length=200)
created_on = models.DateTimeField(auto_now_add=True)
第5步:在blog/admin.py中注册你的模型,这样它就会在管理面板中显示出来。
In blog/admin.py
from django.contrib import admin
from .models import Article, Comment
admin.site.register(Article)
admin.site.register(Comment)
第6步:现在,为了迁移所有的修改并启动服务器,在终端运行以下命令
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
创建一个超级用户账户来登录管理面板
python manage.py createsuperuser
现在,访问管理面板,http://127.0.0.1:8000/admin/
创建一些文章,然后是一些评论。
现在,让我们开始创建自定义Django管理命令。
- 在博客应用中添加一个管理/命令目录
- 将
__init__.py
添加到blog/management,将__init__.py
+ stats.py文件添加到blog/management/commands目录。
注意: Django将为该目录中名称不以下划线开头的每个Python模块注册一个manage.py命令。
博客应用程序的文件夹结构看起来像这样。
我们将使用python manage.py统计表来运行我们的自定义管理命令。现在我们将配置这个命令到底要做什么。
In stats.py
from django.core.management.base import BaseCommand
from django.db.models import Count
from blog.models import Article, Comment
from datetime import timedelta, datetime
from django.utils.timezone import utc
def now():
return datetime.utcnow().replace(tzinfo=utc)
class Command(BaseCommand):
help = 'Displays stats related to Article and Comment models'
def handle(self, *args, **kwargs):
From = now() - timedelta(hours=5)
To = now()
articles_published_in_last_5_hour = Article.objects.filter(
created_on__gt=From, created_on__lte=To).count()
comments_published_per_article = Comment.objects.filter(
created_on__gt=From, created_on__lte=To).values(
'article').annotate(count=Count('article')).order_by()
print("Articles Published in last 5 hours = ",
articles_published_in_last_5_hour)
print("Comments per Article in last 5 hours")
for data in comments_published_per_article:
print(data)
了解 stats.py 文件。
基本上,Django管理命令是由一个名为Command的类构建的,该类继承于BaseCommand。
1)帮助:它告诉人们该命令的实际作用。运行下面的命令,可以看到帮助信息
python manage.py stats --help
2) handle():它处理所有在执行命令时需要执行的逻辑。让我们了解一下handle()方法中的代码
- 在这里,我们关注的是以下两个统计数字
- 过去5小时内发表的文章数量
- 每篇文章在过去5小时内创建的评论数量
- 从。当前时间 – 5小时
- 到。当前时间
- articles_published_in_last_5_hour : 一个整数值
- comments_published_per_article : queryset对象或一个字典的列表
- 打印语句,在终端输出数据
现在,在你的终端运行以下命令。
python manage.py stats
输出 :
自定义参数
Django使用argparse模块来处理自定义参数。我们需要在命令类下定义一个函数add_arguments来处理参数。
from django.core.management.base import BaseCommand
from django.db.models import Count
from app.models import Article, Comment
from datetime import timedelta, datetime
from django.utils.timezone import utc
def now():
return datetime.utcnow().replace(tzinfo=utc)
class Command(BaseCommand):
help = 'Displays stats related to Article and Comment models'
def add_arguments(self, parser):
parser.add_argument('-t', '--time', type=int, help='Articles published in last t hours')
def handle(self, *args, **kwargs):
t = kwargs['time']
if not t:
t=5
From = now() - timedelta(hours=t)
To = now()
articles_published_in_last_t_hour = Article.objects.filter(
created_on__gt=From, created_on__lte=To).count()
comments_published_per_article = Comment.objects.filter(
created_on__gt=From, created_on__lte=To).values(
'article').annotate(count=Count('article')).order_by()
print(f"Articles Published in last {t} hours = ",
articles_published_in_last_t_hour)
print(f"Comments per Article in last {t} hours")
for data in comments_published_per_article:
print(data)
输出: