Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Criação de App de Módulos de aulas close #39 #40

Merged
merged 1 commit into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ django-s3-folder-storage = "*"
collectfast = "*"
django-debug-toolbar = "*"
sentry-sdk = "*"
django-ordered-model = "*"
python-slugify = "*"

[dev-packages]
flake8 = "*"
Expand Down
505 changes: 283 additions & 222 deletions Pipfile.lock

Large diffs are not rendered by default.

Empty file added pypro/base/__init__.py
Empty file.
65 changes: 39 additions & 26 deletions pypro/base/templates/base/base.html
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
<!DOCTYPE html>
{% load static %}
<html lang="pt-br">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Python Pro{% endblock title %}</title>
<meta name="description" content="{% block description %}Página do curso Python Pro{% endblock description %}">
<meta name="author" content="Matheus Lopes">
<head>
<meta charset="utf-8">
<meta content="IE=edge" http-equiv="X-UA-Compatible">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>{% block title %}Python Pro{% endblock title %}</title>
<meta content="{% block description %}Página do curso Python Pro{% endblock description %}" name="description">
<meta content="Matheus Lopes" name="author">

<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
<link href="{% static 'img/favicon.png' %}" rel="icon" type="image/png"/>

<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'css/style.css' %}" rel="stylesheet">
<script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/scripts.js' %}"></script>
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'css/style.css' %}" rel="stylesheet">
<script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/scripts.js' %}"></script>

</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="{% url 'base:home' %}">Python Pro</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
</ul>
</div>
</nav>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="{% url 'base:home' %}">Python Pro</a>
<button aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler"
data-target="#navbarSupportedContent" data-toggle="collapse" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a aria-expanded="false" aria-haspopup="true" class="nav-link dropdown-toggle" data-toggle="dropdown" href="#"
id="navbarDropdown" role="button">
Módulos
</a>
<div aria-labelledby="navbarDropdown" class="dropdown-menu">
{% for modulo in MODULOS %}
<a class="dropdown-item" href="{{modulo.get_absolute_url}}">{{modulo.titulo}}</a>
<div class="dropdown-divider"></div>
{% endfor %}
</div>
</li>
</ul>
</div>
</nav>

{% block body %} {% endblock body %}

{% include 'base/footer.html' with contato_email='[email protected]' only %}

</body>
</body>
</html>
2 changes: 1 addition & 1 deletion pypro/base/tests/test_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


@pytest.fixture
def resp(client):
def resp(client, db):
resp = client.get(reverse('base:home'))
return resp

Expand Down
2 changes: 1 addition & 1 deletion pypro/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@


def home(request):
return render(request, 'base/home.html',)
return render(request, 'base/home.html', {})
Empty file added pypro/modulos/__init__.py
Empty file.
10 changes: 10 additions & 0 deletions pypro/modulos/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.contrib import admin
from ordered_model.admin import OrderedModelAdmin

from pypro.modulos.models import Modulo


@admin.register(Modulo)
class ModuloAdmin(OrderedModelAdmin):
list_display = ('titulo', 'publico', 'move_up_down_links')
prepopulated_fields = {'slug': ('titulo',)}
6 changes: 6 additions & 0 deletions pypro/modulos/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class ModulosConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "pypro.modulos"
5 changes: 5 additions & 0 deletions pypro/modulos/context_processors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pypro.modulos import facade


def listar_modulos(request):
return {'MODULOS': facade.listar_modulos_ordenados()}
16 changes: 16 additions & 0 deletions pypro/modulos/facade.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import List

from pypro.modulos.models import Modulo


def listar_modulos_ordenados() -> List[Modulo]:
"""

Lista módulos ordenados por títulos
:return:
"""
return list(Modulo.objects.order_by('order').all())


def encontrar_modulo(slug: str) -> Modulo:
return Modulo.objects.get(slug=slug)
40 changes: 40 additions & 0 deletions pypro/modulos/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 4.2.6 on 2023-10-07 13:42

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = []

operations = [
migrations.CreateModel(
name="Modulo",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"order",
models.PositiveIntegerField(
db_index=True, editable=False, verbose_name="order"
),
),
("titulo", models.CharField(max_length=64)),
("publico", models.TextField()),
("descricao", models.TextField()),
],
options={
"ordering": ("order",),
"abstract": False,
},
),
]
18 changes: 18 additions & 0 deletions pypro/modulos/migrations/0002_modulo_slug.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.6 on 2023-10-07 15:20

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("modulos", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="modulo",
name="slug",
field=models.SlugField(null=True),
),
]
21 changes: 21 additions & 0 deletions pypro/modulos/migrations/0003_populando_slug.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.2.6 on 2023-10-07 15:25

from django.db import migrations
from django.utils.text import slugify


def popular_slug(apps, schema_editor):
Modulo = apps.get_model('modulos', 'Modulo')
for modulo in Modulo.objects.all():
modulo.slug = slugify(modulo.titulo)
modulo.save()


class Migration(migrations.Migration):
dependencies = [
("modulos", "0002_modulo_slug"),
]

operations = [
migrations.RunPython(popular_slug)
]
18 changes: 18 additions & 0 deletions pypro/modulos/migrations/0004_slug_unico_e_nao_nulo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.6 on 2023-10-07 15:33

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("modulos", "0003_populando_slug"),
]

operations = [
migrations.AlterField(
model_name="modulo",
name="slug",
field=models.SlugField(unique=True),
),
]
Empty file.
19 changes: 19 additions & 0 deletions pypro/modulos/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from django.db import models
from django.urls.base import reverse
from ordered_model.models import OrderedModel


class Modulo(OrderedModel):
titulo = models.CharField(max_length=64)
publico = models.TextField()
descricao = models.TextField()
slug = models.SlugField(unique=True)

class Meta(OrderedModel.Meta):
pass

def __str__(self):
return self.titulo

def get_absolute_url(self):
return reverse('modulos:detalhe', kwargs={'slug': self.slug})
20 changes: 20 additions & 0 deletions pypro/modulos/templates/modulos/modulo_detalhe.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{% extends 'base/base.html' %}
{% load static %}
{% block title %}{{modulo.titulo}}{% endblock title %}
{% block description %}Página com detalhes do módulo {{modulo.titulo}}{% endblock description %}
{% block body %}
<div class="container">
<div class="row">
<div class="col-md-12">
<h1 class="mt-4 mb-3">{{ modulo.titulo }}</h1>
<dl>
<dt>Público</dt>
<dd>{{ modulo.publico }}</dd>
<dt>Descrição</dt>
<dd>{{ modulo.descricao }}</dd>
</dl>
</div>
</div>
</div>
{% endblock body %}

Empty file added pypro/modulos/tests/__init__.py
Empty file.
27 changes: 27 additions & 0 deletions pypro/modulos/tests/test_aba_de_modulos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import pytest
from django.urls import reverse
from pypro.django_assertions import assert_contains
from model_mommy import mommy

from pypro.modulos.models import Modulo


@pytest.fixture
def modulos(db):
return mommy.make(Modulo, 2)


@pytest.fixture
def resp(client, modulos):
resp = client.get(reverse('base:home'))
return resp


def test_titulos_dos_modulos(resp, modulos):
for modulo in modulos:
assert_contains(resp, modulo.titulo)


def test_link_dos_modulos(resp, modulos):
for modulo in modulos:
assert_contains(resp, modulo.get_absolute_url())
14 changes: 14 additions & 0 deletions pypro/modulos/tests/test_facade.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest
from model_mommy import mommy

from pypro.modulos import facade
from pypro.modulos.models import Modulo


@pytest.fixture
def modulos(db):
return [mommy.make(Modulo, titulo=s) for s in 'Antes Depois'.split()]


def test_listar_modulos_ordenados(modulos):
assert list(sorted(modulos, key=lambda modulo: modulo.order)) == facade.listar_modulos_ordenados()
29 changes: 29 additions & 0 deletions pypro/modulos/tests/test_modulo_detalhe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import pytest
from django.urls import reverse
from pypro.django_assertions import assert_contains
from model_mommy import mommy

from pypro.modulos.models import Modulo


@pytest.fixture
def modulo(db):
return mommy.make(Modulo)


@pytest.fixture
def resp(client, modulo):
resp = client.get(reverse('modulos:detalhe', kwargs={'slug': modulo.slug}))
return resp


def test_titulo(resp, modulo: Modulo):
assert_contains(resp, modulo.titulo)


def test_descricao(resp, modulo: Modulo):
assert_contains(resp, modulo.descricao)


def test_publico(resp, modulo: Modulo):
assert_contains(resp, modulo.publico)
8 changes: 8 additions & 0 deletions pypro/modulos/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.urls import path

from pypro.modulos import views

app_name = 'modulos'
urlpatterns = [
path('<slug:slug>', views.detalhe, name='detalhe'),
]
8 changes: 8 additions & 0 deletions pypro/modulos/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.shortcuts import render

from pypro.modulos import facade


def detalhe(request, slug):
modulo = facade.encontrar_modulo(slug)
return render(request, 'modulos/modulo_detalhe.html', {'modulo': modulo})
3 changes: 3 additions & 0 deletions pypro/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
'django.contrib.staticfiles',
'pypro.base',
'pypro.aperitivos',
'pypro.modulos',
'ordered_model',
]

MIDDLEWARE = [
Expand All @@ -71,6 +73,7 @@
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'pypro.modulos.context_processors.listar_modulos',
],
},
},
Expand Down
Loading
Loading