Django Básico === ###### tags: `python, django, python web` # Preparando o Ambiente Download do interpretador do Python para windows: * https://www.python.org/ Documentação: * https://www.python.org/doc/ Teste de código Python via web: * http://pythontutor.com # Configurações Iniciais ### Instalando Django Criar uma uma venv, ambiente virtual. Colocar o código no CMD dentro da pasta da aplicação:. ```a python3 -m venv ./venv ``` Ou apenas: ```a python -m venv ./venv ``` Para carregar a venv, e iniciar o ambiente virtual, o caminho precisa ser completo:. ```a C:\Users\seu_usuario\pasta_da_aplicacao\venv\Scripts\activate ``` Instalar o Django no projeto com a venv iniciada: ```a pip install django==2.2.12 ``` ### Iniciando o projeto Para criar uma pasta do projeto: >O "." no final serve para que crie o projeto como pasta principal e não que crie outra pasta com o nome do projeto. > ```a django-admin startproject nome_proejeto . ``` ### Iniciando um app Um App faz parte do projeto, uma aplicação com determindada função. Iniciando um app: ```a python manage.py startapp nome_do_app ``` ### Alterando o idioma e horário Mude a lingua e timezone do Django no arquivo setting.py, por volta da linha 106 e 108: ```a LANGUAGE_CODE = 'pt-br' TIME_ZONE = 'America/Sao_Paulo' ``` ### CollectStatic Ajuda a criar uma coleção dos arquivos de CSS, JS, imagens, usado quando vamos enviar o sistema para produção: ```a python manage.py collectstatic ``` Configuração em setting.py: ```a #em desenvolvimento STATIC_URL = '/static/' STATICFILES_DIRS=[ os.path.join(BASE_DIR, 'pasta_projeto/static') ] #em produção STATIC_ROOT = os.path.join(BASE_DIR,'static') ``` ### Mensagem de Erro Em settings.py, ao final do arquivo acrescentar: ```a from django.contrib.messages import constants as messages MESSAGE_TAGS = { messages.ERROR: 'danger', messages.SUCCESS: 'success', } ``` No arquivo de views.py do app: ```a if condicao: messages.error(request, 'Mensagem a ser exibida ao usuário') return redirect('pagina') ``` Por convenção é criado um partials com o nome "_alerta.html" com o código: ```a {% if messages %} {% for message in messages %} <div class="alert alert-{{message.tags}}" role="alert"> {{message}} </div> {% endfor %} {% endif %} ``` No caso utilizei o Bootrstrtap 4 com classe de erro, para criar a mensagem. ### Models Arquivo de models.py: ```a from django.db import models from django.db.models import signals from django.template.defaultfilters import slugfy class Base(models.Model): criado = models.DateField('Data de Criação', auto_now_add=True) #salva quando foi criado modificado = models.DateField('Data de Alteração', auto_now=True) #salva quando foi alterado ativo = models.BooleanField('Ativo',default=True) class Meta: abstract = true # A classe abstrata ela não será criada direto no banco. # Irá servir de base para outras classes. class Produto(Base): # A classe produto herda de base nome = models.CharField('Nome', max_length=100) preco = models.DecimalField('Preço', max_digits=8, decimal_places=2) estoque = models.IntegerField('Estoque') slug = models.SlugField('Slug', max_length=100, blank=True, editable=False) #caso algum valor possa ser vazio "null=True", declarar como opção def __str__(self): return self.nome def produto_pre_save(signal, instance, sender, **kwards): instance.slug = slugify(instance.nome) signals.pre_save.connect(produto_pre_save, sender=Produto) #quando produto for enviado, o signals ele é ativo #slugify serve para pegar o nome do produto e transformar em slug. #Exemplo: Pé de Moleque => pe-de-moleque #Esse método serve para criar urls com o nome do produto. #Exemplo: http://site.com/pe-de-moeleque ``` ### Utilizando o Admin do DJango Na pasta da aplicacação, terá um arquivo com o nome admin.py, para utilizar o CRUD dele através do painel administrativo do Django, basta configurar da seguinte forma: ```a from django.contrib import admin from .models importe Nome_das_Classes1,Nome_das_Classes2 @admin.register(Nome_da_Classe) class Nome_das_ClassesAdmin(admin.ModelAdmin): list_display=('nome_da_tabela_1','nome_da_tabela_2','nome_da_tabela_3') ``` ### Forms do Django # Utilidades ### Blibliotecas #### MatchFilter Documentação: https://pypi.org/project/django-mathfilters/ Instala a biblioteca MathFilters, para fazer calcúlos no template: `pip install django-mathfilters` Precisa declarar em INSTALLED_APPS, em settings.py da aplicação. Declarar no template: ```a {% load mathfilters %} ``` Exemplos: ```a <ul> <li>8 + 3 = {{ 8|add:3 }}</li> <li>13 - 17 = {{ 13|sub:17 }}</li> {% with answer=42 %} <li>42 * 0.5 = {{ answer|mul:0.5 }}</li> {% endwith %} {% with numerator=12 denominator=3 %} <li>12 / 3 = {{ numerator|div:denominator }}</li> {% endwith %} <li>|-13| = {{ -13|abs }}</li> </ul> ``` #### Boostrap4 Já adicona o framework boostrap 4 na aplicação. ```a pip install django-bootstrap4 ``` Em settings.py, precisa declarar em APPS_INSTALED `'boostrap4',` #### Envio de E-mail Deve ser declarado no final do arquivo de settings.py da aplicação. Printa o e-mail no console: ```a EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' ``` Caso o servidor de hospedagem possua um servidor de e-mail, usar as configurações abaixo: ```a EMAIL_HOST = 'localhost' #geralmente EMAIL_HOST_USER = 'no-reply@seudominio.com.br' #geralmente EMAIL_HOST_PASSWORD = 'sua_senha' EMAIL_PORT = 587 #geralmente, para conexão segura EMAIL_HOST_TSL = True #pode ser que tenha ``` Na view: ```a from django.core.email.message import EmailMenssage def mandar_email(request): if request.method == 'POST': nome = request.POST['nome'] email = request.POST['email'] assunto = request.POST['assunto'] conteudo = f'Nome:{nome}\n E-mail:{email}\n Assunto:{assunto}' mail = EmailMenssage( subject='E-mail enviado pelo sistema!', body=conteudo, from_email='contato@seu_dominio.com.br', to=['contato@email.com.br','outro_email@email.com'], headers={'Reply-To:email'} #esse email vem do post, ele é pra quem irá responder ) mail.send() ``` ### CRUD com Imagens Documentação: https://pypi.org/project/django-stdimage/ Instale a biblioteca para trabalhar com imagens. ```a pip install django-stdimage ``` #### No arquivo models.py da aplicação: ```a from stdimage import StdImageField, JPEGField imagem = StdImageField('Imagem', upload_to='nome_da_pasta', variations={'thumb':(124,124)}) #variations cria um arquivo com o tamanho nome já pré definido, no caso 'thumb' #també pode ser declarado em models.py: imagem = models.ImageField(upload_to='nome_da_pasta/%d/%m/%Y',blank=True) ``` #### Insert no arquivo de views.py: ```a def nome_do_metodo(request): if request.method == 'POST': imagem = request.FILES['nome_no_input_form'] produto = Produto.objects.create(nome_no_banco=imagem) produto.save() ``` #### Update no arquivo de views.py: ```a def nome_do_metodo(request): if request.method == 'POST': produto_id = request.POST['produto_id'] p = Produto.objects.get(pk=produto_id) #pega todas as informaçoes de produto do banco if 'imagem' in request.FILES: r.nome_no_banco = request.FILES['nome_no_input_form'] p.save() ``` ### Conexão PostgreSQL Instale a biblioteca para conexão. ```a pip install psycopg2 ``` Módulo para banco postgre. ```a pip install psycopg2-binary ``` No settings.py. ```a DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'nome_do_banco', 'USER': 'usuario', 'PASSWORD': 'senha', 'HOST': 'localhost' } } ``` ### Conexão MySQL Instale a biblioteca para conexão. ```a pip install PyMySQL ``` Módulo para banco postgre. ```a pip install MySQL ``` No settings.py. ```a DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'nome_do_banco', 'USER': 'usuario', 'PASSWORD': 'senha', 'HOST': 'localhost', 'PORT': '3306', #porta padrão do MySQL } } ``` ### Redirect ao deslogar Ao final do arquivo settings.py. Força um 'redirect' ao usuário quando deslogar, para a página desejada: ```a LOGOUT_REDIRECT_URL = 'login' ``` ### Página de Erros Importar django.conf.url no início de settings.py: ```a from django.conf.urls import handler400 #requisição não irá ser processada pela má formulação da requisição from django.conf.urls import handler403 #sem premissão ou acesso negado a parte do sistema from django.conf.urls import handler404 #objeto perdido ou não encontrado from django.conf.urls import handler500 #dificuldade de processamento do servidor, a partir de uma incompatibilidade ou configuração incorreta ``` Importar também a localização de onde se encontra a view resposável pelo controle: ```a from app_da_view import views ``` Ao final do arquivo settings.py: ```a handler404 = views.error404 ``` Código na view: ```a from django.http import HttpResponse from django.shortcuts import render def error404(request,excption): from django.template import loader template = loader.get_template('404.html') return HttpResponse(content=template.render(), content_type='text/html; charset=utf8', status=404) ``` ### Comandos Para Aplicação Iniciar o servidor: ```a python manage.py runserver ``` Caso esteja utiliazando o Visual Code, assim sempre que abrir uma nova aba do CMD já vai abrir com oo venv: ```a CTRL+SHIFT+P > python: select interpreter > selecionar o interpretador venv/venv ``` Cria um arquivo com os requerimentos da aplicação ```a pip freeze > requirements.txt ``` ### Comandos Para Banco Faz as migrações para a aplicação: ```a python manage.py makemigrations ``` Faz as migrações para o banco: ```a python manage.py migrate ``` Deleta o banco de dados (CUIDADO AO USAR!): ```a python manage.py flush ``` Faz o model com as tabelas presentes no banco: ```a python manage.py inspectdb ``` Zera as migrações já feitas, igual um delete: ```a python manage.py migrate "nome_do_banco_para_zerar" zero ``` # Deploy da Aplicação no Heroku Digitar no terminal: ```a pip install whitenoise gunicorn ``` Whitenoise => biblioteca para o django exibir os arquivos estáticos Gunicorn => biblioteca serve como servidor para rodar o python Adiconar o Whitenoise em MIDDLEWARE no arquivo settings.py: ```a 'whitenoise.middleware.WhiteNoiseMiddleware', ``` Criar um arquivo na raiz do projeto chamado ".gitignore", com os seguintes parâmetros: ```a __pycache__ *.*~ *.pyc .idea ``` No arquivo settings.py: A opção 'DEBUG' precisa estar como falso, mostrando que a aplicação irá para um amabiente de produção. Em 'ALLOWED_HOSTS', precisa ser o host da aplicação, quando não sabemos, basta colocar o '*', que irá funcionar com qualquer endereço. ```a DEBUG = False ALLOWED_HOSTS = ['*'] ``` --- Digitar os comandos no terminal: ` git init => inicia o GIT` ` git status => mostra os arquivos que não foram adicionados` ` git add . => adicona todos os arquivos` ` git commit -m "Nome do Projeto" => Cria um branch com o nome desejado` Caso seja a primeira vez precisa fazer o login: ```a git config --global user.email "you@example.com" git config --global user.name "Your Name" ``` Servidor usado será o Heroku, precisa baixar o cliente no link abaixo. https://devcenter.heroku.com/articles/getting-started-with-python#set-up Criar um arquivo na raiz do projeto "runtime.txt" Precisa saber qual a versão do python está utilizando, digite no terminal `python -V` Adiconar a versão python no runtime.txt `python-3.8.3` >Essa é a minha versão do python Atualizar o requirements.txt ` pip freeze > requirements.txt` Criar um Arquivo na raiz do projeto "Procfile" do tipo "Text" No arquivo Procfile digitar: ```a web: gunicorn nome_projeto.wsgi --log-file - ``` >Precisa dizer em qual diretório está o arquivo "WSGI.PY" --- Fazer o login no heroku através do terminal:`heroku login` Ao abrir a janela do navegador, faça o login. >As vezes no primeiro login pode dar erro, apenas refaça a operação. > Criando primeiro projeto no Heroku: `heroku create nome_do_projeto_unico --buildpack heroku/python` >Muito Importante! O nome do projeto precisa ser único devido a URL. Apoós criar o projeto, deve passar os arquivos que estão no git. `git push heroku master` ## Deploy com Banco de Dados O banco precisa estar no requirements.txt. Ao dar o push ao heroku, precisa rodar o comando: `heroku run python manage.py migrate` Criar o superuser: `heroku run python manage.py createsuperuser` ## Deploy com Imagens Usando a conta gratuita do Heroku, não tem como usar o Nginx para exibir as imagens. Então uma outra biblioteca tera que ser usada no lugar do WhiteNoise. Baixar: `pip install dj-static` Removendo o WhiteNoise: `pip unistall whitenoise` Remover também do MIDDLEWARE em settings.py Rodar o arquivo de requirements.txt, para instalar tudo: `pip install -r requirements.txt` Atualizar o arquivo de requirements.txt: `pip freeze > requirements.txt` No arquivo wsgi.py; ```a import os from django.nome_do_projeto.wsgi import get_wsgi_application from dj_static import Cling, MediaCling os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'nome_do_projeto.settings') application = Cling(MediaCling(get_wsgi_application())) ``` ---