<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何在Django中創(chuàng)建自定義命令?

          共 6722字,需瀏覽 14分鐘

           ·

          2021-05-09 20:13

          在開(kāi)發(fā)Django項(xiàng)目時(shí),有時(shí)候需要編寫(xiě)一次性腳本來(lái)自動(dòng)化特定任務(wù)。
          例如:
          1、清理錯(cuò)誤的數(shù)據(jù)列
          2、導(dǎo)入初始數(shù)據(jù)庫(kù)數(shù)據(jù)
          我們可以通過(guò)兩種方式在django中運(yùn)行這些類(lèi)型的命令。第一是編寫(xiě)一個(gè)普通的python腳本,然后可以通過(guò)運(yùn)行python file_name.py來(lái)調(diào)用它,而另一個(gè)方法是使用django-admin命令。這些是通過(guò)調(diào)用python manage.py command_name運(yùn)行的。

          對(duì)于這篇文章,我將通過(guò)一個(gè)博客應(yīng)用程序進(jìn)行演示,該應(yīng)用程序只有3個(gè)數(shù)據(jù)庫(kù)表:User,Category和Post。

          普通的python腳本方法
          對(duì)于第一個(gè)示例,我們將嘗試使用以下腳本列出所有系統(tǒng)用戶(hù):
          from django.contrib.auth import get_user_model
          User = get_user_model()
          # retrieve all usersusers = User.objects.all()
          # loop through all usersfor user in users: print(f'user is {user.get_full_name()} and their username is {user.get_username()}')
          可以命名腳本list_users.py并通過(guò)python list_users.py運(yùn)行它,但運(yùn)行的時(shí)候會(huì)遇到如下錯(cuò)誤:
          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
          可能有人會(huì)假設(shè),如果腳本位于django的項(xiàng)目目錄中,腳本可以正常運(yùn)行。然而,這種情況也不對(duì)。這是因?yàn)槟_本不知道該腳本將應(yīng)用于哪個(gè)項(xiàng)目。因?yàn)槲覀兛赡茉谝慌_(tái)計(jì)算機(jī)或虛擬環(huán)境中有多個(gè)項(xiàng)目。因此,給腳本一些上下文信息很重要。

          我們將通過(guò)稍微修改腳本來(lái)做到這一點(diǎn)。
          import os
          os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'projectname.settings')
          import djangodjango.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()}')
          在這里,我們指定項(xiàng)目的設(shè)置,不僅如此,還可以調(diào)用django.setup()方法。該方法配置設(shè)置,記錄日志并填充應(yīng)用程序注冊(cè)表。總之,我們要使腳本知道我們的項(xiàng)目上下文。

          請(qǐng)注意,導(dǎo)入順序很重要,不要調(diào)整,這里有坑。

          如果再次運(yùn)行腳本,則所有用戶(hù)都會(huì)正常打印到終端,沒(méi)有報(bào)錯(cuò)了。

          接下來(lái),我們將通過(guò)運(yùn)行django-admin startapp posts來(lái)創(chuàng)建一個(gè)名為posts的app應(yīng)用。

          該應(yīng)用程序?qū)覀兊牟┛臀恼履P?/span>
          from django.db import modelsfrom 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 categoryclass Category(CommonInfo): name = models.CharField(max_length=255)
          def __str__(self):return self.name
          # blog post instanceclass 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()}'
          對(duì)于此示例,我們將從命令行創(chuàng)建博客帖子的實(shí)例。腳本名為create_post.py
          import osos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'commands.settings')
          import djangodjango.setup()
          from django.contrib.auth import get_user_modelfrom 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()
          在這里,我們正在創(chuàng)建博客帖子的實(shí)例。請(qǐng)注意我們要如何處理ForeignKey關(guān)系?其實(shí)就是確保將相關(guān)數(shù)據(jù)庫(kù)表的對(duì)象實(shí)例分配給該字段。

          通過(guò)運(yùn)行python create_post.py,然后提示我們進(jìn)行一些輸入。

          編寫(xiě)自定義django管理命令方法
          文章剛看開(kāi)始也提到了,django-admin命令是通過(guò)運(yùn)行python manage.py command_name來(lái)執(zhí)行的,我們平時(shí)用的有runserver,migrate和collectstatic。如果要獲取可用命令的列表,可以運(yùn)行python manage.py help。這將顯示可用命令以及它們所在的django app文件夾的列表。

          要注冊(cè)自定義管理命令,需要在django應(yīng)用程序文件夾中添加一個(gè)management \ commands目錄。在我們的例子中,它將位于posts \ management \ commands中。

          設(shè)置完成后,我們便可以在命令文件夾中初始化自定義腳本。對(duì)于第一個(gè)示例,我們將編寫(xiě)一個(gè)命令,將之前創(chuàng)建的博客文章標(biāo)記為已發(fā)布。

          請(qǐng)創(chuàng)建一個(gè)文件并將其命名為publish_post.py
          from django.core.management.base import BaseCommand, CommandErrorfrom posts.models import Category, Post
          class Command(BaseCommand): help = 'Marks the specified blog post as published.'
          # allows for command line argsdef 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'))
          Django管理命令由一個(gè)名為Command的類(lèi)組成,該類(lèi)繼承自BaseCommand。

          為了接收參數(shù),該類(lèi)利用argparse。方法add_arguments允許我們的函數(shù)接收參數(shù)。

          在我們的例子中,該函數(shù)期望一個(gè)參數(shù),該參數(shù)將被分配鍵post_id

          然后,handle()函數(shù)評(píng)估輸入并執(zhí)行我們的邏輯。

          在上面的示例中,期望的參數(shù)類(lèi)型稱(chēng)為位置參數(shù),必須提供該參數(shù)才能運(yùn)行該函數(shù)。為此,我們運(yùn)行python manage.py publish_post 1(或任何發(fā)布主鍵)

          顧名思義,可以將另一種類(lèi)型的參數(shù)稱(chēng)為可選參數(shù)應(yīng)用于方法,缺少這些參數(shù)不會(huì)影響函數(shù)的執(zhí)行。

          下面提供了一個(gè)示例。我們將初始化一個(gè)文件并將其命名為edit_post.py。代碼如下:
          from django.core.management.base import BaseCommand, CommandErrorfrom 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.'))
          在這里,我們只是在編輯博客文章標(biāo)題或內(nèi)容。所以我們可以運(yùn)行python manage.py edit_post 2 -t“ new title”僅編輯標(biāo)題

          或python manage.py edit_post -c
          “new content ”僅編輯內(nèi)容。如果我們希望通過(guò)`python manage.py edit_post 2 -t “new title again” -c “new title again”編輯標(biāo)題和內(nèi)容,則可以提供兩個(gè)參數(shù)。
          文章轉(zhuǎn)載:Python運(yùn)維技術(shù)

          (版權(quán)歸原作者所有,侵刪)

          點(diǎn)擊下方“閱讀原文”查看更多

          瀏覽 64
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  影音先锋色一区二区 | 啪啪视频官网 | 国产a毛片 | 黑人大屌轮奸视频播放免费成人 | 丁香五月天在线视频 |