Django

Estrutura e sintaxe Django

Resumo em construção
Voltar

Material complementar:

  • Conteúdo no YouTube: Acesse
  • Conteúdo no GitHub: Acesse
  • Curso gratuito com certificado na Workover Academy (Curso de Django API REST): Acesse

Introdução

    Instalar Django:
  1. Pré-requisito (pip): sudo apt install python3-pip
  2. Instalar ecossistema Django: pip3 install django djangorestframework markdown django-filter django-cors-headers --break-system-packages
    Criar usuário Django admin (opcional):
  3. Cadastrar usuário no dashboard Django admin: python3 manage.py createsuperuser #Informar dados do usuário
  4. Acessar dashboard Django admin: localhost:8000/admin

  5. Iniciar projeto Django:
  6. Criar pasta do projeto: django-admin startproject nomePastaProjeto
  7. Na pasta do projeto, criar aplicação: python3 manage.py startapp nomeApp
  8. Em 'pastaApp/settings.py': Inserir o nome da App, conforme criado acima, como último elemento do array em INSTALLED_APPS
  9. Realizar a programação, com seu código
  10. Criar migrations: python3 manage.py makemigrations
  11. Executar migrations: python3 manage.py migrate
  12. Executar projeto: python3 manage.py runserver #Acesso padrão em localhost:8000

Estrutura



  • pastaProjeto/
    • pastaAplicacao/
      • migrations/ #Pasta com arquivos de interação com BD
      • admin.py #Configurações da interface administrativa (Registramento de usuários e Objetos para dashboard Django admin)
      • apps.py #Registramento da aplicação ao projeto
      • models.py #Models da aplicação (Classes de persistência)
      • tests.py #Testes automatizados da aplicação e regras sobre (Testes unitários, testes de regressão, testes de integração, etc). Pode-se criar diretórios 'tests/' para inserir mais arquivos dentro (Executar arquivos tests.py: 'python3 manage.py test' ou 'python3 manage.py test proj.pasta.arq')
      • views.py #Views da aplicação (Funções de tratamento de requisições, responsáveis por renderização do projeto)
      • (Criado manualmente) templates/ #Pasta com arquivos Html para frontend do projeto
      • (Criado manualmente) forms.py #Registramento de formulários de geração automática pelo Django
      • (Criado manualmente) urls.py #Arquivo secundário de rotas da aplicação
    • subPastaProjeto/
      • pychache/ #Pasta com arquivos de cache
      • __init.py__ #Módulo para marcar App como package do projeto
      • asgi.py #Integração entre servidores web compatíveis com ASGI e a App
      • settings.py #Configurações gerais do projeto (Configuração de host, BD, nome da App, etc)
      • urls.py #Rotas da aplicação, arquivo geral (Mapeamento de url relacionada com sua determinada Model)
      • wsgi.py #Integração entre servidores web WSGI e a App
    • manage.py #Responsável para execução dos comandos do framework

Funcionamento




settings.py:

Arquivo de configurações gerais do projeto.


from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = 'CHAVES' # Não seguro. Ideal informar a chave em variáveis de ambiente (arquivo .env) e referenciar aqui usando os.environ.get('SECRET_KEY')

DEBUG = True # True para projeto em desenvolvimento, False para produção
ALLOWED_HOSTS = [] # Lista de IPs ou domínios permitidos para acessar a aplicação

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'corsheaders',
    'nomeAppDoProjeto',
] # Lista de apps instalados no projeto, incluindo apps personalizados e de terceiros

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'corsheaders.middleware.CorsMiddleware',
] # Lista de middlewares usados no projeto, incluindo middlewares de segurança, autenticação e CORS


REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        #'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ),
    
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 2,
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '2/minute', #second,day,month,year
        'user': '3/minute'
    },
        'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',
    ]
} # Configurações do Django REST Framework para usar JSON como formato de entrada e saída, autenticação por token, permissões de leitura para não autenticados e paginação de resultados


CORS_ALLOW_ALL_ORIGINS = True # Permite que qualquer origem acesse API. Em produção, recomenda-se configurar CORS de forma mais restritiva usando CORS_ALLOWED_ORIGINS

ROOT_URLCONF = 'paris_cafe.urls' # Módulo de URLs raiz do projeto, onde rotas principais são definidas

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
] # Configurações de templates do Django, incluindo diretórios de templates e processadores de contexto

WSGI_APPLICATION = 'paris_cafe.wsgi.application' # Módulo WSGI do projeto, usado para implantação em servidores compatíveis com WSGI

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
} # Configurações de banco de dados, usando SQLite para desenvolvimento

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
] # Configurações de validação de senha para garantir senhas seguras

# Configurações de internacionalização e fuso horário:
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True

STATIC_URL = 'static/' # URL para servir arquivos estáticos (CSS, JavaScript, imagens)

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # Configuração para usar BigAutoField como tipo de campo padrão para chaves primárias em modelos, garantindo IDs únicos e escaláveis

MEDIA_URL = '/media/' # URL para servir arquivos de mídia enviados pelos usuários
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Diretório onde arquivos de mídia serão armazenados no sistema de arquivos do servidor

LOGIN_URL = '/login' # URL para página de login, onde usuários não autenticados serão redirecionados ao tentar acessar áreas protegidas do site
LOGIN_REDIRECT_URL = '/'
LOGOUT_URL = '/logout'
LOGOUT_REDIRECT_URL = '/login'

AUTHENTICATION_BACKENDS = [
    'social_core.backends.google.GoogleOAuth2',
    'social_core.backends.facebook.FacebookOAuth2',
    'django.contrib.auth.backends.ModelBackend',
]

SOCIAL_AUTH_FACEBOOK_EXTRA_DATA = [
    ('name', 'name'),
    ('email', 'email'),
    ('picture', 'picture'),
    ('link', 'profile_url'),
]

import django_heroku
django_heroku.settings(locals())

models.py:

Arquivo contendo Models da aplicação. Pode estar localizado em diretório chamado, models dentra da pasta da app, onde cada Model é arquivo cujo nome é mesmo da respectiva classe. Models são classes de persistência, responsável por representar tabela do banco de dados e seus campos. Cada atributo da classe representa campo da tabela (com suas características e condições), onde Django se encarrega de criar estrutura do banco de dados com base nessas definições. Models também podem incluir métodos para manipulação dos dados, como validação, formatação ou cálculos relacionados aos campos definidos. Exemplo de model (models/activity.py):


from django.db import models

class Activity(models.Model):
    strava_id = models.BigIntegerField(
        unique=True,
        help_text="ID da atividade no Strava",
    )
    name = models.CharField(
        max_length=255,
        help_text="Nome da atividade",
    )
    distance = models.FloatField(
        help_text="Distância em metros",
    )
    moving_time = models.PositiveIntegerField(
        help_text="Tempo em movimento (segundos)",
    )
    sport_type = models.CharField(
        max_length=50,
        help_text="Tipo de esporte (Run, Walk, Ride, etc)",
    )
    start_date = models.DateTimeField(
        help_text="Data/hora de início (UTC)",
    )
    average_speed = models.FloatField(
        null=True,
        blank=True,
        help_text="Velocidade média (m/s)",
    )

    created_at = models.DateTimeField(
        auto_now_add=True,
    )

    class Meta:
        ordering = ["-start_date"]
        verbose_name = "Atividade"
        verbose_name_plural = "Atividades"

    def __str__(self) -> str:
        return f"{self.name} - {self.distance / 1000:.2f} km"

Exemplo de Model com métodos (models/Profile.py):


from medicSearch.models import *
from django.db.models import Sum, Count

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    role = models.IntegerField(choices=ROLE_CHOICE, default=3)
    birthday = models.DateField(default=None, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    token = models.CharField(max_length=255, null=True, blank=True)
    image = models.ImageField(null=True, blank=True)
    favorites = models.ManyToManyField(User, blank=True, related_name='favorites')
    specialties = models.ManyToManyField(Speciality, blank=True, related_name='specialties')
    addresses = models.ManyToManyField(Address, blank=True, related_name='addresses')
    
    def __str__(self):
        return '{}'.format(self.user.username)

    @receiver(post_save, sender=User)
    def create_user_profile(sender, instance, created, **kwargs):
        try:
            if created:
                Profile.objects.create(user=instance)
        except:
            pass

    @receiver(post_save, sender=User)
    def save_user_profile(sender, instance, **kwargs):
        try:
            instance.profile.save()
        except:
            pass

    def show_scoring_average(self):
        from .Rating import Rating
        try:
            ratings = Rating.objects.filter(user_rated=self.user).aggregate(Sum('value'), Count('user'))
            if ratings['user__count'] > 0:
                scoring_average = ratings['value__sum'] / ratings['user__count']
                scoring_average = round(scoring_average, 2) # Arredondando o valor para duas casas decimais
                return scoring_average
            return 'Sem avaliações'
        except:
            return 'Sem avaliações'

    def show_favorites(self):
        ids = [result.id for result in self.favorites.all()]
        return Profile.objects.filter(user__id__in=ids)

    def show_ratings(self):
        from .Rating import Rating
        return Rating.objects.filter(user_rated=self.user)

Exemplo de Model com Meta (models/Profile.py):


from django.db import models

class Base(models.Model):
    criacao = models.DateTimeField(auto_now_add=True)
    atualizacao = models.DateTimeField(auto_now=True)
    ativo = models.BooleanField(default=True)
    
    class Meta:
        abstract = True

class Curso(Base):
    titulo = models.CharField(max_length=255)
    url = models.URLField(unique=True)

    class Meta:
        verbose_name = 'Curso'
        verbose_name_plural = 'Cursos'
        ordering = ['id']
        #Decrescente: ordering = ['-id']
    
    def __str__(self):
        return self.titulo

class Avaliacao(Base):
    curso = models.ForeignKey(Curso, related_name='avaliacoes', on_delete=models.CASCADE)
    nome = models.CharField(max_length=255)
    email = models.EmailField()
    comentario = models.TextField(blank=True, default='')
    avaliacao = models.DecimalField(max_digits=2, decimal_places=1)

    class Meta:
        verbose_name = 'Avaliação'
        verbose_name_plural = 'Avaliações'
        unique_together = ['email', 'curso']
        ordering = ['id']
    
    def __str__(self):
        return f'{self.nome} avaliou o curso {self.curso} com nota {self.avaliacao}'

Opcionalmente, alguns projetos possui models na pasta de models, onde há arquivo de inicialização e regras de negócio (__init__.py):


from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

ROLE_CHOICE = (
    (1, 'Admin'),
    (2, 'Médico'),
    (3, 'Paciente')
)

# Outras models desse projeto específico:
from .Rating import Rating
from .DayWeek import DayWeek
from .State import State
from .City import City
from .Neighborhood import Neighborhood
from .Address import Address
from .Speciality import Speciality
from .Profile import Profile

Rotas globais:

Arquivo de rotas globais do projeto, onde são mapeadas URLs para respectivas views, acessíveis a todo projeto. Geralmente localizado em pastaProjeto/urls.py. Exemplo:


from django.contrib import admin
from django.urls import path
from django.conf.urls.static import static
from django.conf import settings
from django.conf.urls import url, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('medicSearch.urls.HomeUrls')),
    path('', include('medicSearch.urls.AuthUrls')),
    path('profile/', include('medicSearch.urls.ProfileUrls')),
    path('medic/', include('medicSearch.urls.MedicUrls')),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Exemplo simples (pastaProjeto/urls.py):


from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('cafes.urls')), # Arquivo de rotas locais, da app 'cafes'
]

Exemplo, usando versionamento de APIs REST (pastaProjeto/urls.py):


from django.contrib import admin
from django.urls import path, include
from cursos.urls import router

urlpatterns = [
    path('api/v1/', include('cursos.urls')),
    path('api/v2/', include(router.urls)),
    path('admin/', admin.site.urls),
    path('auth/', include('rest_framework.urls')),
]

Exemplo, usando ViewSets (pastaProjeto/urls.py):


from django.urls import path
from .views import BookListCreateView, BookRetrieveUpdateDestroyView

urlpatterns = [
    path('books/', BookListCreateView.as_view(), name='book-list-create'),
    path('books/<int:pk>/', BookRetrieveUpdateDestroyView.as_view(), name='book-detail'),
]

Exemplo, usando JWT (pastaProjeto/urls.py):


from django.contrib import admin
from django.urls import path, include
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/auth/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
    path("api/auth/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
    path("api/", include("apps.activities.urls")),
]

Rotas locais:

Em breve...

Elaborado por Mateus Schwede
ubsocial.github.io