Trzeba prze edytować 3 elementy klasę Form (opcjonalnie), View i Template. Koszty, dochód, i ZUS walidacje już nie rozpisuje w poniższym przykładzie bo nie chce już wnikać o co chodzi tam i jakie typy są itp.
Idziemy do deklaracja klasy form( pomijamy ten krok jeśli chcemy tylko ustawić miesiąc i rok na aktualny bez dodatkowych opcji):
np:
- jeśli chcemy aby był ustawiony aktualny miesiąc oraz użytkownik mógł dodatkowo wybrać inny miesiąc
- rok jest zawsze jest ustawiony na aktualny rok
from django import forms
from django.core.exceptions import ValidationError
class NowymiesiacForm(forms.Form):
# na sztywno field rok nie moze byc starszy niz ten aktualny - ustawiam minimalny rok jako aktualny
rok = forms.IntegerField(label="Rok", min_value=datetime.now().year)
miesiac = forms.ChoiceField(choices=[
(1, 'Styczeń'),
(2, 'Luty'),
(3, 'Marzec'),
(4, 'Kwiecień'),
(5, 'Maj'),
(6, 'Czerwiec'),
(7, 'Lipiec'),
(8, 'Sierpień'),
(9, 'Wrzesień'),
(10, 'Październik'),
(11, 'Listopad'),
(12, 'Grudzień'),
])
przychod = forms.DecimalField(label="Przychód", max_digits=10, decimal_places=2, validators=[validate_positive_decimal])
# robimy dodatkowa walidacje ( operujemy na wielu polach jednoczesnie)
def clean(self):
cleaned_data = super().clean()
rok = cleaned_data.get('rok')
miesiac = cleaned_data.get('miesiac')
if rok and miesiac:
if miesiac > 12 or miesiac < 1:
raise ValidationError("Nieprawidłowy miesiąc. Wprowadź wartość z zakresu 1-12.")
return cleaned_data
# Te walidatory mogą być przydatne do ponownego wykorzystania logiki walidacji pomiędzy różnymi typami pól.
def validate_positive_decimal(value):
if value <= 0:
raise ValidationError("Przychód musi być wartością dodatnią lub równa zero.")
# poniższy kod nie mma sensu bo jest ustawiona minimalna wartosc ale chce pokazac jak jeszcze mozna validować poszczególne fieldy
#możemy to zrobić za pomocą metody która waliduje nam poszczególny field
def clean_rok(self):
min_value = datetime.now().year
rok = cleaned_data.get('rok')
if rok < min_value:
raise ValidationError(
f'Rok (year) must be greater than or equal to the current year ({min_value}).'
)
return rok
Edytujemy view aby dodać nasz initial data
i ustawić aktualny rok i miesiąc jako wyświetlane default
.
from django.shortcuts import render, redirect
from .forms import NowymiesiacForm
from datetime import datetime
def nowy_miesiac(request):
# w zasadzie tylko potrzebujemy tego aby przekazać jako initial
rok_aktualny = datetime.now().year
miesiac_aktualny = datetime.now().month - 1 # index miesiaca startuje z 0
form = NowymiesiacForm(request.POST)
if form.is_valid():
# przekaz dane z formularza do zmiennych by wykonac jakies akce na nich
rok = form.cleaned_data['rok']
miesiac = form.cleaned_data['miesiac']
przychod = form.cleaned_data['przychod']
# akcje na bazie , cuda, wianki
# ...
#
message = "Nowy miesiąc dodany pomyślnie!"
return render(request, 'nowy_miesiac.html', {'form': form, 'message': message})
else:
# stworznowy form element z initial data
form = NowymiesiacForm(initial={initial={'rok': rok_aktualny, 'miesiac': miesiac_aktualny})
return render(request, 'nowy_miesiac.html', {'form': form})
Następnie ustawiamy templatke żeby ustawić value ( to jest przykładowa bo nie chce odbiegać od tematu i rozpisywać css i html layout)
<form method="post">
{% csrf_token %}
<div class="form-group">
<label for="rok">Rok:</label>
<input type="number" name="rok" id="rok" value="{{ form.rok.value }}">
{% if form.rok.errors %}
<ul class="errors">
{% for error in form.rok.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
<div class="form-group">
<label for="miesiac">Miesiąc:</label>
<select name="miesiac" id="miesiac">
{% for month_number, month_name in form.miesiac.choices %}
<option value="{{ month_number }}" {% if month_number == form.miesiac.value %}selected{% endif %}>{{ month_name }}</option>
{% endfor %}
</select>
{% if form.miesiac.errors %}
<ul class="errors">
{% for error in form.miesiac.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
<div class="form-group">
<label for="przychod">Przychód:</label>
<input type="number" name="przychod" id="przychod" step="0.01" value="{{ form.przychod.value }}">
{% if form.przychod.errors %}
<ul class="errors">
{% for error in form.przychod.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
<button type="submit">Zapisz</button>
{% if message %}
<div class="message">{{ message }}</div>
{% endif %}
</form>