Compare commits
3 Commits
178377cfb6
...
382e514d03
| Author | SHA1 | Date | |
|---|---|---|---|
| 382e514d03 | |||
| fc6b3a7fa0 | |||
| 2fc2d07a7d |
Binary file not shown.
@ -0,0 +1,46 @@
|
|||||||
|
# Generated by Django 5.0.4 on 2024-05-16 05:33
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("main", "0003_person"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="person",
|
||||||
|
name="address",
|
||||||
|
field=models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
validators=[
|
||||||
|
django.core.validators.MinLengthValidator(2),
|
||||||
|
django.core.validators.MaxLengthValidator(100),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="person",
|
||||||
|
name="city",
|
||||||
|
field=models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
validators=[
|
||||||
|
django.core.validators.MinLengthValidator(2),
|
||||||
|
django.core.validators.MaxLengthValidator(100),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="person",
|
||||||
|
name="name",
|
||||||
|
field=models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
validators=[
|
||||||
|
django.core.validators.MinLengthValidator(2),
|
||||||
|
django.core.validators.MaxLengthValidator(100),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -1,10 +1,26 @@
|
|||||||
|
from django.core.validators import MaxLengthValidator, MinLengthValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
class Person(models.Model):
|
class Person(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(
|
||||||
address = models.CharField(max_length=100)
|
max_length=100,
|
||||||
city = models.CharField(max_length=100)
|
blank=False,
|
||||||
|
null=False,
|
||||||
|
validators=[MinLengthValidator(2), MaxLengthValidator(100)],
|
||||||
|
)
|
||||||
|
address = models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
blank=False,
|
||||||
|
null=False,
|
||||||
|
validators=[MinLengthValidator(2), MaxLengthValidator(100)],
|
||||||
|
)
|
||||||
|
city = models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
blank=False,
|
||||||
|
null=False,
|
||||||
|
validators=[MinLengthValidator(2), MaxLengthValidator(100)],
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "persons"
|
db_table = "persons"
|
||||||
|
|||||||
@ -1,33 +1,4 @@
|
|||||||
{% macro inline_table_row(person, is_editing) %}
|
{% macro inline_table_row(person) %}
|
||||||
{% if is_editing %}
|
|
||||||
<tr id="person-row-{{ person.pk }}" hx-target="this" hx-swap="outerHTML">
|
|
||||||
<td>
|
|
||||||
<input class="form-control" name="name" value="{{ person.name }}">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input class="form-control" name="address" value="{{ person.address }}">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input class="form-control" name="city" value="{{ person.city }}">
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-success"
|
|
||||||
hx-post="{{ url("table-inline-edit-row", pk=person.pk) }}"
|
|
||||||
hx-include="#person-row-{{ person.pk }} input"
|
|
||||||
>
|
|
||||||
<i class="bi bi-check-circle-fill"></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-outline-danger"
|
|
||||||
hx-get="{{ url("table-inline-edit-row", pk=person.pk) }}"
|
|
||||||
hx-vals='{"action": "cancel"}'
|
|
||||||
>
|
|
||||||
<i class="bi bi-x-circle-fill"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% else %}
|
|
||||||
<tr hx-target="this" hx-swap="outerHTML">
|
<tr hx-target="this" hx-swap="outerHTML">
|
||||||
<td>{{ person.name }}</td>
|
<td>{{ person.name }}</td>
|
||||||
<td>{{ person.address }}</td>
|
<td>{{ person.address }}</td>
|
||||||
@ -42,5 +13,66 @@
|
|||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
|
||||||
|
{% macro inline_table_row_edit(person, cities, errors={}) %}
|
||||||
|
{% macro render_input(field_name, value) %}
|
||||||
|
{% set has_error = field_name in errors %}
|
||||||
|
<input
|
||||||
|
class="form-control {% if has_error %}is-invalid{% endif %}"
|
||||||
|
name="{{ field_name }}"
|
||||||
|
value="{{ value }}"
|
||||||
|
{% if has_error %}title="{{ errors[field_name] }}"{% endif %}
|
||||||
|
>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_select(field_name, value, options) %}
|
||||||
|
{% set has_error = field_name in errors %}
|
||||||
|
<select
|
||||||
|
class="form-select {% if has_error %}is-invalid{% endif %}"
|
||||||
|
name="{{ field_name }}"
|
||||||
|
{% if has_error %}title="{{ errors[field_name] }}"{% endif %}
|
||||||
|
>
|
||||||
|
{% for option in options %}
|
||||||
|
{% set selected = value == option %}
|
||||||
|
<option value="{{ option }}" {% if selected %}selected{% endif %}>
|
||||||
|
{{ option }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
<tr
|
||||||
|
id="person-row-{{ person.pk }}"
|
||||||
|
hx-target="this"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
>
|
||||||
|
<td>
|
||||||
|
{{ render_input(field_name="name", value=person.name) }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ render_input(field_name="address", value=person.address) }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{# {{ render_input(field_name="city", value=person.city) }}#}
|
||||||
|
{{ render_select(field_name="city", value=person.city, options=cities) }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-success"
|
||||||
|
hx-post="{{ url("table-inline-edit-row", pk=person.pk) }}"
|
||||||
|
hx-include="#person-row-{{ person.pk }} input, #person-row-{{ person.pk }} select"
|
||||||
|
>
|
||||||
|
<i class="bi bi-check-circle-fill"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-outline-danger"
|
||||||
|
hx-get="{{ url("table-inline-edit-row", pk=person.pk) }}"
|
||||||
|
hx-vals='{"action": "cancel"}'
|
||||||
|
>
|
||||||
|
<i class="bi bi-x-circle-fill"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for person in persons %}
|
{% for person in persons %}
|
||||||
{{ inline_table_row(person, is_editing=False) }}
|
{{ inline_table_row(person) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
{% from "main/components/inline_table_row.html" import inline_table_row %}
|
{% from "main/components/inline_table_row.html" import inline_table_row, inline_table_row_edit %}
|
||||||
|
|
||||||
{{ inline_table_row(person, is_editing=is_editing) }}
|
{% if is_editing %}
|
||||||
|
{{ inline_table_row_edit(person, cities=cities, errors=errors) }}
|
||||||
|
{% else %}
|
||||||
|
{{ inline_table_row(person) }}
|
||||||
|
{% endif %}
|
||||||
|
|||||||
@ -1,12 +1,22 @@
|
|||||||
from typing import Any
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
from django.http import Http404, HttpRequest, HttpResponse
|
from django.http import Http404, HttpResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
from project.main.models import Person
|
from project.main.models import Person
|
||||||
from project.main.views.demo_view_base import DemoViewBase
|
from project.main.views.demo_view_base import DemoViewBase
|
||||||
|
|
||||||
|
CITIES: list[str] = [
|
||||||
|
"",
|
||||||
|
"Zagreb",
|
||||||
|
"Split",
|
||||||
|
"Pula",
|
||||||
|
"Rijeka",
|
||||||
|
"Kozari bok",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_person(pk: int) -> Person:
|
def get_person(pk: int) -> Person:
|
||||||
try:
|
try:
|
||||||
@ -45,22 +55,33 @@ class TableInlineEditRowView(DemoViewBase):
|
|||||||
context_data.update(
|
context_data.update(
|
||||||
{
|
{
|
||||||
"person": person,
|
"person": person,
|
||||||
|
"cities": CITIES,
|
||||||
"is_editing": action == "edit",
|
"is_editing": action == "edit",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return context_data
|
return context_data
|
||||||
|
|
||||||
def post(self, request: WSGIRequest, *args, **kwargs) -> HttpResponse:
|
def post(self, request: WSGIRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
errors: Optional[dict[str, str]] = None
|
||||||
|
|
||||||
person = get_person(pk=kwargs.get("pk"))
|
person = get_person(pk=kwargs.get("pk"))
|
||||||
person.name = request.POST.get("name")
|
person.name = request.POST.get("name")
|
||||||
person.address = request.POST.get("address")
|
person.address = request.POST.get("address")
|
||||||
person.city = request.POST.get("city")
|
person.city = request.POST.get("city")
|
||||||
|
|
||||||
|
try:
|
||||||
|
person.clean_fields()
|
||||||
|
except ValidationError as ex:
|
||||||
|
errors = {key: value[0].message for key, value in ex.error_dict.items()}
|
||||||
|
else:
|
||||||
person.save()
|
person.save()
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
context={
|
context={
|
||||||
"person": person,
|
"person": person,
|
||||||
"is_editing": False,
|
"errors": errors,
|
||||||
|
"cities": CITIES,
|
||||||
|
"is_editing": errors is not None,
|
||||||
},
|
},
|
||||||
template_name=self.template_name,
|
template_name=self.template_name,
|
||||||
request=request,
|
request=request,
|
||||||
|
|||||||
Reference in New Issue
Block a user