[TUTORIAL] SPA com Django é possível? Sim, e eu vou explicar como!
Django SPA (Single Page Application)
Quando utilizamos uma aplicação SPA, a fluidez que isso traz para o usuário é incrível, um exemplo de projeto utilizando django single page application,é o Instagram, para um iniciante se basear na aplicação do Instagram fica bem complicada, no entanto há uma outra forma de se criar uma aplicação django SPA com uma quantidade de linhas de código até menor e sem perder a interação com o seu usuário, sem a necessidade da utilização dos frameworks baseados em Java.
HTMX
HTMX - Documentation and references
Resumidamente com HTMX, a partir de qualquer parte do seu template, você podera fazer uma requisição e alterar um alvo para o contéudo renderizado por uma view, sem que haja a atualização de toda a página, podendo também utilizar um formulário para enviar requisições, exemplo:
Criando o projeto
$ mkdir Todos
$ cd Todos
$ python3 -m vritualenv env
$ source env/bin/activate
$ pip install django
$ django-admin startproject backend
$ cd backend
$ mkdir apps
$ cd apps
$ ../manage.py startapp todo
$ cd todo
$ mkdir -p static/js/htmx
$ mkdir -p templates/routers/pages
static/js/htmx/htmx.min.js
Crie um arquivo js com nome htmx.min.js copie e cole o código abaixo.
Código JS para HTMX
Estrutura do projeto
.
└── Todos/
└── backend/
├── apps/
│ └── todo/
│ ├── templates/
│ │ ├── base.html
│ │ └── routers/
│ │ └── pages/
│ │ ├── index.html
│ │ ├── about.html
│ │ └── contact.html
│ ├── static/
│ │ └── js/
│ │ └── htmx/
│ │ └── htmx.min.js
│ ├── urls.py
│ ├── apps.py
│ └── views.py
├── backend/
│ ├── settings.py
│ └── urls.py
└── manage.py
backend/settings.py
import os
INSTALLED_APPS = [
...
'apps.todo',
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')],
...
},
]
LANGUAGE_CODE = 'pt-br'
TIME_ZONE = 'America/Sao_Paulo'
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'static')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
backend/urls.py
from django.contrib import admin
from django.urls import path,include
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
#APPS
path('',include('apps.todo.urls')),
] + static(settings.STATIC_URL , document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL , document_root=settings.MEDIA_ROOT)
todo/apps.py
from django.apps import AppConfig
class CoreConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.todo'
todo/urls.py
from django.urls import path
from . import views
urlpatterns =[
path('',views.base, name="base"),
path('index/',views.index, name="index"),
path('about/',views.about, name="about"),
path('contact/',views.contact, name="contact"),
]
todo/template/base.hml
ANTEÇÃO, no atributo hx-get="" você poderá escolher uma das duas opções, utilizar metodo URL built-ins do django {% url '' %} ou utilizar o caminho escrito urls.py, qual seria esse caminho?
path('index/', views.index,name="index")
^-CAMINHO ^-URL UTILIZADA NO BUILT-INS
{% load static%}
<!DOCTYPE html>
<html lang="pt-br">
<head>
<title>Todo</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- HTMX -->
<script src="{% static 'js/htmx/htmx.min.js' %}"></script>
</head>
<body>
<nav>
<li
hx-get="{% url 'index'%} ou /index/"
hx-trigger="click"
hx-target="#MainPage"
hx-swap="outterHTML"
>
Index
</li>
<li
hx-get="{% url 'about'%} ou /about/"
hx-trigger="click"
hx-target="#MainPage"
hx-swap="outterHTML"
>
About
</li>
<li
hx-get="{% url 'contact'%} ou /contact/"
hx-trigger="click"
hx-target="#MainPage"
hx-swap="outterHTML"
>
Contact
</li>
</nav>
<main id="MainPage">
#RENDERIZAÇÃO OCORRERÁ AQUI
</main>
<!-- CSRF_TOKEN -->
<script>
document.body.addEventListener('htmx:configRequest', (event) =>
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}'
);
</script>
</body>
</html>
todo/views.py
from django.shortcuts import render
def base(request):
"""
BASE PARA TEMPLATES
"""
return render(request, 'base.html')
def index(request):
"""
Não necessita de uma verificação do tipo de requisição,
pois retornaremos apenas um layout
"""
return render(request,"routers/pages/index.html")
def about(request):
"""
Não necessita de uma verificação do tipo de requisição,
pois retornaremos apenas um layout
"""
return render(request,"routers/pages/about.html")
def contact(request):
"""
Não necessita de uma verificação do tipo de requisição,
pois retornaremos apenas um layout,neste caso para enviar
um formulário, deve-se criar outra view com um template próprio
para seu formulário.
"""
return render(request,"routers/pages/contact.html")
todo/templates/routers/pages/index.html
<div>
<h1> Index </h1>
</div>
todo/templates/routers/pages/about.html
<div>
<h1> About </h1>
</div>
todo/templates/routers/pages/contact.html
<div>
<h1> Contact </h1>
</div>
Em Todos/backend, utilizando o terminal, com o seu Virtual Enviroment ativo:
python manage.py migrate
python manage.py runserver
Está pronto, você tem uma página SPA.
Tudo bem pessoal?
Sou apenas um entusiasta da programação, e escolhi o python como minha linguagem de programação. Estou no começo de um grande caminho.
Minha história é complicada, estudo farmácia 5/10, e tenho vontade de migrar para a área da programação, ainda não consegui minha primeira vaga como DEV, mas estou correndo atrás.
Espero que gostem e aceito críticas construtivas, e dicas também, sempre com intuito de melhorar.
Eclesiastes 3
https://github.com/Ilopesr
https://www.linkedin.com/in/igorlopr/