Pular para o conteúdo
Ramos da Informática - Comunidade de Desenvolvedores

Torne-se um desenvolvedor FullStack: Pacote completo de formação desenvolvedor Frontend e Backend utilizando as linguagens de programação e frameworks mais procurados no mercado de trabalho. Mais informações, aqui. Faça o download do E-BookGuia Completo Para Se Tornar um(a) Desenvolvedor(a) Full-Stack, Começando do ZERO”.

Engenheiro de Software, autor de livros sobe tecnologia e negócios. É mantenedor do site Ramos da Informática. Hobbies: investir em ações, natação e finanças.

Engenheiro de Software, autor de livros sobe tecnologia e negócios. É mantenedor do site Ramos da Informática. Hobbies: investir em ações, natação e finanças.

admin

Todos os artigos deste autor

Criando novos comandos no django-admin

Chatbots com Whatsapp e Cielo integrados Nesse curso, eu vou te mostrar como o consumidor poder realizar um pagamento por dentro do aplicativo do WhatsApp, aonde o seu cliente vai entrar numa conversa como entraria numa conversa com qualquer pessoa ou com a sua empresa, navegar entre os produtos/serviços em menus simples enviados pelo chatbot, adicionar esses produtos/serviços no carrinho de compras, e num determinado ponto do chat, um link exclusivo é enviado para o cliente preencher os dados do cartão de crédito. No final, a análise é devolvida para o Whatsapp no qual a conversa foi iniciada. Inscreva-se.

Veja aqui como criar o seu próprio comando para ser usado com o django-admin ou manage.py do Django.

O django-admin ou manage.py já tem um bocado de comandos interessantes, os mais utilizados são:

startproject – cria novos projetos.
startapp – cria novas apps.
makemigrations – cria novas migrações baseadas nas mudanças detectadas nos modelos Django.
migrate – sincroniza o banco de dados com as novas migrações.
createsuperuser – cria novos usuários.
test – roda os testes da aplicação.
loaddata – carrega dados iniciais a partir de um json, por exemplo, python manage.py loaddata fixtures.json
shell – inicializa um interpretador Python interativo.
dbshell – acessa o banco de dados através da linha de comando, ou seja, você pode executar comandos sql do banco, por exemplo, diretamente no terminal.
inspectdb – retorna todos os modelos Django que geraram as tabelas do banco de dados.
runserver – roda o servidor local do projeto Django.

Mas de repente você precisa criar um comando personalizado conforme a sua necessidade. A palavra chave é BaseCommand ou Writing custom django-admin commands.

Começando do começo

Importante: estamos usando Django 1.8.12 e Python 3.

Criando o projeto

Eu usei esta sequência de comandos para criar o projeto.

# Criando djangoproject.
mkdir djangoproject
cd djangoproject# Criando virtualenv
virtualenv -p python3 .venv# Ativando o .venv.
source .venv/bin/activate
# Diminuindo o caminho do prompt (opcional)
PS1=“(`basename “$VIRTUAL_ENV“`)e[1;34m:/W�33[00m$

# Instalando o Django
pip install django==1.8.12
pip freeze > requirements.txt

# Criando o projeto myproject …
django-admin.py startproject myproject .
cd myproject

# Criando a app ‘core’ …
python ../manage.py startapp core
cd ..

# Editando settings.py”
sed -i “/django.contrib.staticfiles/a ‘myproject.core’,” myproject/settings.py

Pronto! Agora nós já temos um projetinho Django funcionando. Note que o nome da app é core.

Criando as pastas

Para criarmos um novo comando precisamos das seguintes pastas:

core
├── management
│ ├── __init__.py
│ ├── commands
│ │ ├── __init__.py
│ │ ├── novocomando.py

No nosso caso, teremos 3 novos comandos, então digite, estando na pasta djangoproject

mkdir -p core/management/commands
touch core/management/__init__.py
touch core/management/commands/{__init__.py,hello.py,initdata.py,search.py}

Sintaxe do novo comando

Importante: estamos usando Django 1.8.12 e Python 3.

O Django 1.8 usa o argparse como parser de argumentos do command, mais informações em module-argparse.

from django.core.management.base import BaseCommand, CommandError
from optparse import make_optionclass Command(BaseCommand):
help = ‘Texto de ajuda aqui.’
option_list = BaseCommand.option_list + (
make_option(‘–awards’, ‘-a’,
action=“store_true”,
help=‘Ajuda da opção aqui.’),
)def handle(self, **options):
self.stdout.write(‘Hello world.’)
if options[‘awards’]:
self.stdout.write(‘Awards’)

Entendeu? Basicamente o handle é a função que executa o comando principal, no caso o self.stdout.write(‘Hello world.’), ou seja, se você digitar o comando a seguir ele imprime a mensagem na tela.

$ python manage.py hello
Hello World

–awards é um argumento opcional, você também pode digitar -a.

$ python manage.py hello -a
Hello World
Awards

action=”store_true” significa que ele armazena um valor verdadeiro.

Obs: A partir do Django 1.8 os comandos de argumentos opcionais são baseados em **options.

Veja uma outra forma de escrever

from django.core.management.base import BaseCommand, CommandError

class Command(BaseCommand):

def add_arguments(self, parser):
# Argumento nomeado (opcional)
parser.add_argument(‘–awards’, ‘-a’,
action=‘store_true’,
help=‘Ajuda da opção aqui.’)

def handle(self, *args, **options):
self.stdout.write(‘Hello world.’)
if options[‘awards’]:
self.stdout.write(‘Awards’)

A diferença é que aqui usamos parser.add_argument ao invés de make_option.

hello.py

from django.core.management.base import BaseCommand, CommandError
# minimalista
class Command(BaseCommand):
help = ‘Print hello world’def handle(self, **options):
self.stdout.write(‘Hello World’)

Uso

$ python manage.py hello

initdata.py

Objetivo: Obter alguns filmes de uma api e salvar os dados no banco.

api: omdbapi.com

models.py

from django.db import models

class Movie(models.Model):
title = models.CharField(u‘título’, max_length=100)
year = models.PositiveIntegerField(‘ano’, null=True, blank=True)
released = models.CharField(u‘lançamento’, max_length=100, default=, blank=True)
director = models.CharField(‘diretor’, max_length=100, default=, blank=True)
actors = models.CharField(‘atores’, max_length=100, default=, blank=True)
poster = models.URLField(‘poster’, null=True, blank=True)
imdbRating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
imdbID = models.CharField(max_length=50, default=, blank=True)

class Meta:
ordering = [‘title’]
verbose_name = ‘filme’
verbose_name_plural = ‘filmes’

def __str__(self):
return self.title

Não se esqueça de fazer

python manage.py makemigrations
python manage.py migrate

admin.py

Vamos visualizar pelo admin.

from django.contrib import admin
from core.models import Movieadmin.site.register(Movie)

Instale o requests

pip install requests

initdata.py

O código a seguir é longo, mas basicamente temos

print_red(name) função que imprime um texto em vermelho (opcional)
get_html(year) função que lê os dados da api usando requests, e depois escolhe um filme randomicamente a partir de 2 letras
get_movie(year) se o dicionário conter {‘Response’: ‘True’, …} então retorna um dicionário do filme localizado
save() salva os dados no banco
handle(movies, year) este é o comando principal. Busca os filmes várias vezes, conforme definido pela variável movies, e salva os n filmes.

# -*- coding: utf-8 -*- #

import random
import string
import requests
from django.core.management.base import BaseCommand, CommandError
from django.core.exceptions import ValidationError
from optparse import make_option
from core.models import Movie

class Command(BaseCommand):
help = “””Faz o crawler numa api de filmes e retorna os dados.
Uso: python manage.py initdata
ou: python manage.py initdata -m 20
ou: python manage.py initdata -m 20 -y 2015″””
option_list = BaseCommand.option_list + (
make_option(‘–movies’, ‘-m’,
dest=‘movies’,
default=10,
help=‘Define a quantidade de filmes a ser inserido.’),
make_option(‘–year’, ‘-y’,
dest=‘year’,
action=‘store’,
default=None,
help=‘Define o ano de lançamento do filme.’),
)

def print_red(self, name):
“””imprime em vermelho”””
print(�33[91m {}�33[00m”.format(name))

def get_html(self, year):
“””
Le os dados na api http://www.omdbapi.com/ de forma aleatoria
e escolhe um filme buscando por 2 letras
“””

# Escolhe duas letras aleatoriamente
letters = .join(random.choice(string.ascii_lowercase) for _ in range(2))

# Se não for definido o ano, então escolhe um randomicamente
if year is None:
year = str(random.randint(1950, 2015))
url = ‘http://www.omdbapi.com/?t={letters}*&y={year}&plot=short&r=json’.format(letters=letters, year=str(year))
return requests.get(url).json()

def get_movie(self, year, **kwargs):
“”” Retorna um dicionário do filme “””

movie = self.get_html(year)
j = 1 # contador

# Faz a validação de Response. Se a resposta for falsa, então busca outro filme.
while movie[‘Response’] == ‘False’ and j < 100:
movie = self.get_html(year)
self.print_red(‘Tentanto %d vezesn % j)
j += 1
return movie

def save(self, **kwargs):
“””SALVA os dados”””
try:
Movie.objects.create(**kwargs)
except ValidationError as e:
self.print_red(e.messages)
self.print_red(‘O objeto não foi salvo.n)

def handle(self, movies, year, **options):
“”” se “movies” não for nulo, transforma em inteiro “””

self.verbosity = int(options.get(‘verbosity’))

if movies is not None:
movies = int(movies)

# busca os filmes n vezes, a partir da variavel “movies”
for i in range(movies):
# verifica as validações
m = self.get_movie(year)
if m[‘imdbRating’] == “N/A”:
m[‘imdbRating’] = 0.0

# Transforma “year” em inteiro
if “–” in m[‘Year’]:
m[‘Year’] = year

data = {
“title”: m[‘Title’],
“year”: m[‘Year’],
“released”: m[‘Released’],
“director”: m[‘Director’],
“actors”: m[‘Actors’],
“poster”: m[‘Poster’],
“imdbRating”: m[‘imdbRating’],
“imdbID”: m[‘imdbID’],
}

self.save(**data)

if self.verbosity > 0:
self.stdout.write(n {0} {1} {2}.format(i + 1, data[‘year’], data[‘title’]))
if self.verbosity > 0:
self.stdout.write(nForam salvos %d filmes’ % movies)

Uso

Usage: python manage.py initdata [options]

Faz o crawler numa api de filmes e retorna os dados.
Uso: python manage.py initdata
ou: python manage.py initdata -m 20
ou: python manage.py initdata -m 20 -y 2015

search.py

Objetivo: Localizar o filme pelo título ou ano de lançamento.

from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
from core.models import Movieclass Command(BaseCommand):
help = “””Localiza um filme pelo título ou ano de lançamento.
Uso: python manage.py search -t ‘Ted 2’
ou: python manage.py search -y 2015
ou: python manage.py search -t ‘a’ -y 2015″””option_list = BaseCommand.option_list + (
make_option(‘–title’, ‘-t’,
dest=‘title’,
default=None,
help=‘Localiza um filme pelo título.’),
make_option(‘–year’, ‘-y’,
dest=‘year’,
default=None,
help=‘Localiza um filme pelo ano de lançamento.’),
)

def handle(self, title=None, year=None, **options):
“”” dicionário de filtros “””
self.verbosity = int(options.get(‘verbosity’))

filters = {
‘title__istartswith’: title,
‘year’: year
}

filter_by = {key: value for key, value in filters.items() if value is not None}
queryset = Movie.objects.filter(**filter_by)

if self.verbosity > 0:
for movie in queryset:
self.stdout.write({0} {1}.format(movie.year, movie.title))
self.stdout.write(n{0} filmes localizados.’.format(queryset.count()))

Uso

Usage: python manage.py search [options]

Localiza um filme pelo título ou ano de lançamento.
Uso: python manage.py search -t ‘Ted 2’
ou: python manage.py search -y 2015
ou: python manage.py search -t ‘a’ -y 2015

Aqui tem um exemplo legal que eu usei como ideia pra fazer este post.

Mais algumas referências:

Writing custom django-admin commands

Zachary Voase: Fixing Django Management Commands

Adding Custom Commands to manage.py and django-admin.py by dave

Este artigo foi importado automaticamente por fazer parte do Planetário Dev. Quer fazer parte deste HUB de conteúdos? Faça parte do Planetário e veja as vantagens.

Não tem site ou blog? Seja um autor do site e ainda pode ser remunerado.

Leia também:

Facebook
LinkedIn
Twitter
Pinterest
Reddit
Telegram
WhatsApp
Email
Print

Relacionados

Deixe uma resposta