如何在Django中创建自定义命令?
马哥Linux运维
共 6722字,需浏览 14分钟
· 2021-05-09
例如:
1、清理错误的数据列
2、导入初始数据库数据
我们可以通过两种方式在django中运行这些类型的命令。第一是编写一个普通的python脚本,然后可以通过运行python file_name.py来调用它,而另一个方法是使用django-admin命令。这些是通过调用python manage.py command_name运行的。
对于这篇文章,我将通过一个博客应用程序进行演示,该应用程序只有3个数据库表:User,Category和Post。
对于第一个示例,我们将尝试使用以下脚本列出所有系统用户:
from django.contrib.auth import get_user_model
User = get_user_model()
# retrieve all users
users = User.objects.all()
# loop through all users
for user in users:
print(f'user is {user.get_full_name()} and their username is {user.get_username()}')
django.core.exceptions.ImproperlyConfigured: Requested setting AUTH_USER_MODEL, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings
我们将通过稍微修改脚本来做到这一点。
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'projectname.settings')
import django
django.setup()
from django.contrib.auth import get_user_model
User = get_user_model()
users = User.objects.all()
for user in users:
print(f'user is {user.get_full_name()} and their username is {user.get_username()}')
请注意,导入顺序很重要,不要调整,这里有坑。
如果再次运行脚本,则所有用户都会正常打印到终端,没有报错了。
接下来,我们将通过运行django-admin startapp posts来创建一个名为posts的app应用。
该应用程序将包含我们的博客文章模型
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
# Create your models here.
class CommonInfo(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
ordering = ('-created_at',)
# blog post category
class Category(CommonInfo):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
# blog post instance
class Post(CommonInfo):
title = models.CharField(max_length=255)
category = models.ForeignKey(Category,related_name='posts',on_delete=models.PROTECT)
author = models.ForeignKey(User,related_name='posts',on_delete=models.PROTECT)
content = models.TextField()
published = models.BooleanField(default=False)
def __str__(self):
return f'{self.title} by {self.author.get_full_name()}'
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'commands.settings')
import django
django.setup()
from django.contrib.auth import get_user_model
from posts.models import Category, Post
User = get_user_model()
def select_category():
# retrieve categories. (You can create some examples from the django admin)
categories = Category.objects.all().order_by('created_at')
print('Please select a category for your post: ')
for category in categories:
print(f'{category.id}: {category}')
category_id = input()
category = Category.objects.get(id=category_id)
return category
def select_author():
# retrieve all users
users = User.objects.all()
print('Please select an author for your post: ')
for user in users:
print(f'{user.id}: {user}')
user_id = input()
user = User.objects.get(id=user_id)
return user
def create_post():
title = input("Title of your post: ")
content = input("Long post content: ")
category = select_category()
author = select_author()
Post(**locals()).save()
print('Post created successfully!')
if __name__ == "__main__":
create_post()
通过运行python create_post.py,然后提示我们进行一些输入。
编写自定义django管理命令方法
文章刚看开始也提到了,django-admin命令是通过运行python manage.py command_name来执行的,我们平时用的有runserver,migrate和collectstatic。如果要获取可用命令的列表,可以运行python manage.py help。这将显示可用命令以及它们所在的django app文件夹的列表。
要注册自定义管理命令,需要在django应用程序文件夹中添加一个management \ commands目录。在我们的例子中,它将位于posts \ management \ commands中。
设置完成后,我们便可以在命令文件夹中初始化自定义脚本。对于第一个示例,我们将编写一个命令,将之前创建的博客文章标记为已发布。
请创建一个文件并将其命名为publish_post.py
from django.core.management.base import BaseCommand, CommandError
from posts.models import Category, Post
class Command(BaseCommand):
help = 'Marks the specified blog post as published.'
# allows for command line args
def add_arguments(self, parser):
parser.add_argument('post_id', type=int)
def handle(self, *args, **options):
try:
post = Post.objects.get(id=options['post_id'])
except Post.DoesNotExist:
raise CommandError(f'Post with id {options["post_id"]} does not exist')
if post.published:
self.stdout.write(self.style.ERROR(f'Post: {post.title} was already published'))
else:
post.published = True
post.save()
self.stdout.write(self.style.SUCCESS(f'Post: {post.title} successfully published'))
为了接收参数,该类利用argparse。方法add_arguments允许我们的函数接收参数。
在我们的例子中,该函数期望一个参数,该参数将被分配键post_id
然后,handle()函数评估输入并执行我们的逻辑。
在上面的示例中,期望的参数类型称为位置参数,必须提供该参数才能运行该函数。为此,我们运行python manage.py publish_post 1(或任何发布主键)
顾名思义,可以将另一种类型的参数称为可选参数应用于方法,缺少这些参数不会影响函数的执行。
下面提供了一个示例。我们将初始化一个文件并将其命名为edit_post.py。代码如下:
from django.core.management.base import BaseCommand, CommandError
from posts.models import Category, Post
class Command(BaseCommand):
help = 'Edits the specified blog post.'
def add_arguments(self, parser):
parser.add_argument('post_id', type=int)
# optional arguments
parser.add_argument('-t', '--title',type=str, help='Indicate new name of the blog post.')
parser.add_argument('-c', '--content',type=str, help='Indicate new blog post content.')
def handle(self, *args, **options):
title = options['title']
content = options['content']
try:
post = Post.objects.get(id=options['post_id'])
except Post.DoesNotExist:
raise CommandError(f'Post with id {options["post_id"]} does not exist')
if title or content:
if title:
old_title = post.title
post.title = title
post.save()
self.stdout.write(self.style.SUCCESS(f'Post: {old_title} has been update with a new title, {post.title}'))
if content:
post.content = content
post.save()
self.stdout.write(self.style.SUCCESS('Post: has been update with new text content.'))
else:
self.stdout.write(self.style.NOTICE('Post content remains the same as no arguments were given.'))
或python manage.py edit_post -c “new content ”仅编辑内容。如果我们希望通过`python manage.py edit_post 2 -t “new title again” -c “new title again”编辑标题和内容,则可以提供两个参数。
(版权归原作者所有,侵删)
点击下方“阅读原文”查看更多
评论
一个神奇的 Linux命令——type
转自:科学随想录在Linux系统中,了解命令的类型、位置和完整路径对于系统管理和开发非常重要。type命令是一个强大而实用的工具,能够帮助我们查看给定命令的类型、位置和完整路径。在本文中,我们将深入探索type命令的用法和功能,并提供详细的代码示例和输出,以帮助读者全面了解该命令。第一部分:type
开源Linux
0
架构应该如何来理解?
来源:zhuanlan.zhihu.com/p/141027477👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接:htt
小哈学Java
0
Go早期是如何在Google内部发展起来的
2007年Go诞生于Google,2009年Google正式对外宣布了Go语言的开源!时至今日,距离Go开源已经过去了近15个年头了[1]!Go在Google公司内部究竟是怎样的一个状态呢?前Google员工Yves Junqueira近期撰文从其个人所见所闻谈了Go在Google的历程[2]!这里
GoCN
0
3人运营,不用投流,年翻十倍...这些头部商家如何在得物获得确定性新增长
是新朋友吗?记得先点蓝字关注我哦~这场硬仗一定要打,也一定要打赢。文/靳舒乔珠宝品牌周大生2022年一季报数据显示,2021年周大生营收91.55亿元,门店突破4500家,遂加快线上渠道布局。一次跟得物官方交流,感觉这款App上的年轻人非常活跃,很契合线上发展需求。那时,得物App更名一年有余,正打
调皮电商
2
分享几个前端中好玩且有用的开源工具,总有一个适合你!
点击上方 前端Q,关注公众号回复加群,加入前端Q技术交流群正所谓差生文具多,作为前端的我们,拥有几个合适的工具和网站可以很有效的提高我们的工具效率,还会有一些很有趣的网站可以在我们敲 bug 累了的时候供我们娱乐,接下来我就和大嘎分析一下我在用的一些工具和网站。聚合API该网站提供了大量的
前端Q
0
图解 transformer 中的自注意力机制
↓推荐关注↓本文将将介绍注意力的概念从何而来,它是如何工作的以及它的简单的实现。注意力机制在整个注意力过程中,模型会学习了三个权重:查询、键和值。查询、键和值的思想来源于信息检索系统。所以我们先理解数据库查询的思想。假设有一个数据库,里面有所有一些作家和他们的书籍信息。现在我想读一些Rabindra
Python学习与数据挖掘
0
C#中using的使用的几种场景
using在C#中随处可见,比如引入命名空间,这是也是每个C#的cs页面必须存在的,除了引入命名空间还有几种用法,下面将介绍这几种的使用。1、用于引入命名空间 这是最常见最基本的用法, 这样可以在程序中直
dotNET全栈开发
10
使用OpenCV测量图像中物体之间的距离
点击上方“小白学视觉”,选择加"星标"或“置顶”重磅干货,第一时间送达来源丨opcv学堂编辑丨极市平台极市导读 附详细代码操作。本文来自光头哥哥的博客【Measuring distance between objects in an image with OpenCV】,仅做学习分享。原文
小白学视觉
10