Web - Full Stack Compressed
Web - Full Stack Compressed
https://www.notion.so/Web-Full-Stack-12f6cf8ea89f8009ab39cb5078877c20?pvs=4
Teoria
Web Full-Stack 1
Configurações iniciais
Primeiro devemos criar o ambiente virtual:
# Criar
# Linux
python3 -m venv venv
# Windows
python -m venv venv
#Ativar
# Linux
source venv/bin/activate
# Windows
venv\Scripts\Activate
# Caso algum comando retorne um erro de permissão execute o código e tente novamente:
Ative o auto-save
INSTALE O APP!
Web Full-Stack 2
Noivos
Em URL’s redirecione para o app criado:
path('noivos/', include('noivos.urls')),
urlpatterns = [
path('', views.home, name='home'),
]
def home(request):
if request.method == "GET":
return render(request, 'home.html')
import os
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'templates/static'),)
STATIC_ROOT = os.path.join('static')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<title>Eu.Noiva</title>
</head>
<body>
{% block 'body' %} {% endblock %}
<div class="absolute inset-x-0 top-10 -z-10 flex transform-gpu justify-center overflow-hidden blur-3xl"
aria-hidden="true">
<div class="aspect-[1108/632] w-[69.25rem] flex-none bg-gradient-to-r from-pink-400 to-purple-600 opacity-20"
style="clip-path: polygon(43% 17%, 38% 52%, 84% 75%, 68% 21%, 41% 80%, 94% 35%, 17% 29%, 23% 73%, 92% 54%, 62% 83%, 29% 14%, 33% 74%, 3% 57%, 53%
</div>
</div>
</body>
</html>
Voltando ao home.html:
{% extends "base.html" %}
{% block 'body' %}
<div class="max-w-7xl mx-auto mt-12">
<div class="grid grid-cols-2 gap-4">
<div class="bg-slate-200/20 p-6 rounded-md">
<div class="w-full">
<label class="mt-4 block text-sm leading-6 text-gray-900">Preço estimado</label>
<input type="number" name="preco" class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring
</div>
</div>
<div class="w-full">
<label class="mt-4 block text-sm leading-6 text-gray-900">importancia</label>
Web Full-Stack 3
<input type="range" min='1' max="5" name="importancia" class="block w-full py-3 text-gray-900">
</div>
<div class="w-full">
<input type="submit" class="rounded-md w-full mt-4 bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-ind
</div>
</div>
</form>
</div>
<div class="mx-auto">
</div>
</div>
<div>
<span class="inline-flex items-center rounded-md bg-green-400/10 px-2 py-1 text-xs font-medium text-green-400 ring-1 ring-inset ring-green-400
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</span>
</div>
</div>
</div>
{% endblock %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('myChart');
new Chart(ctx, {
type: 'pie',
data: {
labels: ['Não reservado', 'Reservado'],
datasets: [{
label: 'Presentes',
data: [5, 6],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
</script>
{% load static %}
<nav class="bg-slate-100">
<div class="mx-auto max-w-7xl">
<div class="relative flex h-16 items-center justify-between">
Web Full-Stack 4
</div>
</div>
</div>
</div>
</div>
</nav>
{% include "partials/navbar.html" %}
https://drive.google.com/drive/folders/14T6RrxyVd7ExrYUNRTQjEJJ5qYtcmfEE?usp=sharing
Em templates/static/noivos/img adicione todas as imagens acima.
{% static 'noivos/img/logo.webp' %}
Presentes
Crie uma tabela para os presente:
class Presentes(models.Model):
nome_presente = models.CharField(max_length=100)
foto = models.ImageField(upload_to='presentes')
preco = models.DecimalField(max_digits=6, decimal_places=2)
importancia = models.PositiveIntegerField()
reservado = models.BooleanField(default=False)
def __str__(self):
return self.nome_presente
Execute as migrações
def home(request):
if request.method == "GET":
presentes = Presentes(
nome_presente = nome_presente,
foto = foto,
preco = preco,
importancia=importancia,
)
presentes.save()
return redirect('home')
presentes = Presentes.objects.all()
return render(request, 'home.html', {'presentes': presentes})
Web Full-Stack 5
</span>
{% elif presente.importancia < 4 %}
<span class="inline-flex items-center rounded-md bg-orange-400/10 px-2 py-1 text-xs font-medium text-orange-400 ring-1 ring-inset ring-orange-400/30">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</span>
{% else %}
<span class="inline-flex items-center rounded-md bg-red-400/10 px-2 py-1 text-xs font-medium text-red-400 ring-1 ring-inset ring-red-400/30">Muito imp
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</span>
{% endif %}
</div>
{% endfor %}
urlpatterns = [
path('admin/', admin.site.urls),
path('noivos/', include('noivos.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Lista de convidados
Crie a URL para lista de convidados:
def lista_convidados(request):
if request.method == 'GET':
return render(request, 'lista_convidados.html')
Crie o HTML:
{% extends "base.html" %}
{% load static %}
{% block 'body' %}
<div class="max-w-7xl mx-auto mt-12">
<div class="grid gap-4 grid-cols-2">
<div class="bg-slate-200/20 p-6 rounded-md">
<form action="{% url 'lista_convidados' %}" method="POST">{% csrf_token %}
<h2 class="text-balance text-xl font-semibold tracking-tight text-gray-900">Cradastre seus convidados</h2>
<br>
<label class="mt-4 block text-sm leading-6 text-gray-900">Nome do convidado</label>
<input type="text" name="nome_convidado" class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gr
<div>
<ul role="list" class="divide-y divide-gray-100">
{% for convidado in convidados %}
<li class="flex items-center justify-between gap-x-6 py-5">
<div class="flex min-w-0 gap-x-4">
<img class="h-12 w-12 flex-none rounded-full bg-gray-50" src="{% static 'noivos/img/default.png' %}" alt="">
<div class="min-w-0 flex-auto">
<p class="text-sm font-semibold leading-6 text-gray-900">{{convidado.nome_convidado}}</p>
<p class="mt-1 truncate text-xs leading-5 text-gray-500">{{convidado.whatsapp}}</p>
<p class="mt-1 text-xs leading-5 text-gray-500">{{convidado.link_convite}}</p>
</div>
</div>
<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset {% if convidado.status == 'AC' %}text
</li>
{% endfor %}
</ul>
</div>
</div>
Web Full-Stack 6
</div>
{% endblock %}
Atualize a navbar:
<a href="{% url 'lista_convidados' %}" class="rounded-md px-3 py-2 text-sm font-medium text-gray-900 hover:bg-gray-700 hover:text-white">Convidados</a>
class Convidados(models.Model):
status_choices = (
('AC', 'Aguardando confirmação'),
('C', 'Confirmado'),
('R', 'Recusado')
)
nome_convidado = models.CharField(max_length=100)
whatsapp = models.CharField(max_length=25, null=True, blank=True)
maximo_acompanhantes = models.PositiveIntegerField(default=0)
token = models.CharField(max_length=25)
status = models.CharField(max_length=2, choices=status_choices, default='AC')
Processe os dados:
def lista_convidados(request):
if request.method == 'GET':
convidados = Convidados.objects.all()
return render(request, 'lista_convidados.html', {'convidados': convidados})
elif request.method == 'POST':
nome_convidado = request.POST.get('nome_convidado')
whatsapp = request.POST.get('whatsapp')
maximo_acompanhantes = int(request.POST.get('maximo_acompanhantes'))
convidados = Convidados(
nome_convidado=nome_convidado,
whatsapp=whatsapp,
maximo_acompanhantes=maximo_acompanhantes
)
convidados.save()
return redirect('lista_convidados')
Convidado
Crie um app para os convidados:
Instale o APP
path('convidados/', include('convidados.urls'))
urlpatterns = [
path('', views.convidados, name='convidados'),
]
def convidados(request):
token = request.GET.get('token')
convidado = Convidados.objects.get(token=token)
presentes = Presentes.objects.filter(reservado=False).order_by('-importancia')
return render(request, 'convidados.html', {'convidado': convidado, 'presentes': presentes, 'token': token})
@property
def link_convite(self):
Web Full-Stack 7
return f'http://127.0.0.1:8000{reverse("convidados")}?token={self.token}'
Crie o convidados.html
{% extends "base.html" %}
{% block 'body' %}
<div class="max-w-7xl mx-auto mt-12">
<div class="mx-auto max-w-2xl text-center">
<p class="mt-2 text-lg leading-8 text-gray-600">Confirme sua presença no casamento: <a href="" class="text-green-400">confirmar</a>, <a href="" cl
</div>
<br>
<hr>
<a href="" class="rounded-md block w-full mt-4 bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-ind
</div>
{% endfor %}
</div>
</div>
</li>
<br>
</ul>
</div>
</div>
</div>
{% endblock %}
Web Full-Stack 8
path('responder_presenca/', views.responder_presenca, name='responder_presenca'),
def responder_presenca(request):
resposta = request.GET.get('resposta')
token = request.GET.get('token')
convidado = Convidados.objects.get(token=token)
if resposta not in ['C', 'R']:
messages.add_message(request, constants.ERROR, 'Você deve confirmar ou recusar')
return redirect(f'{reverse('convidados')}?token={token}')
convidado.status = resposta
convidado.save()
return redirect(f'{reverse('convidados')}?token={token}')
No HTML adicione:
{% if convidado.status == 'AC' %}
<p class="mt-2 text-lg leading-8 text-gray-600">Confirme sua presença no casamento: <a href="{% url 'responder_presenca' %}?resposta=C&token={{token}}" cl
{% endif %}
Reservar presente
Crie uma URL para reservar o presente:
convidado = Convidados.objects.get(token=token)
presente = Presentes.objects.get(id=id)
presente.reservado=True
presente.reservado_por = convidado
presente.save()
return redirect(f'{reverse('convidados')}?token={token}')
Reserve o presente:
<a href="{% url 'reservar_presente' presente.id %}?token={{token}}" class="rounded-md block w-full mt-4 bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold tex
nao_reservado = Presentes.objects.filter(reservado=False).count()
reservado = Presentes.objects.filter(reservado=True).count()
E altere no JS
data: {{data|safe}},
Web Full-Stack 9