Oct 21, 2021
16 min read
Negros Dev
Tutorial para o site negros.dev
Este projeto foi feito com:
Como rodar o projeto?
Clone esse repositório.
Crie um virtualenv com Python 3.
Ative o virtualenv.
Instale as dependências.
Rode as migrações.
git clone https://github.com/rg3915/django-negros-dev.git
cd django-negros-dev
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python contrib/env_gen.py
python manage.py migrate
python manage.py createsuperuser --username="admin" --email=""
Tutorial
O que é Django?
Segundo Django Brasil,
Django é um framework web de alto nível escrito em Python que estimula o desenvolvimento rápido e limpo.
adota o padrão MTV
possui ORM
admin
herança de templates e modelos
open source
Documentação oficial Django .
MVC x MTV
Model – é o modelo, a camada de abstração do banco de dados, onde acontece o ORM
View – é o controlador, onde acontece as regras de negócio e a comunicação entre a base de dados e o navegador
Templates – é a camada de apresentação, são as páginas html
ORM
Object Relational Mapper (Mapeamento Objeto Relacional)
Usa orientação a objetos para abstrair as querys do banco de dados.
O exemplo a seguir retorna todos os usuários cujo email termina com gmail.com
.
User .objects .filter (email__endswith = 'gmail.com' )
No modelo a seguir Person
será o nome da tabela no banco de dados e first_name
será o nome do campo.
# models.py
class Person (models .Model ):
first_name = models .CharField ('nome' , max_length = 100 , unique = True )
O que é Virtualenv e Requirements?
Virtualenv é um ambiente virtual que isola seu projeto junto com suas dependências.
E requirements é um arquivo (requirements.txt
) que lista todas as bibliotecas que você precisa usar no seu projeto, por exemplo:
# requirements.txt
Django==3.1.8
dj-database-url==0.5.0
python-decouple==3.4
django-extensions==3.1.2
Qual é a essência do Django?
ORM – abstrair as querys SQL.
Admin – O painel de Admin facilita a nossa vida com um CRUD básico.
Herança de templates e modelos
Iniciando um projeto
Instale o Python na sua versão mais recente.
Crie uma virtualenv
Ative a virtualenv
# Linux
source .venv/bin/activate
# Windows
.venv\Scripts\activate.bat
Instale as dependências
pip install -U pip
pip install Django==3.1.8 dj-database-url python-decouple django-extensions
Importante: crie um arquivo requirements.txt
> requirements.txt
pip freeze | grep dj-database-url >> requirements.txt
pip freeze | grep python-decouple >> requirements.txt
pip freeze | grep django-extensions >> requirements.txt
cat requirements.txt
“>
pip freeze
pip freeze | grep Django==3.1.8 >> requirements.txt
pip freeze | grep dj-database-url >> requirements.txt
pip freeze | grep python-decouple >> requirements.txt
pip freeze | grep django-extensions >> requirements.txt
cat requirements.txt
Criando um .gitignore
Veja no repositório do projeto.
Gere um arquivo .env
Copiar o conteúdo de env_gen.py
https://github.com/rg3915/django-negros-dev/blob/main/contrib/env_gen.py
mkdir contrib
touch contrib/env_gen.py
python contrib/env_gen.py
cat .env
Criando um projeto
django-admin.py startproject myproject .
Criando uma app
cd myproject
python ../manage.py startapp core
Edite o settings.py
# settings.py
INSTALLED_APPS = [
...
'django_extensions ',
'myproject.core' ,
]
Rodando as migrações para criar um banco de dados local
cd ..
python manage.py migrate
Criando um super usuário
python manage.py createsuperuser
Rodando a aplicação (nível 0)
python manage.py runserver
A aplicação roda na porta 8000.
Projeto mínimo
Veja a estrutura do projeto
├── .gitignore
├── contrib
│ └── env_gen.py
├── db.sqlite3
├── manage.py
├── myproject
│ ├── asgi.py
│ ├── core
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── models.py
│ │ ├── tests.py
│ │ └── views.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── README.md
└── requirements.txt
Nível 1
Editar settings.py
# settings.py
from pathlib import Path
from decouple import Csv , config
from dj_database_url import parse as dburl
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path (__file__ ).resolve ().parent .parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config ('SECRET_KEY' )
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config ('DEBUG' , default = False , cast = bool )
ALLOWED_HOSTS = config ('ALLOWED_HOSTS' , default = [], cast = Csv ())
...
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
default_dburl = 'sqlite:///' + str (BASE_DIR / 'db.sqlite3' )
DATABASES = {
'default' : config ('DATABASE_URL' , default = default_dburl , cast = dburl ),
}
...
LANGUAGE_CODE = 'pt-br'
TIME_ZONE = 'America/Sao_Paulo'
...
STATIC_ROOT = BASE_DIR .joinpath ('staticfiles' )
Editar urls.py
<div class="highlight highlight-source-python position-relative overflow-auto" data-snippet-clipboard-copy-content="# urls.py
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
def index(request):
return HttpResponse('
Django Tutorial
‘)
urlpatterns = [
path(”, index, name=’index’),
path(‘admin/’, admin.site.urls),
]
“>
# urls.py
from django .contrib import admin
from django .http import HttpResponse
from django .urls import path
def index (request ):
return HttpResponse ('<h1>Django Tutorial</h1>' )
urlpatterns = [
path ('' , index , name = 'index' ),
path ('admin/' , admin .site .urls ),
]
Nível 2
Editar core/urls.py
touch myproject/core/urls.py
# core/urls.py
from django .urls import path
from .views import index
app_name = 'core'
urlpatterns = [
path ('' , index , name = 'index' ),
]
Editar urls.py
# urls.py
from django .contrib import admin
from django .urls import include , path
urlpatterns = [
path ('' , include ('myproject.core.urls' , namespace = 'core' )),
path ('admin/' , admin .site .urls ),
]
Editar core/views.py
touch myproject/core/views.py
<div class="highlight highlight-source-python position-relative overflow-auto" data-snippet-clipboard-copy-content="# core/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse('
Django Tutorial
‘)
“>
# core/views.py
from django .http import HttpResponse
def index (request ):
return HttpResponse ('<h1>Django Tutorial</h1>' )
Nível 3
Editar core/views.py
# core/views.py
from django .shortcuts import render
def index (request ):
template_name = 'index.html'
return render (request , template_name )
Editar core/templates/index.html
mkdir myproject/core/templates
touch myproject/core/templates/index.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
Django Tutorial
Negros Dev
“>
<!-- index -->
< h1 > Django Tutorial</ h1 >
< h2 > Negros Dev</ h2 >
Projeto mais completo
Instalando e usando PostgreSQL
sudo apt-get install -y postgresql-12 postgresql-contrib-12
Criar database
sudo su - postgres
psql -U postgres -c "CREATE ROLE myuser ENCRYPTED PASSWORD 'mypass' LOGIN;"
psql -U postgres -c "CREATE DATABASE mydb OWNER myuser;"
Editar o settings.py
# settings.py
DATABASES = {
'default' : {
'ENGINE' : 'django.db.backends.postgresql' ,
'NAME' : config ('POSTGRES_DB' , 'postgres' ),
'USER' : config ('POSTGRES_USER' , 'postgres' ),
'PASSWORD' : config ('POSTGRES_PASSWORD' , '' ),
'HOST' : config ('DB_HOST' , '' ),
'PORT' : '5432' ,
}
}
Editar o .env
# .env
POSTGRES_DB=
POSTGRES_USER=
POSTGRES_PASSWORD=
DB_HOST=localhost
Instalando psycopg2-binary
django.core.exceptions.ImproperlyConfigured: Error loading psycopg2 module: No module named 'psycopg2'
> requirements.txt
“>
pip install psycopg2-binary
pip freeze | grep psycopg2-binary >> requirements.txt
Criando um novo app
cd myproject
python ../manage.py startapp expense
cd ..
Edite o settings.py
# settings.py
INSTALLED_APPS = [
...
'myproject .core ',
'myproject.expense' ,
]
Editar core/models.py
# core/models.py
from django .db import models
class TimeStampedModel (models .Model ):
created = models .DateTimeField (
'criado em' ,
auto_now_add = True ,
auto_now = False
)
modified = models .DateTimeField (
'modificado em' ,
auto_now_add = False ,
auto_now = True
)
class Meta :
abstract = True
Editar expense/models.py
https://docs.djangoproject.com/en/3.2/ref/models/fields/
# expense/models.py
from django .db import models
from myproject .core .models import TimeStampedModel
class Customer (models .Model ):
first_name = models .CharField ('nome' , max_length = 50 )
last_name = models .CharField ('sobrenome' , max_length = 50 , null = True , blank = True ) # noqa E501
email = models .EmailField (null = True , blank = True )
class Meta :
ordering = ('first_name' ,)
verbose_name = 'cliente'
verbose_name_plural = 'clientes'
@property
def full_name (self ):
return f'{ self .first_name } { self .last_name or "" } ' .strip ()
def __str__ (self ):
return self .full_name
class Expense (TimeStampedModel ):
description = models .CharField ('descrição' , max_length = 100 )
payment_date = models .DateField ('data de pagamento' , null = True , blank = True )
customer = models .ForeignKey (
Customer ,
on_delete = models .SET_NULL ,
verbose_name = 'pago a' ,
related_name = 'expenses' ,
null = True ,
blank = True
)
value = models .DecimalField ('valor' , max_digits = 7 , decimal_places = 2 )
paid = models .BooleanField ('pago' , default = False )
class Meta :
ordering = ('-payment_date' ,)
verbose_name = 'despesa'
verbose_name_plural = 'despesas'
def __str__ (self ):
return self .description
# def get_absolute_url(self):
# return reverse_lazy('_detail', kwargs={'pk': self.pk})
Editar expense/admin.py
# expense/admin.py
from django .contrib import admin
from .models import Customer , Expense
# admin.site.register(Customer)
@admin .register (Customer )
class CustomerAdmin (admin .ModelAdmin ):
list_display = ('__str__' , 'email' )
search_fields = ('first_name' , 'last_name' , 'email' )
@admin .register (Expense )
class ExpenseAdmin (admin .ModelAdmin ):
list_display = ('__str__' , 'customer' , 'value' , 'payment_date' , 'paid' )
search_fields = ('description' , 'customer__first_name' , 'customer__last_name' ) # noqa E501
list_filter = ('paid' ,)
date_hierarchy = 'payment_date'
Atualizando o banco
Gerar arquivo de migração.
python manage.py makemigrations
Executar a migração.
ORM
python manage.py shell_plus
Criando alguns registros
customers = ['Huguinho', 'Zezinho', 'Luizinho']
for customer in customers:
Customer.objects.create(first_name=customer)
customers = ['Prático', 'Heitor', 'Cícero']
items = []
for customer in customers:
obj = Customer(first_name=customer)
items.append(obj)
Customer.objects.bulk_create(items)
Criar despesas pelo Admin.
Alterando a data das despesas não pagas.
python manage.py shell_plus
# Selecionar as despesas não pagas.
expenses = Expense.objects.filter(paid=False)
# Alterando a data de pagamento para uma data futura.
from datetime import date
future = date(2021, 5, 2)
for expense in expenses:
expense.payment_date = future
Expense.objects.bulk_update(expenses, ['payment_date'])
Cuidado ao deletar
expense = Expense.objects.get(pk=1)
expense.delete()
Templates
mkdir -p myproject/core/templates/includes
touch myproject/core/templates/base.html
touch myproject/core/templates/includes/nav.html
mkdir -p myproject/core/static/{css,img,js}
touch myproject/core/static/css/style.css
touch myproject/core/static/js/main.js
mkdir -p myproject/expense/templates/expense
touch myproject/expense/templates/expense/expense_{list,detail,form}.html
tree
Editar base.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% load static %}
Django
{% block css %}{% endblock css %}
{% include "includes/nav.html" %}
{% block content %}{% endblock content %}
“>
<!-- base.html -->
{% load static %}
<!DOCTYPE html>
< html lang ="en ">
< head >
< meta charset ="utf-8 ">
< meta http-equiv ="X-UA-Compatible " content ="IE=edge ">
< meta name ="viewport " content ="width=device-width, initial-scale=1.0, shrink-to-fit=no ">
< link rel ="shortcut icon " href ="https://www.djangoproject.com/favicon.ico ">
< title > Django</ title >
<!-- Bootstrap core CSS -->
< link rel ="stylesheet " href ="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css ">
<!-- Font-awesome -->
< link rel ="stylesheet " href ="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css ">
< link rel ="stylesheet " href ="{% static 'css/style.css' %} ">
{% block css %}{% endblock css %}
</ head >
< body >
< div class ="container ">
{% include "includes/nav.html" %}
{% block content %}{% endblock content %}
</ div >
<!-- jQuery -->
< script src ="https://code.jquery.com/jquery-3.4.1.min.js "> </ script >
<!-- Bootstrap core JS -->
< script src ="https://cdn.jsdelivr.net/npm/[email protected] /dist/umd/popper.min.js "> </ script >
< script src ="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js "> </ script >
</ body >
</ html >
Editar includes/nav.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
Navbar
“>
<!-- includes/nav.html -->
<!-- https://getbootstrap.com/docs/4.0/examples/starter-template/ -->
<!-- https://github.com/JTruax/bootstrap-starter-template/blob/master/template/start.html -->
< nav class ="navbar navbar-expand-md navbar-dark bg-dark fixed-top ">
< a class ="navbar-brand " href ="{% url 'core:index' %} "> Navbar</ a >
< button class ="navbar-toggler " type ="button " data-toggle ="collapse " data-target ="#navbarsExampleDefault " aria-controls ="navbarsExampleDefault " aria-expanded ="false " aria-label ="Toggle navigation ">
< span class ="navbar-toggler-icon "> </ span >
</ button >
< div class ="collapse navbar-collapse " id ="navbarsExampleDefault ">
< ul class ="navbar-nav mr-auto ">
< li class ="nav-item active ">
< a class ="nav-link " href ="{% url 'core:index' %} "> Home < span class ="sr-only "> (current)</ span > </ a >
</ li >
< li class ="nav-item ">
< a class ="nav-link " href =""> Despesas</ a >
</ li >
</ ul >
</ div >
</ nav >
Editar index.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% extends "base.html" %}
{% block content %}
{% endblock content %}
“>
<!-- index.html -->
{% extends "base.html" %}
{% block content %}
< div class ="jumbotron ">
< h1 > Django Tutorial</ h1 >
< a href ="https://negros.dev/ " target ="_blank "> negros.dev</ a >
</ div >
{% endblock content %}
Editar style.css
<div class="highlight highlight-source-css position-relative overflow-auto" data-snippet-clipboard-copy-content="cat < myproject/core/static/css/style.css
body {
margin-top: 60px;
}
label.required:after {
content: ‘ *’;
color: red;
}
.no {
color: red;
}
EOF
“>
cat << EOF > myproject / cor e/ static/ css/ style.css
body {
margin-top : 60px ;
}
label .required : after {
content : ' *' ;
color : red;
}
.no {
color : red;
}
EOF
Rodar a aplicação
Editar expense_list.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% extends "base.html" %}
{% block content %}
Lista de Despesas
{% endblock content %}
“>
<!-- expense_list.html -->
{% extends "base.html" %}
{% block content %}
Lista de Despesas
{% endblock content %}
Editar expense_detail.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% extends "base.html" %}
{% block content %}
Detalhes de Despesa
{% endblock content %}
“>
<!-- expense_detail.html -->
{% extends "base.html" %}
{% block content %}
Detalhes de Despesa
{% endblock content %}
Editar expense_form.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% extends "base.html" %}
{% block content %}
Adicionar Despesa
{% endblock content %}
“>
<!-- expense_form.html -->
{% extends "base.html" %}
{% block content %}
Adicionar Despesa
{% endblock content %}
Editar expense/views.py
# expense/views.py
from django .shortcuts import render
def expense_list (request ):
template_name = 'expense/expense_list.html'
return render (request , template_name )
def expense_detail (request , pk ):
template_name = 'expense/expense_detail.html'
return render (request , template_name )
def expense_create (request ):
template_name = 'expense/expense_form.html'
return render (request , template_name )
Editar expense/urls.py
touch myproject/expense/urls.py
<div class="highlight highlight-source-python position-relative overflow-auto" data-snippet-clipboard-copy-content="# expense/urls.py
from django.urls import path
from myproject.expense import views as v
app_name = 'expense'
urlpatterns = [
path('', v.expense_list, name='expense_list'),
path('/’, v.expense_detail, name=’expense_detail’),
path(‘create/’, v.expense_create, name=’expense_create’),
]
“>
# expense/urls.py
from django .urls import path
from myproject .expense import views as v
app_name = 'expense'
urlpatterns = [
path ('' , v .expense_list , name = 'expense_list' ),
path ('<int:pk>/' , v .expense_detail , name = 'expense_detail' ),
path ('create/' , v .expense_create , name = 'expense_create' ),
]
Editar urls.py
# urls.py
...
path ('expense/' , include ('myproject.expense.urls' , namespace = 'expense' )),
...
Editar includes/nav.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="…
Despesas
…
“>
...
< a class ="nav-link " href ="{% url 'expense:expense_list' %} "> Despesas</ a >
...
Rodar a aplicação e navegar pelas urls.
CRUD
Lista
Editar expense/views.py
# expense/views.py
from .models import Expense
def expense_list (request ):
template_name = 'expense/expense_list.html'
object_list = Expense .objects .all ()
context = {'object_list' : object_list }
return render (request , template_name , context )
Editar expense_list.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% extends "base.html" %}
{% block content %}
Descrição
Pago a
Valor
Data de pagamento
{% for object in object_list %}
{{ object.description }}
{{ object.customer|default:’—‘ }}
{{ object.value }}
{{ object.payment_date|date:’d/m/Y’|default:’—‘ }}
{% endfor %}
{% endblock content %}
“>
<!-- expense_list.html -->
{% extends "base.html" %}
{% block content %}
< h1 >
Lista de Despesas
< a class ="btn btn-primary " href ="{% url 'expense:expense_create' %} "> Adicionar</ a >
</ h1 >
< table class ="table ">
< thead >
< tr >
< th > Descrição</ th >
< th > Pago a</ th >
< th > Valor</ th >
< th > Data de pagamento</ th >
</ tr >
</ thead >
< tbody >
{% for object in object_list %}
< tr >
< td >
< a href ="{{ object.get_absolute_url }} "> {{ object.description }}</ a >
</ td >
< td > {{ object.customer|default:'---' }}</ td >
< td > {{ object.value }}</ td >
< td > {{ object.payment_date|date:'d/m/Y'|default:'---' }}</ td >
</ tr >
{% endfor %}
</ tbody >
</ table >
{% endblock content %}
Editar expense/models.py
# expense/models.py
from django .urls import reverse_lazy
...
def get_absolute_url (self ):
return reverse_lazy ('expense:expense_detail' , kwargs = {'pk' : self .pk })
Detalhes
Editar expense_detail.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% extends "base.html" %}
{% block content %}
Detalhes de Despesa
Descrição: {{ object.description }}
Cliente: {{ object.customer|default:’—‘ }}
Valor: {{ object.value }}
Data de pagamento: {{ object.payment_date|date:’d/m/Y’|default:’—‘ }}
{% endblock content %}
“>
<!-- expense_detail.html -->
{% extends "base.html" %}
{% block content %}
< h1 > Detalhes de Despesa</ h1 >
< ul >
< li > < b > Descrição:</ b > {{ object.description }}</ li >
< li > < b > Cliente:</ b > {{ object.customer|default:'---' }}</ li >
< li > < b > Valor:</ b > {{ object.value }}</ li >
< li > < b > Data de pagamento:</ b > {{ object.payment_date|date:'d/m/Y'|default:'---' }}</ li >
</ ul >
{% endblock content %}
Editar expense/views.py
# expense/views.py
def expense_detail (request , pk ):
template_name = 'expense/expense_detail.html'
_object = Expense .objects .get (pk = pk )
context = {'object' : _object }
return render (request , template_name , context )
Adicionar
Editar expense_form.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% extends "base.html" %}
{% block content %}
Despesa
{% csrf_token %}
{{ form.as_p }}
Salvar
{% endblock content %}
“>
<!-- expense_form.html -->
{% extends "base.html" %}
{% block content %}
< h1 > Despesa</ h1 >
< div class ="cols-6 ">
< form class ="form-horizontal " action =". " method ="POST " enctype ="multipart/form-data ">
< div class ="col-sm-6 ">
{% csrf_token %}
{{ form.as_p }}
< div class ="form-group ">
< button type ="submit " class ="btn btn-primary "> Salvar</ button >
</ div >
</ div >
</ form >
</ div >
{% endblock content %}
Editar expense/forms.py
touch myproject/expense/forms.py
# expense/forms.py
from django import forms
from .models import Expense
class ExpenseForm (forms .ModelForm ):
required_css_class = 'required'
payment_date = forms .DateField (
label = 'Data de pagamento' ,
widget = forms .DateInput (
format = '%Y-%m-%d' ,
attrs = {
'type' : 'date' ,
}),
input_formats = ('%Y-%m-%d' ,),
required = False ,
)
class Meta :
model = Expense
# fields = '__all__'
fields = ('description' , 'payment_date' , 'customer' , 'value' )
# exclude = ('paid',)
def __init__ (self , * args , ** kwargs ):
super (ExpenseForm , self ).__init__ (* args , ** kwargs )
for field_name , field in self .fields .items ():
field .widget .attrs ['class' ] = 'form-control'
Editar expense/views.py
# expense/views.py
from django .shortcuts import redirect , render
from .forms import ExpenseForm
from .models import Expense
def expense_create (request ):
template_name = 'expense/expense_form.html'
form = ExpenseForm (request .POST or None )
if request .method == 'POST' :
if form .is_valid ():
form .save ()
return redirect ('expense:expense_list' )
context = {'form' : form }
return render (request , template_name , context )
Editar
Editar expense_list.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
Ações
“>
<!-- expense_list.html -->
< th > Ações</ th >
< td >
< a href ="{% url 'expense:expense_update' object.pk %} ">
< i class ="fa fa-edit "> </ i >
</ a >
</ td >
Editar expense/urls.py
<div class="highlight highlight-source-python position-relative overflow-auto" data-snippet-clipboard-copy-content="# expense/urls.py
…
path('/update/’, v.expense_update, name=’expense_update’),
“>
# expense/urls.py
...
path ('<int:pk>/update/' , v .expense_update , name = 'expense_update' ),
Editar expense/views.py
# expense/views.py
def expense_update (request , pk ):
template_name = 'expense/expense_form.html'
instance = Expense .objects .get (pk = pk )
form = ExpenseForm (request .POST or None , instance = instance )
if request .method == 'POST' :
if form .is_valid ():
form .save ()
return redirect ('expense:expense_list' )
context = {'form' : form }
return render (request , template_name , context )
Deletar
Editar expense_list.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
“>
< a href ="{% url 'expense:expense_delete' object.pk %} " style ="padding-left: 7px ">
< i class ="fa fa-close no "> </ i >
</ a >
Editar expense/urls.py
<div class="highlight highlight-source-python position-relative overflow-auto" data-snippet-clipboard-copy-content="# expense/urls.py
…
path('/delete/’, v.expense_delete, name=’expense_delete’),
“>
# expense/urls.py
...
path ('<int:pk>/delete/' , v .expense_delete , name = 'expense_delete' ),
Editar expense/views.py
# expense/views.py
def expense_delete (request , pk ):
template_name = 'expense/expense_confirm_delete.html'
obj = Expense .objects .get (pk = pk )
if request .method == 'POST' :
obj .delete ()
return redirect ('expense:expense_list' )
context = {'object' : obj }
return render (request , template_name , context )
Editar expense/expense_confirm_delete.html
touch myproject/expense/templates/expense/expense_confirm_delete.html
<div class="highlight highlight-text-html-basic position-relative overflow-auto" data-snippet-clipboard-copy-content="
{% extends "base.html" %}
{% block content %}
Deletar Despesa
{% csrf_token %}
Deseja deletar {{ object }} ?
Valor: {{ object.value }}
{% endblock content %}
“>
<!-- expense_confirm_delete.html -->
{% extends "base.html" %}
{% block content %}
< h1 > Deletar Despesa</ h1 >
< div class ="cols-6 ">
< form action =". " method ="POST ">
< div class ="col-sm-6 ">
{% csrf_token %}
< p > Deseja deletar {{ object }} ?</ p >
< p > Valor: {{ object.value }}</ p >
< div class ="form-group ">
< button type ="submit " class ="btn btn-primary "> Sim</ button >
< a class ="btn btn-danger " href ="{% url 'expense:expense_list' %} "> Não</ a >
</ div >
</ div >
</ form >
</ div >
{% endblock content %}
Class Based View
https://ccbv.co.uk/
Editar expense/urls.py
<div class="highlight highlight-source-python position-relative overflow-auto" data-snippet-clipboard-copy-content="# expense/urls.py
from django.urls import path
from myproject.expense import views as v
app_name = 'expense'
urlpatterns = [
# path('', v.expense_list, name='expense_list'),
# path('/’, v.expense_detail, name=’expense_detail’),
# path(‘create/’, v.expense_create, name=’expense_create’),
# path(‘/update/’, v.expense_update, name=’expense_update’),
# path(‘/delete/’, v.expense_delete, name=’expense_delete’),
path(”, v.ExpenseListView.as_view(), name=’expense_list’),
path(‘/’, v.ExpenseDetailView.as_view(), name=’expense_detail’),
path(‘create/’, v.ExpenseCreateView.as_view(), name=’expense_create’),
path(‘/update/’, v.ExpenseUpdateView.as_view(), name=’expense_update’),
path(‘/delete/’, v.ExpenseDeleteView.as_view(), name=’expense_delete’),
]
“>
# expense/urls.py
from django .urls import path
from myproject .expense import views as v
app_name = 'expense'
urlpatterns = [
# path('', v.expense_list, name='expense_list'),
# path('<int:pk>/', v.expense_detail, name='expense_detail'),
# path('create/', v.expense_create, name='expense_create'),
# path('<int:pk>/update/', v.expense_update, name='expense_update'),
# path('<int:pk>/delete/', v.expense_delete, name='expense_delete'),
path ('' , v .ExpenseListView .as_view (), name = 'expense_list' ),
path ('<int:pk>/' , v .ExpenseDetailView .as_view (), name = 'expense_detail' ),
path ('create/' , v .ExpenseCreateView .as_view (), name = 'expense_create' ),
path ('<int:pk>/update/' , v .ExpenseUpdateView .as_view (), name = 'expense_update' ),
path ('<int:pk>/delete/' , v .ExpenseDeleteView .as_view (), name = 'expense_delete' ),
]
Editar expense/views.py
# expense/views.py
from django .shortcuts import redirect , render
from django .urls import reverse_lazy
from django .views .generic import (
CreateView ,
DeleteView ,
DetailView ,
ListView ,
UpdateView
)
...
class ExpenseListView (ListView ):
model = Expense
class ExpenseDetailView (DetailView ):
model = Expense
class ExpenseCreateView (CreateView ):
model = Expense
form_class = ExpenseForm
class ExpenseUpdateView (UpdateView ):
model = Expense
form_class = ExpenseForm
class ExpenseDeleteView (DeleteView ):
model = Expense
success_url = reverse_lazy ('expense:expense_list' )
Assista: Python-triangulo: Django: FBV vs CBV
Links
GitHub
View Github
John was the first writer to have joined pythonawesome.com. He has since then inculcated very effective writing and reviewing culture at pythonawesome which rivals have found impossible to imitate.
Previous Post
Huawei Solar sensors for Home Assistant
Next Post
NLPIR tutorial: pretrain for IR. pre-train on raw textual corpus, fine-tune on MS MARCO Document Ranking
Django Basics and Related Technologies Tutorial
26 November 2021
The Definitive Django Learning Platform
10 October 2021
Learn Python and the Django Framework by building a e-commerce website
05 August 2021
django-production Opinionated one-size-fits-most defaults for running Django to production (or any other deployed environment). Installation pip install django-production DJANGO_SETTINGS_MODULE=yourproject.settings django-production-apply What it does When you install the package, it
17 January 2023
Django Websockets Framework Django Websockets Framework (DWF) is a layer over Django Channels aimed to make it as simple as possible to broadcast changes in Django models to browsers through websockets, with minimal
17 January 2023
Minimal Django + PostgreSQL + Create React App template
13 August 2022
Tetra - A full stack component framework for Django using Alpine.js
07 August 2022
A music venue review web app built with Djando framework
31 July 2022