Configuração do Projeto
Criar Projeto e App
pip install django django-admin startproject mysite cd mysite python manage.py startapp blog
Comandos Comuns
runserverIniciar servidor de desenvolvimento na porta 8000
makemigrationsGerar arquivos de migração a partir de alterações no modelo
migrateAplicar migrações ao banco de dados
createsuperuserCriar superusuário admin
shellShell Python interativo com Django
testExecutar suite de testes
Estrutura do Projeto
manage.pyPonto de entrada CLI
settings.pyConfiguração do projeto
urls.pyConfiguração de URL raiz
wsgi.py / asgi.pyPontos de entrada do servidor
apps/models.pyModelos de banco de dados
apps/views.pyHandlers de requisição
Models
Definir um Model
from django.db import models class Post(models.Model): title = models.CharField(max_length=200) body = models.TextField() created = models.DateTimeField(auto_now_add=True) published = models.BooleanField(default=False)
Tipos de Campo
CharField(max_length=N)Texto curto (max_length obrigatório)
TextField()Texto longo (sem limite)
IntegerField()Valor inteiro
FloatField()Número de ponto flutuante
BooleanField()True / False
DateTimeField()Data e hora
EmailField()Email com validação
FileField(upload_to='')Upload de arquivo
Relacionamentos
author = models.ForeignKey( User, on_delete=models.CASCADE ) tags = models.ManyToManyField(Tag, blank=True) profile = models.OneToOneField(User, on_delete=models.CASCADE)
Meta e Métodos
class Meta: ordering = ['-created'] verbose_name_plural = 'posts' def __str__(self): return self.title
Views
View Baseada em Função
from django.shortcuts import render, get_object_or_404 def post_list(request): posts = Post.objects.filter(published=True) return render(request, 'blog/list.html', {'posts': posts})
Views Baseadas em Classe
from django.views.generic import ListView, DetailView class PostListView(ListView): model = Post template_name = 'blog/list.html' context_object_name = 'posts' paginate_by = 10
CBVs Comuns
ListViewExibir lista de objetos
DetailViewExibir objeto único
CreateViewFormulário para criar objeto
UpdateViewFormulário para editar objeto
DeleteViewConfirmar e excluir objeto
TemplateViewRenderizar template (sem model)
Resposta JSON
from django.http import JsonResponse def api_posts(request): data = list(Post.objects.values('id', 'title')) return JsonResponse(data, safe=False)
Templates
Sintaxe de Template
{{ variable }} {{ post.title|truncatewords:30 }} {% if user.is_authenticated %}

Welcome, {{ user.username }}!

{% endif %}
Laços e Condicionais
{% for post in posts %}

{{ post.title }}

{% if forloop.last %}
{% endif %} {% empty %}

No posts yet.

{% endfor %}
Herança de Template
{# base.html #} {% block content %}{% endblock %} {# child.html #} {% extends "base.html" %} {% block content %}

Hello

{% endblock %}
Filtros Comuns
|date:"Y-m-d"Formatar data
|default:"N/A"Fallback para valores vazios
|lengthContar itens na lista
|truncatewords:NLimitar a N palavras
|safeMarcar como HTML seguro (sem escape)
|slugifyString em letras minúsculas segura para URL
URLs
Padrões de URL
from django.urls import path, include urlpatterns = [ path('', views.index, name='index'), path('post//', views.detail, name='detail'), path('blog/', include('blog.urls')), ]
Conversores de Caminho
<int:pk>Inteiro (ex.: 42)
<str:slug>String sem barras
<slug:slug>Slug (letras, números, hífens)
<uuid:id>Formato UUID
<path:rest>Caminho completo incluindo barras
URLs Reversas
from django.urls import reverse url = reverse('detail', kwargs={'pk': 1}) # In templates: {% url 'detail' pk=post.pk %}
Formulários
Model Form
from django import forms class PostForm(forms.ModelForm): class Meta: model = Post fields = ['title', 'body', 'published']
Processar Formulário na View
def create_post(request): form = PostForm(request.POST or None) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.save() return redirect('detail', pk=post.pk) return render(request, 'blog/form.html', {'form': form})
Formulário no Template
{% csrf_token %} {{ form.as_p }}
Validação
def clean_title(self): title = self.cleaned_data['title'] if len(title) < 5: raise forms.ValidationError("Title too short.") return title
Admin
Registrar Model
from django.contrib import admin from .models import Post @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ['title', 'author', 'created', 'published'] list_filter = ['published', 'created'] search_fields = ['title', 'body']
Opções do Admin
list_displayColunas na visualização em lista
list_filterOpções de filtro na barra lateral
search_fieldsCampos pesquisáveis
prepopulated_fieldsAuto-preencher (ex.: slug a partir do título)
readonly_fieldsNão editável no admin
orderingOrdenação padrão
Queries ORM
Queries Básicas
Post.objects.all() # todos os registros Post.objects.get(pk=1) # único (lança exceção se ausente) Post.objects.filter(published=True) # queryset Post.objects.exclude(draft=True) # excluir correspondências Post.objects.count() # total
Lookups de Campo
field__exactCorrespondência exata (padrão)
field__icontainsContém (case-insensitive)
field__gt / __ltMaior que / menor que
field__gte / __lteMaior/menor ou igual
field__in=[1,2,3]Valor na lista
field__isnull=TrueÉ NULL
field__startswithComeça com string
field__range=(a,b)Entre a e b inclusive
Encadeamento e Agregação
from django.db.models import Q, Count, Avg Post.objects.filter( Q(title__icontains='django') | Q(body__icontains='django') ).order_by('-created')[:10] Post.objects.aggregate(avg_views=Avg('views'))
Criar, Atualizar, Excluir
post = Post.objects.create(title='New', body='...') post.title = 'Updated' post.save() Post.objects.filter(draft=True).update(published=False) post.delete()
Autenticação
Login / Logout
from django.contrib.auth import authenticate, login, logout user = authenticate(request, username='admin', password='pw') if user is not None: login(request, user)
Proteger Views
from django.contrib.auth.decorators import login_required @login_required def dashboard(request): return render(request, 'dashboard.html')
URLs de Auth
# urls.py path('accounts/', include('django.contrib.auth.urls')) # Provides: login, logout, password_change, password_reset
Auth no Template
{% if user.is_authenticated %}

Hi, {{ user.username }}

Logout {% else %} Login {% endif %}
Configurações
Configurações Principais
DEBUGTrue para dev, False para produção
ALLOWED_HOSTSLista de hostnames válidos
SECRET_KEYChave de assinatura criptográfica (manter secreta)
DATABASESEngine, nome, host e credenciais do banco
INSTALLED_APPSLista de apps registrados
STATIC_URLPrefixo de URL para arquivos estáticos
MEDIA_URL / MEDIA_ROOTCaminhos para arquivos enviados por usuários
Configuração de Banco de Dados
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mydb', 'USER': 'dbuser', 'HOST': 'localhost', 'PORT': '5432', } }
Arquivos Estáticos
STATIC_URL = '/static/' STATICFILES_DIRS = [BASE_DIR / 'static'] # In templates: {% load static %} #