Merge branch 'crispy-forms' into 'master'

Crispy forms

See merge request JustScreaMy/facturio!1
This commit is contained in:
Jakub Kropáček 2023-12-19 12:49:35 +00:00
commit 8bbfb6010c
21 changed files with 172 additions and 65 deletions

View file

@ -1,13 +1,29 @@
from crispy_forms import helper, layout
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from .models import User
# from .models import User # from .models import User
class LoginForm(AuthenticationForm): class LoginForm(AuthenticationForm):
pass def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = helper.FormHelper()
self.helper.form_action = "login"
self.helper.form_method = "post"
self.helper.add_input(layout.Submit('submit', 'Login'))
#
# class RegisterForm(UserCreationForm): class RegisterForm(UserCreationForm):
# class Meta(UserCreationForm.Meta): class Meta:
# model = User model = User
# fields = UserCreationForm.Meta.fields fields = UserCreationForm.Meta.fields + ("first_name", "last_name", "email")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = helper.FormHelper()
self.helper.form_action = "register"
self.helper.form_method = "post"
self.helper.add_input(layout.Submit('submit', 'Register'))

View file

@ -0,0 +1,27 @@
# Generated by Django 5.0 on 2023-12-19 11:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("account", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name="user",
name="email",
field=models.EmailField(max_length=254, verbose_name="email address"),
),
migrations.AlterField(
model_name="user",
name="first_name",
field=models.CharField(max_length=150, verbose_name="first name"),
),
migrations.AlterField(
model_name="user",
name="last_name",
field=models.CharField(max_length=150, verbose_name="last name"),
),
]

View file

@ -1,5 +1,14 @@
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import gettext_lazy as _
class User(AbstractUser): class User(AbstractUser):
pass REQUIRED_FIELDS = ["email", "first_name", "last_name"]
first_name = models.CharField(_("first name"), max_length=150)
last_name = models.CharField(_("last name"), max_length=150)
email = models.EmailField(_("email address"))
class Meta(AbstractUser.Meta):
pass

View file

@ -1,32 +1,9 @@
{% extends "facturio/base.html" %} {% extends "facturio/base.html" %}
{% load crispy_forms_tags %}
{% block title %}Login{% endblock %} {% block title %}Login{% endblock %}
{% block content %} {% block content %}
<div class="container mt-5"> {% crispy form form.helper %}
<form class="col-md-6 offset-md-3" action="{% url 'login' %}" method="post">
{% csrf_token %}
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" name="username" id="username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" name="password" id="password" required>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
{# <form class="col-md-6 offset-md-3" action="{% url 'login' %}" method="post">#}
{# {% csrf_token %}#}
{# <div class="mb-3">#}
{# <label for="username" class="form-label">Username</label>#}
{# <input type="text" class="form-control" name="username" id="username" required>#}
{# </div>#}
{# <div class="mb-3">#}
{# <label for="password" class="form-label">Password</label>#}
{# <input type="password" class="form-control" name="password" id="password" required>#}
{# </div>#}
{# <button type="submit" class="btn btn-primary">Login</button>#}
{# </form>#}
</div>
{% endblock %} {% endblock %}

View file

@ -6,10 +6,11 @@
<div class="container mt-4"> <div class="container mt-4">
<h2 class="mb-4">About Me</h2> <h2 class="mb-4">About Me</h2>
<div class="card"> <div class="card">
<div class="card-body"> <h5 class="card-header">Welcome, {{ request.user.first_name }} {{ request.user.last_name }}!</h5>
<h5 class="card-title">Welcome, {{ request.user.username }}!</h5> <ul class="list-group list-group-flush">
<p class="card-text">Email: {{ request.user.email }}</p> <li class="list-group-item">Username: {{ request.user.username }}</li>
</div> <li class="list-group-item">Email: {{ request.user.email }}</li>
</ul>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,5 +1,10 @@
{% extends "facturio/base.html" %} {% extends "facturio/base.html" %}
{% load crispy_forms_tags %}
{% block title %}Register{% endblock %} {% block title %}Register{% endblock %}
{% block content %} {% block content %}
<h1>TODO: register</h1> {# TODO: neukazovat všechny pičoviny hned najedou#}
{% crispy form form.helper %}
{% endblock %} {% endblock %}

View file

@ -1,15 +1,15 @@
from django.conf import settings from django.conf import settings
from django.contrib.auth import login, logout from django.contrib.auth import login, logout
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.http import HttpRequest, HttpResponse, JsonResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect, render from django.shortcuts import redirect, render, reverse
from . import forms from . import forms
def auth_login(req: HttpRequest) -> HttpResponse: def auth_login(req: HttpRequest) -> HttpResponse:
if req.method == "POST": if req.method == "POST":
form = forms.LoginForm(req, req.POST) form = forms.LoginForm(data=req.POST)
if not form.is_valid(): if not form.is_valid():
return render(req, "account/login.html", dict(form=form)) return render(req, "account/login.html", dict(form=form))
@ -21,8 +21,7 @@ def auth_login(req: HttpRequest) -> HttpResponse:
return redirect(redirect_url) return redirect(redirect_url)
elif req.method == "GET": elif req.method == "GET":
form = forms.LoginForm()
form = forms.LoginForm(req)
return render(req, "account/login.html", dict(form=form)) return render(req, "account/login.html", dict(form=form))
return HttpResponse(status=405) return HttpResponse(status=405)
@ -35,7 +34,23 @@ def auth_logout(req: HttpRequest) -> HttpResponse:
def auth_register(req: HttpRequest) -> HttpResponse: def auth_register(req: HttpRequest) -> HttpResponse:
return render(req, "account/register.html") if req.user.is_authenticated:
return redirect(reverse("me"))
if req.method == "POST":
form = forms.RegisterForm(data=req.POST)
if not form.is_valid():
return render(req, "account/register.html", dict(form=form))
user = form.save()
login(req, user)
return redirect(settings.LOGIN_BASE_URL)
elif req.method == "GET":
form = forms.RegisterForm()
return render(req, "account/register.html", dict(form=form))
return HttpResponse(status=405)
@login_required @login_required

View file

@ -35,7 +35,10 @@ INSTALLED_APPS = [
"django.contrib.sessions", "django.contrib.sessions",
"django.contrib.messages", "django.contrib.messages",
"django.contrib.staticfiles", "django.contrib.staticfiles",
"account.apps.AccountConfig" "crispy_forms",
"crispy_bootstrap5",
"account.apps.AccountConfig",
"subjects.apps.SubjectsConfig"
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -124,3 +127,8 @@ LOGOUT_REDIRECT_URL = f"/"
LOGIN_REDIRECT_URL = f"{LOGIN_BASE_URL}/me" LOGIN_REDIRECT_URL = f"{LOGIN_BASE_URL}/me"
AUTH_USER_MODEL = "account.User" AUTH_USER_MODEL = "account.User"
# Crispy config
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"

View file

@ -15,20 +15,17 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin from django.contrib import admin
# TODO: remove
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
from django.urls import path, include from django.urls import path, include
# TODO: remove def landing_page(req: HttpRequest) -> HttpResponse:
def demo(req: HttpRequest) -> HttpResponse: return render(req, "facturio/index.html")
return render(req, "facturio/invoice.html")
urlpatterns = [ urlpatterns = [
path("", demo, name="main-page"), path("", landing_page, name="main-page"),
path("account/", include("account.urls")), path("account/", include("account.urls")),
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
] ]

34
poetry.lock generated
View file

@ -14,6 +14,24 @@ files = [
[package.extras] [package.extras]
tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
[[package]]
name = "crispy-bootstrap5"
version = "2023.10"
description = "Bootstrap5 template pack for django-crispy-forms"
optional = false
python-versions = ">=3.8"
files = [
{file = "crispy-bootstrap5-2023.10.tar.gz", hash = "sha256:f16c44f1997310e5a89c0cf230402e7111cc1f942f64fb7e44603958b89b06a1"},
{file = "crispy_bootstrap5-2023.10-py3-none-any.whl", hash = "sha256:9b5a6c9880f37cd32aa678c0d7576ae60b3e502c444c8712e582f8bd91659afb"},
]
[package.dependencies]
django = ">=4.2"
django-crispy-forms = ">=2"
[package.extras]
test = ["pytest", "pytest-django"]
[[package]] [[package]]
name = "django" name = "django"
version = "5.0" version = "5.0"
@ -34,6 +52,20 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""}
argon2 = ["argon2-cffi (>=19.1.0)"] argon2 = ["argon2-cffi (>=19.1.0)"]
bcrypt = ["bcrypt"] bcrypt = ["bcrypt"]
[[package]]
name = "django-crispy-forms"
version = "2.1"
description = "Best way to have Django DRY forms"
optional = false
python-versions = ">=3.8"
files = [
{file = "django-crispy-forms-2.1.tar.gz", hash = "sha256:4d7ec431933ad4d4b5c5a6de4a584d24613c347db9ac168723c9aaf63af4bb96"},
{file = "django_crispy_forms-2.1-py3-none-any.whl", hash = "sha256:d592044771412ae1bd539cc377203aa61d4eebe77fcbc07fbc8f12d3746d4f6b"},
]
[package.dependencies]
django = ">=4.2"
[[package]] [[package]]
name = "sqlparse" name = "sqlparse"
version = "0.4.4" version = "0.4.4"
@ -64,4 +96,4 @@ files = [
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.12" python-versions = "^3.12"
content-hash = "1c6ab57fc89858a0923620d3307e9173662bad9b58d9dde4f567267506e03587" content-hash = "a3eaa3850f93a5b33da70f1d4831d68ee7593e05e7a0e040de0cc09229be92fd"

View file

@ -9,6 +9,8 @@ readme = "README.md"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.12" python = "^3.12"
django = "^5.0" django = "^5.0"
crispy-bootstrap5 = "^2023.10"
django-crispy-forms = "^2.1"
[build-system] [build-system]

0
subjects/__init__.py Normal file
View file

3
subjects/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
subjects/apps.py Normal file
View file

@ -0,0 +1,6 @@
from django.apps import AppConfig
class SubjectsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "subjects"

View file

3
subjects/models.py Normal file
View file

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

3
subjects/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

3
subjects/views.py Normal file
View file

@ -0,0 +1,3 @@
# Create your views here.
ARES_BASE_URL = "https://wwwinfo.mfcr.cz/cgi-bin/ares/darv_rzp.cgi?ico=27074358&xml=0&ver=1.0.4"

View file

@ -9,26 +9,25 @@
<body> <body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="#">Facturio</a> <a class="navbar-brand" href="{% url "main-page" %}">Facturio</a>
<!-- Left-aligned items -->
<div class="collapse navbar-collapse" id="navbarLeft"> <div class="collapse navbar-collapse" id="navbarLeft">
<ul class="navbar-nav"> <ul class="navbar-nav">
<!-- Additional items on the left --> {#<li class="nav-item">#}
<li class="nav-item"> {# <a class="nav-link" href="#">Item 1</a>#}
<a class="nav-link" href="#">Item 1</a> {#</li>#}
</li> {#<li class="nav-item">#}
<li class="nav-item"> {# <a class="nav-link" href="#">Item 2</a>#}
<a class="nav-link" href="#">Item 2</a> {#</li>#}
</li>
<!-- Add more items as needed -->
</ul> </ul>
</div> </div>
<!-- Right-aligned login/logout links --> <div class="collapse navbar-collapse justify-content-end">
<div class="collapse navbar-collapse justify-content-end" id="navbarRight">
<ul class="navbar-nav"> <ul class="navbar-nav">
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'me' %}">Profile</a>
</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}">Logout</a> <a class="nav-link" href="{% url 'logout' %}">Logout</a>
</li> </li>

View file

@ -0,0 +1,2 @@
{% extends "facturio/base.html" %}

View file

@ -1,4 +1,3 @@
<!-- Vaše faktura s aktualizacemi -->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="cs"> <html lang="cs">
<head> <head>