์ƒˆ์†Œ์‹

LANGUAGES/Django

[Django] Django ์ปค์Šคํ…€ ์ปค๋งจ๋“œ ๋งŒ๋“ค๊ธฐ

  • -

๐Ÿ“Œ Django๋กœ ์ปค์Šคํ…€ ์ปค๋งจ๋“œ ๋งŒ๋“ค๊ธฐ

์žฅ๊ณ  manage.py์— ์‚ฌ์šฉ์ž ์ง€์ • ์ปค๋งจ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.์ปค์Šคํ…€ ์ปค๋งจ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์œผ๋กœ manage.py๋ถ€ํ„ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ปค๋งจ๋“œ๋ฅผ ๋Š˜๋ฆด ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

์ง€๊ธˆ๋ถ€ํ„ฐ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ปค๋งจ๋“œ๋กœ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•˜์—ฌ ๋ณด์ž.

  • ์‚ฌ์šฉ์ž ์ง€์ • ์ปค๋งจ๋“œ ๊ฐœ์š”
  • ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ
  • ์ปค๋งจ๋“œ ์ž‘์„ฑ
  • ์ปค๋งจ๋“œ ์‹คํ–‰
  • ์ปค๋งจ๋“œ ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ

 

๐Ÿ“Œ ์‚ฌ์šฉ์ž ์ง€์ • ์ปค๋งจ๋“œ ๊ฐœ์š”

Django ์ปค์Šคํ…€ ์ปค๋งจ๋“œ๋Š” Django์—์„œ ์ƒ์„ฑํ•˜๋Š” ์•ฑ๋งˆ๋‹ค ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ปค์Šคํ…€ ํ•˜์—ฌ ๋งŒ๋“ค์–ด์ง„ ์ปค๋งจ๋“œ๋Š” manage.py์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‚ด๊ฐ€ showuser๋ผ๋Š” ์ปค๋งจ๋“œ๋ฅผ ๋งŒ๋“ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ๋œ๋‹ค.

python3 manage.py showuser

Django์—์„œ ๊ด€๋ฆฌ์šฉ์œผ๋กœ ๋ชจ๋ธ์„ ์กฐ์ž‘ํ•˜๊ฑฐ๋‚˜ ์ฐธ์กฐํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ, ๋ทฐ๋ฅผ ์ผ๋ถ€๋Ÿฌ ์ •์˜ํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €๋กœ ๋ถ€ํ„ฐ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ๋ฒˆ๊ฑฐ๋กญ๊ณ , ๊ท€์ฐฎ์€ ์ผ์ด๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ปค์Šคํ…€ ์ปค๋งจ๋“œ๋ฅผ ๋งŒ๋“ค๋ฉด ์ปค๋งจ๋“œ ๋ผ์ธ์—์„œ ๋ชจ๋ธ, ๋‚˜์•„๊ฐ€์„œ๋Š” ์ „์ฒด ํ”„๋กœ์ ํŠธ๋ฅผ ์ฐธ์กฐ ํ•  ์ˆ˜ ์žˆ์–ด ๋งค์šฐ ํŽธ๋ฆฌํ•ด์ง„๋‹ค.

 

๐Ÿ’ก ์ปค์Šคํ…€ ์ปค๋งจ๋“œ๋ฅผ ๋งŒ๋“œ๋Š” cron๋“ฑ์˜ ์Šค์ผ€์ค„๋Ÿฌ์™€ ์กฐํ•ฉํ•˜๋ฉด ์ •๊ธฐ์ ์œผ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์‹œ์Šคํ…œ๋„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค.

Django ์ปค์Šคํ…€ ์ปค๋งจ๋“œ๋Š” ์„ค์น˜ํ•œ ์•ฑ ํ•˜์œ„์— management๋ผ๋Š” ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ  ๊ทธ ์•„๋ž˜ commands๋ผ๋Š” ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ปค๋งจ๋“œ๋ช…์— ํ•ด๋‹นํ•˜๋Š” ๋ชจ๋“ˆ์„ ๋ฐฐ์น˜ํ•˜๊ณ , ๋ชจ๋“ˆ ์•ˆ์—์„œ ์ปค๋งจ๋“œ์˜ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์œผ๋กœ Django๊ฐ€ ๊ทธ ์ปค๋งจ๋“œ๋ฅผ ์ธ์‹ํ•œ๋‹ค.

โžค ๋ช…๋ น์–ด ์ƒ์„ฑ

  % python3 manage.py

  Type 'manage.py help <subcommand>' for help on a specific subcommand.

  Available subcommands:

  [auth]
      changepassword
      createsuperuser

  [contenttypes]
      remove_stale_contenttypes

  [debug_toolbar]
      debugsqlshell

  [django]
      check
      compilemessages
      createcachetable
      dbshell
      diffsettings
      dumpdata

์œ„์˜ manage.py๋กœ ์ปค๋งจ๋“œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ํ˜„์žฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ช…๋ น์–ด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.


์•„๋ž˜์™€ ๊ฐ™์ด management>commands>showuser.py ํŒŒ์ผ์„ ์ถ”๊ฐ€ ํ›„ ๋™์ผํ•œ ํด๋”์— __init__.pyํŒŒ์ผ์„ ์ƒ์„ฑ ํ›„ ๋‹ค์‹œ ํ•œ ๋ฒˆ manage.py ๋ช…๋ น์–ด๋ฅผ ํ™•์ธํ•˜์—ฌ ๋ณด์ž.

 

๋‚ด๊ฐ€ ์ƒ์„ฑํ•œ showuser๋ผ๋Š” ๋ช…๋ น์–ด๋ฅผ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

% python3 manage.py

Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:
...
[shortener]
    showuser
...

 

๐Ÿ“Œ ๋ชจ๋ธ ๋งŒ๋“ค๊ธฐ

์ปค์Šคํ…€ ์ปค๋งจ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ž„์˜์˜ ๋ชจ๋ธ์„ ์ƒ์„ฑํ•ด ๋ณด์ž.

models.py

class User(models.Model):
    ''' ์ปค์Šคํ…€ ์ปค๋งจ๋“œ๋ฅผ ์œ„ํ•œ ๋ชจ๋ธ ์ƒ์„ฑ '''
    name = models.CharField(max_length=128, help_text="์‚ฌ์šฉ์ž ์ด๋ฆ„")
    content = models.TextField(max_length=1024, help_text="์‚ฌ์šฉ์ž ์„ค๋ช…")

๋ชจ๋ธ์„ ์ •์˜ํ•œ ํ›„ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์ง„ํ–‰ํ•œ๋‹ค.

% python3 manage.py makemigrations
% python3 manage.py migrate

 

๐Ÿ“Œ ์ปค๋งจ๋“œ ์ž‘์„ฑ

์ปค๋งจ๋“œ๋กœ ์‹คํ–‰ํ•˜๋Š” showuser.pyํŒŒ์ผ ์•ˆ์— ๋ช…๋ น์–ด๋ฅผ ์ž‘์„ฑํ•˜์—ฌ๋ณด์ž.

management>commands>showuser.py

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = 'Show user list'

    def handle(self, *args, **options):
        self.stdout.write('show user')

๋‹ค์Œ๊ณผ ๊ฐ™์ด Command ๋ผ๊ณ  ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค.

 

์ด ํด๋ž˜์Šค๋Š” BaseCommand ๋ฅผ ์ƒ์†ํ•จ์œผ๋กœ์„œ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 

help ์†์„ฑ์— ์ปค๋งจ๋“œ์˜ ์„ค๋ช…์„ ์ž‘์„ฑํ•˜๋ฉด -h ์˜ต์…˜์‚ฌ์šฉ ์‹œ ๊ทธ์— ๋Œ€ํ•œ ์„ค๋ช…์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

handle() ๋ฉ”์†Œ๋“œ ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ(override)ํ•ด, ์ปค๋งจ๋“œ๊ฐ€ ์‹คํ–‰๋˜์—ˆ์„ ๋•Œ์˜ ์ฒ˜๋ฆฌ๋ฅผ ๊ธฐ์ž…ํ•˜๊ฒŒ ํ•œ๋‹ค.

 

๐Ÿ“Œ ์ปค๋งจ๋“œ ์‹คํ–‰

% python3 manage.py showuser
show user

% python3 manage.py showuser -h
usage: manage.py showuser [-h] [--version] [-v {0,1,2,3}] [--settings SETTINGS]
                          [--pythonpath PYTHONPATH] [--traceback] [--no-color]
                          [--force-color] [--skip-checks]

Show user list

options:
  -h, --help            show this help message and exit
  --version             Show program's version number and exit.
  -v {0,1,2,3}, --verbosity {0,1,2,3}
                        Verbosity level; 0=minimal output, 1=normal output,
                        2=verbose output, 3=very verbose output
  --settings SETTINGS   The Python path to a settings module, e.g.
                        "myproject.settings.main". If this isn't provided, the
                        DJANGO_SETTINGS_MODULE environment variable will be used.
  --pythonpath PYTHONPATH
                        A directory to add to the Python path, e.g.
                        "/home/djangoprojects/myproject".
  --traceback           Raise on CommandError exceptions.
  --no-color            Don't colorize the command output.
  --force-color         Force colorization of the command output.
  --skip-checks         Skip system checks.

์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋˜๋ฉด ๋ณธ์ธ์ด ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฉฐ -h ์˜ต์…˜์„ ๋ถ™์—ฌ ์ปค๋งจ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋˜๋ฉด help ๋ณ€์ˆ˜์— ์ž‘์„ฑํ•ด ๋†“์•˜๋˜ ์ปค๋งจ๋“œ์˜ ์„ค๋ช…์ด ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ“Œ ์ปค๋งจ๋“œ ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ

โžค ํ‘œ์ค€ ์ถœ๋ ฅ ๋ฐ ํ‘œ์ค€ ์˜ค๋ฅ˜ ์ •๋ณด

์ปค๋งจ๋“œ์—์„œ ํ‘œ์ค€ ์ถœ๋ ฅ๊ณผ ํ‘œ์ค€ ์—๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด self.stdout๊ณผ self.stderr๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ถ”์ฒœ๋˜๊ณ  ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ํŒŒ์ผ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปค๋งจ๋“œ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ณ  ๋””๋ฒ„๊น…ํ•  ์ˆ˜ ์žˆ๋‹ค.

def handle(self, *args, **options):
    self.stdout.write('success')
    self.stderr.write('error')

๋˜, ์ด๋Ÿฌํ•œ ์˜ค๋ธŒ์ ํŠธ์˜ wirte()๋ฉ”์†Œ๋“œ๋Š” ๊ฐœํ–‰์„ ์ž๋™์œผ๋กœ ๋ถ€๊ฐ€ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ค„ ๋์— ์ค„ ๋ฐ”๊ฟˆ์„ ์ถ”๊ฐ€ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

๊ฐœํ–‰์„ ์ œ๊ฑฐํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ print()๋ฉ”์†Œ๋“œ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•˜๊ฒŒ ending์ธ์ˆ˜์— ๊ณต๋ฌธ์ž์—ด์„ ์ง€์ •ํ•˜๋ฉด๋œ๋‹ค.

def handle(self, *args, **options):
    self.stdout.write('success', ending='')
    self.stderr.write('error', ending='')

โžค ์ธ์ˆ˜ ์ถ”๊ฐ€

์ปค๋งจ๋“œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ ์ปค๋งจ๋“œ๊ฐ€ ์ธ์ˆ˜๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ถ”๊ฐ€ํ•˜์—ฌ ์ปค๋งจ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

from django.core.management.base import BaseCommand

from shortener.models import User

class Command(BaseCommand):
    help = 'Create user data'

    def add_arguments(self, parser):
        parser.add_argument('attrs', nargs='+', type=str)

    def handle(self, *args, **options):
        attrs = options['attrs']
        user = User.objects.create(name=attrs[0], content=attrs[1])

        self.stdout.write('Complete created user')

์œ„์™€ ๋‹ค๋ฅด๊ฒŒ add_arguments() ๋ฉ”์†Œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค. ์ด ๋ฉ”์†Œ๋“œ์˜ parser๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ
parser.add_argument๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปค๋งจ๋“œ๋กœ ์ „๋‹ฌํ•  ์ธ์ž๋ฅผ ๋ฐ›์•„ handle()๋ฉ”์†Œ๋“œ๋กœ ์ „๋‹ฌ์‹œ์ผœ ์ค€๋‹ค.

handle() ๋ฉ”์†Œ๋“œ์—์„œ๋Š” ์œ„์—์„œ ์ „๋‹ฌํ•œ ์ธ์ž๋ฅผ options ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์•„ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

% python3 manage.py createuser username usercontent

['username', 'usercontent']
username usercontent
Complete created user

์ถ”๊ฐ€๋กœ ์ƒ์„ฑํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์›Œ์ฃผ๊ธฐ ์œ„ํ•ด ์‚ญ์ œ ์ปค๋งจ๋“œ๋ฅผ ์ž‘์„ฑํ•ด ๋ณด์•˜๋‹ค.

from django.core.management.base import BaseCommand

from shortener.models import User

class Command(BaseCommand):
    help = 'Delete user data'

    def add_arguments(self, parser):
        parser.add_argument('user_id', nargs='+', type=str)

    def handle(self, *args, **options):
        users = options['user_id']
        print(users)

        for user_id in users:
            user = User.objects.filter(id=str(user_id)).last()
            user.delete()
% python3 manage.py deleteuser 3

['3']
delete user 3

โžค ์˜ต์…˜ ์ถ”๊ฐ€

์ธ์ˆ˜๊ฐ€ ์•„๋‹Œ ์˜ต์…˜์„ ํ†ตํ•ด ์ธ์ž๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ด๋ณด์ž.

from django.core.management.base import BaseCommand

from shortener.models import User

class Command(BaseCommand):
    help = 'Create user data'

    def add_arguments(self, parser):
        # parser.add_argument('attrs', nargs='+', type=str)
        parser.add_argument('-n', '--name', required=True, type=str)
        parser.add_argument('-c', '--content', required=True, type=str)

    def handle(self, *args, **options):
        # attrs = options['attrs']
        attrs = [options['name'], options['content']]

        user = User.objects.create(name=attrs[0], content=attrs[1])
        self.stdout.write('Complete created user')
% python3 manage.py createuser -n username -c usercontent

% python3 manage.py createuser --name username2 --content usercontent2

['username', 'usercontent']
Complete created user

['username2', 'usercontent2']
Complete created user

 

๐Ÿ“Œ ์ฐธ๊ณ 

Contents

ํฌ์ŠคํŒ… ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค

์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.