8 Commits

Author SHA1 Message Date
fc6b3a7fa0 Validation 2024-05-16 07:55:27 +02:00
2fc2d07a7d Persons constraint 2024-05-16 07:35:01 +02:00
178377cfb6 Finished 2024-05-15 22:56:30 +02:00
af61d45fa4 Basic table inline edit functionality 2024-05-15 22:16:59 +02:00
7c20d4d23e BS icons 2024-05-15 21:56:28 +02:00
4ca502c6bc Finish filter list 2024-05-15 17:25:58 +02:00
4c7b18d07b Filter list with db model 2024-05-14 22:34:21 +02:00
1456ba8538 Cat breeds 2024-04-16 15:23:08 +02:00
29 changed files with 1174 additions and 7279 deletions

2
.gitignore vendored
View File

@ -2,5 +2,5 @@
/.vscode
/.venv
__pycache__
/db.sqlite3
/project/settings_local.py
/db.sqlite3

BIN
db.template.sqlite3 Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,21 @@
import os
import shutil
from django.apps import AppConfig
from django.conf import settings
class MainConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "project.main"
def ready(self):
"""copy template database if db not exists"""
db_fname = settings.DATABASES["default"]["NAME"]
template_db_fname = settings.BASE_DIR / "db.template.sqlite3"
if os.path.exists(db_fname):
return
shutil.copyfile(template_db_fname, db_fname)

View File

@ -1,6 +1,5 @@
# Generated by Django 5.0.4 on 2024-04-10 19:31
# Generated by Django 5.0.4 on 2024-05-14 20:16
import django.db.models.deletion
from django.db import migrations, models
@ -11,7 +10,7 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name="County",
name="CatBreed",
fields=[
(
"id",
@ -23,62 +22,13 @@ class Migration(migrations.Migration):
),
),
("name", models.CharField(max_length=100)),
("country", models.CharField(max_length=100)),
("origin", models.CharField(max_length=100)),
("coat", models.CharField(max_length=100)),
("pattern", models.CharField(max_length=100)),
],
options={
"db_table": "counties",
"ordering": ["name"],
},
),
migrations.CreateModel(
name="PostOffice",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("zip", models.PositiveIntegerField()),
("name", models.CharField(max_length=100)),
],
options={
"db_table": "post_offices",
"ordering": ["zip"],
},
),
migrations.CreateModel(
name="Area",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=100)),
(
"county",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="main.county"
),
),
(
"post_office",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="main.postoffice",
),
),
],
options={
"db_table": "areas",
"ordering": ["name"],
"db_table": "cat_breeds",
},
),
]

View File

@ -1,48 +0,0 @@
# Generated by Django 5.0.4 on 2024-04-10 19:42
from django.db import migrations
counties = [
'KoprivničkO-križevačka',
'Međimurska',
'Dubrovačko-neretvanska',
'Zagrebačka',
'Primorsko-goranska',
'Požeško-slavonska',
'Vukovarsko-srijemska',
'Karlovačka',
'Zadarska',
'Bjelovarsko-bilogorska',
'Splitsko-dalmatinska',
'Virovitičko-podravska',
'Ličko-senjska',
'Grad Zagreb',
'Brodsko-posavska',
'Osječko-baranjska',
'Sisačko-moslavačka',
'Krapinsko-zagorska',
'Istarska',
'Šibensko-kninska',
'Varaždinska',
]
def create_counties(apps, schema_editor):
County = apps.get_model("main", "County")
bulk = []
for county in counties:
bulk.append(County(name=county))
County.objects.bulk_create(bulk)
class Migration(migrations.Migration):
dependencies = [
("main", "0001_initial"),
]
operations = [
migrations.RunPython(create_counties),
]

View File

@ -0,0 +1,717 @@
from dataclasses import dataclass
from django.db import migrations
@dataclass
class Breed:
name: str
country: str
origin: str
coat: str
pattern: str
cat_breeds = [
Breed(
name="Abyssinian",
country="Ethiopia",
origin="Natural/Standard",
coat="Short",
pattern="Ticked",
),
Breed(
name="Aegean",
country="Greece",
origin="Natural/Standard",
coat="Semi-long",
pattern="Bi- or tri-colored",
),
Breed(
name="American Curl",
country="United States",
origin="Mutation",
coat="Short/Long",
pattern="All",
),
Breed(
name="American Bobtail",
country="United States",
origin="Mutation",
coat="Short/Long",
pattern="All",
),
Breed(
name="American Shorthair",
country="United States",
origin="Natural",
coat="Short",
pattern="All but colorpoint",
),
Breed(
name="American Wirehair",
country="United States",
origin="Mutation",
coat="Rex",
pattern="All but colorpoint",
),
Breed(
name="Arabian Mau",
country="Arabian Peninsula",
origin="Natural",
coat="Short",
pattern="",
),
Breed(
name="Australian Mist",
country="Australia",
origin="Crossbreed",
coat="Short",
pattern="Spotted and Classic tabby",
),
Breed(
name="Asian",
country="United Kingdom",
origin="",
coat="Short",
pattern="Evenly solid",
),
Breed(
name="Asian Semi-longhair",
country="United Kingdom",
origin="Crossbreed",
coat="Semi-long",
pattern="Solid",
),
Breed(
name="Balinese",
country="United States",
origin="Crossbreed",
coat="Long",
pattern="Colorpoint",
),
Breed(
name="Bambino",
country="United States",
origin="Crossbreed",
coat="Hairless/Furry down",
pattern="",
),
Breed(
name="Bengal",
country="United States",
origin="Hybrid",
coat="Short",
pattern="Spotted/Marbled",
),
Breed(
name="Birman",
country="France",
origin="Natural",
coat="Semi Long",
pattern="Colorpoint",
),
Breed(
name="Bombay",
country="United States",
origin="Crossbred",
coat="Short",
pattern="Solid",
),
Breed(
name="Brazilian Shorthair",
country="Brazil",
origin="Natural",
coat="Short",
pattern="All",
),
Breed(
name="British Semi-longhair",
country="United Kingdom",
origin="",
coat="Medium",
pattern="All",
),
Breed(
name="British Shorthair",
country="United Kingdom",
origin="Natural",
coat="Short",
pattern="All",
),
Breed(
name="British Longhair",
country="United Kingdom",
origin="",
coat="Long",
pattern="",
),
Breed(
name="Burmese",
country="Burma and Thailand",
origin="Natural",
coat="Short",
pattern="Solid",
),
Breed(
name="Burmilla",
country="United Kingdom",
origin="Crossbreed",
coat="Short/Long",
pattern="",
),
Breed(
name="California Spangled",
country="United States",
origin="Crossbreed",
coat="Short",
pattern="Spotted",
),
Breed(
name="Chantilly-Tiffany",
country="United States",
origin="",
coat="",
pattern="",
),
Breed(
name="Chartreux",
country="France",
origin="Natural",
coat="Short",
pattern="Solid",
),
Breed(
name="Chausie",
country="France",
origin="Hybrid",
coat="Short",
pattern="Ticked",
),
Breed(
name="Cheetoh",
country="United States",
origin="Hybrid Crossbreed",
coat="Short",
pattern="Spotted",
),
Breed(
name="Cornish Rex",
country="United Kingdom",
origin="Mutation",
coat="Rex",
pattern="All",
),
Breed(
name="Cymric or Manx Longhair",
country="United Kingdom",
origin="Natural/Mutation",
coat="Long",
pattern="",
),
Breed(
name="Cyprus",
country="Cyprus",
origin="Natural",
coat="All",
pattern="All",
),
Breed(
name="Devon Rex",
country="United Kingdom",
origin="Mutation",
coat="Rex",
pattern="All",
),
Breed(
name="Donskoy, or Don Sphynx",
country="Russia",
origin="",
coat="Hairless",
pattern="",
),
Breed(
name="Dragon Li",
country="China",
origin="Natural",
coat="Short",
pattern="Striped tabby",
),
Breed(
name="Dwarf cat, or Dwelf",
country="",
origin="Crossbreed",
coat="",
pattern="Hairless",
),
Breed(
name="Egyptian Mau",
country="Egypt",
origin="Natural",
coat="Short",
pattern="Spotted",
),
Breed(
name="European Shorthair",
country="Finland and Sweden",
origin="Natural",
coat="Short",
pattern="",
),
Breed(
name="Exotic Shorthair",
country="United States",
origin="Crossbreed",
coat="Short",
pattern="All",
),
Breed(
name="Foldex[4]",
country="Canada",
origin="Crossbreed",
coat="Short",
pattern="All",
),
Breed(
name="German Rex",
country="East Germany",
origin="Mutation",
coat="Rex",
pattern="",
),
Breed(
name="Havana Brown",
country="United Kingdom",
origin="",
coat="Short",
pattern="Solid",
),
Breed(
name="Highlander",
country="United States",
origin="Crossbreed",
coat="Short/Long",
pattern="All",
),
Breed(
name="Himalayan, or Colorpoint Persian",
country="United States/United Kingdom",
origin="Crossbreed",
coat="Long",
pattern="Colorpoint",
),
Breed(
name="Japanese Bobtail",
country="Japan",
origin="Natural",
coat="Short/Long",
pattern="All but colorpoint and ticked",
),
Breed(
name="Javanese",
country="United States",
origin="Crossbreed",
coat="Long/Short",
pattern="Colorpoint",
),
Breed(
name="Karelian Bobtail",
country="Western Russia",
origin="Natural",
coat="",
pattern="",
),
Breed(
name="Khao Manee",
country="Thailand",
origin="Natural",
coat="Short",
pattern="Solid",
),
Breed(
name="Korat",
country="Thailand",
origin="Natural",
coat="Short",
pattern="Solid",
),
Breed(
name="Korean Bobtail",
country="Korea",
origin="Natural",
coat="Short/Long",
pattern="Colorprint",
),
Breed(
name="Korn Ja",
country="Thailand",
origin="Natural",
coat="Short/Hairless",
pattern="Solid",
),
Breed(
name="Kurilian Bobtail, or Kuril Islands Bobtail",
country="Eastern Russia,Japan",
origin="Natural",
coat="Short/Long",
pattern="",
),
Breed(
name="LaPerm",
country="United States",
origin="Mutation",
coat="Rex",
pattern="All",
),
Breed(
name="Lykoi",
country="United States",
origin="Natural/Mutation",
coat="Partly Hairless",
pattern="Ticked",
),
Breed(
name="Maine Coon",
country="United States",
origin="Natural",
coat="Long",
pattern="All but colorpoint and ticked",
),
Breed(
name="Manx",
country="United Kingdom",
origin="Mutation",
coat="Short/Long",
pattern="All but colorpoint",
),
Breed(
name="Mekong Bobtail",
country="Russia",
origin="Natural/Mutation",
coat="Short",
pattern="Colorpoint",
),
Breed(
name="Minskin",
country="United States",
origin="Crossbreed",
coat="Short/Hairless",
pattern="All",
),
Breed(
name="Munchkin",
country="United States",
origin="Mutation",
coat="",
pattern="",
),
Breed(
name="Nebelung",
country="United States",
origin="",
coat="Semi-long",
pattern="Solid",
),
Breed(
name="Napoleon",
country="",
origin="",
coat="Long/short",
pattern="Varied",
),
Breed(
name="Norwegian Forest cat",
country="Norway",
origin="Natural",
coat="Long",
pattern="All but colorpoint",
),
Breed(
name="Ocicat",
country="United States",
origin="Crossbreed",
coat="Short",
pattern="Spotted",
),
Breed(
name="Ojos Azules",
country="United States",
origin="",
coat="",
pattern="",
),
Breed(
name="Oregon Rex",
country="United States",
origin="Mutation",
coat="Rex",
pattern="",
),
Breed(
name="Oriental Bicolor",
country="",
origin="",
coat="",
pattern="Bicolor",
),
Breed(
name="Oriental Shorthair",
country="",
origin="",
coat="Short",
pattern="All but colorpoint",
),
Breed(
name="Oriental Longhair",
country="",
origin="",
coat="Semi-long",
pattern="",
),
Breed(
name="PerFoldæ(Experimental Breed - WCF),",
country="Europe",
origin="Crossbreed",
coat="Long",
pattern="All",
),
Breed(
name="Persian (Modern Persian Cat),",
country="Iran (Persia),",
origin="Crossbreed",
coat="Long",
pattern="All",
),
Breed(
name="Persian (Traditional Persian Cat),",
country="Greater Iran",
origin="Natural",
coat="Long",
pattern="All",
),
Breed(
name="Peterbald",
country="Russia",
origin="Crossbreed",
coat="Hairless",
pattern="All",
),
Breed(
name="Pixie-bob",
country="United States",
origin="Natural",
coat="Short",
pattern="Spotted",
),
Breed(
name="Raas",
country="Indonesia",
origin="Natural",
coat="Short",
pattern="",
),
Breed(
name="Ragamuffin",
country="United States",
origin="Crossbreed",
coat="Long",
pattern="All",
),
Breed(
name="Ragdoll",
country="United States",
origin="Crossbreed",
coat="Long",
pattern="Colorpoint/Mitted/Bicolor",
),
Breed(
name="Russian Blue",
country="Russia",
origin="Natural",
coat="Short",
pattern="Solid",
),
Breed(
name="Russian White, Black and Tabby",
country="Australia",
origin="Crossbreed",
coat="Short",
pattern="",
),
Breed(
name="Sam Sawet",
country="Thailand",
origin="Natural",
coat="Short",
pattern="Solid",
),
Breed(
name="Savannah",
country="United States",
origin="Hybrid",
coat="Short",
pattern="Spotted",
),
Breed(
name="Scottish Fold",
country="United Kingdom",
origin="Natural/Mutation",
coat="Short/Long",
pattern="All",
),
Breed(
name="Selkirk Rex",
country="United States",
origin="Mutation/Cross",
coat="Rex (Short/Long),",
pattern="All",
),
Breed(
name="Serengeti",
country="United States",
origin="Hybrid Crossbreed",
coat="Short",
pattern="Spotted",
),
Breed(
name="Serrade petit",
country="France",
origin="Natural",
coat="Short",
pattern="",
),
Breed(
name="Siamese",
country="Thailand",
origin="Natural",
coat="Short",
pattern="Colorpoint",
),
Breed(
name="Siberian",
country="Russia",
origin="Natural",
coat="Semi-long",
pattern="All",
),
Breed(
name="Singapura",
country="Singapore",
origin="Natural",
coat="Short",
pattern="Ticked",
),
Breed(
name="Snowshoe",
country="United States",
origin="Crossbreed",
coat="Short",
pattern="Colorpoint",
),
Breed(
name="Sokoke",
country="Kenya",
origin="Natural",
coat="Short",
pattern="Classic tabby with ticking",
),
Breed(
name="Somali",
country="Somalia",
origin="Mutation",
coat="Long",
pattern="Ticked",
),
Breed(
name="Sphynx",
country="Canada",
origin="Mutation",
coat="Hairless",
pattern="All",
),
Breed(
name="Suphalak",
country="Thailand",
origin="Natural",
coat="Short",
pattern="Solid",
),
Breed(
name="Thai",
country="Thailand",
origin="Natural",
coat="Short",
pattern="Colorpoint",
),
Breed(
name="Thai Lilac",
country="Thailand",
origin="Natural",
coat="Short",
pattern="Solid",
),
Breed(
name="Tonkinese",
country="Canada",
origin="Crossbreed",
coat="Short",
pattern="Colorpoint/Mink/Solid",
),
Breed(
name="Toyger",
country="United States",
origin="Crossbreed",
coat="Short",
pattern="Mackerel",
),
Breed(
name="Turkish Angora",
country="Turkey",
origin="Natural",
coat="Semi-long",
pattern="All but colorpoint",
),
Breed(
name="Ukrainian Levkoy",
country="Ukraine",
origin="",
coat="Hairless",
pattern="",
),
Breed(
name="York Chocolate",
country="United States",
origin="Natural",
coat="Long",
pattern="Solid",
),
]
def create_cat_breeds(apps, schema_editor):
CatBreed = apps.get_model("main", "CatBreed")
bulk = []
for cat_breed in cat_breeds:
bulk.append(
CatBreed(
name=cat_breed.name,
country=cat_breed.country,
origin=cat_breed.origin,
coat=cat_breed.coat,
pattern=cat_breed.pattern,
)
)
CatBreed.objects.bulk_create(bulk)
class Migration(migrations.Migration):
dependencies = [
("main", "0001_initial"),
]
operations = [
migrations.RunPython(create_cat_breeds),
]

View File

@ -1,333 +0,0 @@
# Generated by Django 5.0.4 on 2024-04-10 19:59
from django.db import migrations
post_offices = {
10000: 'Zagreb',
10010: 'Zagreb-Sloboština',
10020: 'Zagreb-Novi Zagreb',
10040: 'Zagreb-Dubrava',
10090: 'Zagreb-Susedgrad',
10104: 'Zagreb',
10105: 'Zagreb',
10108: 'Zagreb',
10109: 'Zagreb',
10110: 'Zagreb',
10135: 'Zagreb',
10172: 'Zagreb',
10250: 'Lučko',
10255: 'Gornji Stupnik',
10257: 'Brezovica',
10290: 'Zaprešić',
10291: 'Prigorje Brdovečko',
10292: 'Šenkovec',
10295: 'Kupljenovo',
10297: 'Jakovlje',
10298: 'Bistra',
10310: 'Ivanić Grad',
10315: 'Novoselec',
10340: 'Vrbovec',
10342: 'Dubrava',
10360: 'Sesvete',
10361: 'Sesvete Kraljevec',
10362: 'Kašina',
10370: 'Dugo Selo',
10380: 'Sveti Ivan Zelina',
10410: 'Velika Gorica',
10413: 'Kravarsko',
10414: 'Pokupsko',
10430: 'Samobor',
10431: 'Sveta Nedelja',
10435: 'Sveti Martin pod Okićem',
10437: 'Bestovje',
10450: 'Jastrebarsko',
10451: 'Pisarovina',
10454: 'Krašić',
20000: 'Dubrovnik',
20207: 'Mlini',
20210: 'Cavtat',
20215: 'Gruda',
20221: 'Koločep',
20222: 'Lopud',
20223: 'Šipanska Luka',
20225: 'Babino Polje',
20230: 'Ston',
20232: 'Slano',
20235: 'Zaton Veliki',
20236: 'Mokošica',
20240: 'Trpanj',
20244: 'Potomje',
20246: 'Janjina',
20250: 'Orebić',
20260: 'Korčula',
20270: 'Vela Luka',
20271: 'Blato',
20290: 'Lastovo',
20340: 'Ploče',
20350: 'Metković',
20355: 'Opuzen',
21000: 'Split',
21203: 'Donji Muć',
21204: 'Dugopolje',
21210: 'Solin',
21212: 'Kaštel Sućurac',
21214: 'Kaštel Kambelovac',
21217: 'Kaštel Štafilić',
21220: 'Trogir',
21222: 'Marina',
21225: 'Drvenik Veliki',
21230: 'Sinj',
21240: 'Trilj',
21232: 'Dicmo',
21233: 'Hrvace',
21236: 'Vrlika',
21238: 'Otok (Dalmacija)',
21250: 'Šestanovac',
21256: 'Cista Provo',
21260: 'Imotski',
21270: 'Zagvozd',
21276: 'Vrgorac',
21300: 'Makarska',
21310: 'Omiš',
21311: 'Stobreč',
21315: 'Dugi Rat',
21320: 'Baška Voda',
21327: 'Podgora',
21330: 'Gradac',
21400: 'Supetar',
21405: 'Milna',
21412: 'Pučišća',
21420: 'Bol',
21425: 'Selca',
21430: 'Grohote',
21450: 'Hvar',
21460: 'Stari Grad',
21465: 'Jelsa',
21469: 'Sućuraj',
21480: 'Vis',
21485: 'Komiža',
22000: 'Šibenik',
22202: 'Primošten',
22211: 'Vodice',
22213: 'Pirovac',
22222: 'Skradin',
22232: 'Zlarin',
22233: 'Prvić Luka',
22234: 'Prvić Šepurine',
22235: 'Kaprije',
22236: 'Žirje',
22240: 'Tisno',
22243: 'Murter',
22300: 'Knin',
22320: 'Drniš',
22323: 'Unešić',
23000: 'Zadar',
23205: 'Bibinje',
23206: 'Sukošan',
23210: 'Biograd na Moru',
23212: 'Tkon',
23222: 'Zemunik',
23223: 'Škabrnja',
23232: 'Nin',
23233: 'Privlaka',
23234: 'Vir',
23235: 'Vrsi',
23241: 'Poličnik',
23242: 'Posedarje',
23244: 'Starigrad Paklenica',
23248: 'Ražanac',
23250: 'Pag',
23271: 'Kukljica',
23273: 'Preko',
23281: 'Sali',
23283: 'Rava',
23284: 'Veli Iž',
23286: 'Božava',
23287: 'Veli Rat',
23291: 'Sestrunj',
23292: 'Molat',
23293: 'Ist',
23294: 'Premuda',
23295: 'Silba',
23296: 'Olib',
23312: 'Novigrad (Dalmacija)',
23420: 'Benkovac',
23422: 'Stankovci',
23440: 'Gračac',
23450: 'Obrovac',
31000: 'Osijek',
31200: 'Osijek',
31207: 'Tenja',
31226: 'Dalj',
31300: 'Beli Manastir',
31326: 'Darda',
31400: 'Đakovo',
31431: 'Čepin',
31500: 'Našice',
31540: 'Donji Miholjac',
31550: 'Valpovo',
31551: 'Belišće',
32000: 'Vukovar',
32100: 'Vinkovci',
32236: 'Ilok',
32242: 'Slakovci',
32249: 'Tovarnik',
32252: 'Otok',
32257: 'Drenovci',
32270: 'Županja',
32284: 'Stari Mikanovci',
33000: 'Virovitica',
33405: 'Pitomača',
33410: 'Suhopolje',
33515: 'Orahovica',
33520: 'Slatina',
34000: 'Požega',
34310: 'Pleternica',
34340: 'Kutjevo',
34550: 'Pakrac',
35000: 'Slavonski Brod',
35212: 'Garčin',
35214: 'Donji Andrijevci',
35220: 'Slavonski Šamac',
35222: 'Gundinci',
35250: 'Oriovac',
35252: 'Sibinj',
35400: 'Nova Gradiška',
35410: 'Nova Kapela',
35420: 'Staro Petrovo Selo',
35430: 'Okučani',
40000: 'Čakovec',
40313: 'Sveti Martin na Muri',
40315: 'Mursko Središče',
40320: 'Donji Kraljevec',
40323: 'Prelog',
42000: 'Varaždin',
42202: 'Trnovec Bartolovečki',
42204: 'Turčin',
42208: 'Cestica',
42220: 'Novi Marof',
42223: 'Varaždinske Toplice',
42230: 'Ludbreg',
42240: 'Ivanec',
42243: 'Maruševec',
42250: 'Lepoglava',
43000: 'Bjelovar',
43240: 'Čazma',
43270: 'Veliki Grđevac',
43280: 'Garešnica',
43290: 'Grubišno Polje',
43500: 'Daruvar',
44000: 'Sisak',
44010: 'Sisak-Caprag',
44210: 'Sunja',
44250: 'Petrinja',
44317: 'Popovača',
44320: 'Kutina',
44330: 'Novska',
44400: 'Glina',
44410: 'Vrginmost',
44430: 'Hrvatska Kostajnica',
44440: 'Dvor',
47000: 'Karlovac',
47220: 'Vojnić',
47240: 'Slunj',
47250: 'Duga Resa',
47280: 'Ozalj',
47300: 'Ogulin',
48000: 'Koprivnica',
48214: 'Sveti Ivan Žabno',
48260: 'Križevci',
48316: 'Đelekovec',
48350: 'Đurđevac',
49000: 'Krapina',
49210: 'Zabok',
49216: 'Desinić',
49217: 'Krapinske Toplice',
49218: 'Pregrada',
49221: 'Bedekovčina',
49223: 'Sveti Križ Začretje',
49225: 'Đurmanec',
49231: 'Hum na Sutli',
49240: 'Donja Stubica',
49243: 'Oroslavje',
49246: 'Marija Bistrica',
49250: 'Zlatar',
49252: 'Mihovljan',
49282: 'Konjščina',
49284: 'Budinščina',
49290: 'Klanjec',
51000: 'Rijeka',
51211: 'Matulji',
51215: 'Kastav',
51216: 'Viškovo',
51217: 'Klana',
51218: 'Dražice',
51224: 'Krasica',
51226: 'Hreljin',
51250: 'Novi Vinodolski',
51260: 'Crikvenica',
51262: 'Kraljevica',
51280: 'Rab',
51300: 'Delnice',
51306: 'Čabar',
51326: 'Vrbovsko',
51410: 'Opatija',
51415: 'Lovran',
51417: 'Mošćenička Draga',
51500: 'Krk',
51511: 'Malinska',
51523: 'Baška',
51550: 'Mali Lošinj',
51552: 'Ilovik',
51556: 'Martinšćica',
51557: 'Cres',
51561: 'Susak',
51562: 'Unije',
52000: 'Pazin',
52100: 'Pula (Pola)',
52207: 'Barban',
52210: 'Rovinj (Rovigno)',
52220: 'Labin',
52333: 'Podpićan',
52341: 'Žminj',
52420: 'Buzet',
52424: 'Motovun (Montona)',
52440: 'Poreč (Parenzo)',
52460: 'Buje (Buie)',
52466: 'Novigrad-Cittanova',
52470: 'Umag (Umago)',
53000: 'Gospić',
53202: 'Perušić',
53220: 'Otočac',
53230: 'Korenica',
53234: 'Udbina',
53250: 'Donji Lapac',
53260: 'Brinje',
53270: 'Senj',
53288: 'Karlobag',
53291: 'Novalja',
}
def create_post_offices(apps, schema_editor):
PostOffice = apps.get_model("main", "PostOffice")
bulk = []
for key, name in post_offices.items():
bulk.append(PostOffice(
zip=key,
name=name,
))
PostOffice.objects.bulk_create(bulk)
class Migration(migrations.Migration):
dependencies = [
("main", "0002_auto_20240410_1942"),
]
operations = [
migrations.RunPython(create_post_offices),
]

View File

@ -0,0 +1,60 @@
from django.db import migrations, models
def create_persons_data(apps, schema_editor):
Person = apps.get_model("main", "Person")
bulk = [
Person(
name="Pero",
address="Perina ulica 15",
city="Zagreb",
),
Person(
name="Mirko",
address="Mirkova ulica 17",
city="Zagreb",
),
Person(
name="Šime",
address="Šimina ulica 19",
city="Split",
),
Person(
name="Furio",
address="Furiozna ulica 21",
city="Pula",
),
]
Person.objects.bulk_create(bulk)
class Migration(migrations.Migration):
dependencies = [
("main", "0002_example_data"),
]
operations = [
migrations.CreateModel(
name="Person",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=100)),
("address", models.CharField(max_length=100)),
("city", models.CharField(max_length=100)),
],
options={
"db_table": "persons",
},
),
migrations.RunPython(create_persons_data),
]

View File

@ -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),
],
),
),
]

View File

@ -1,11 +0,0 @@
# Generated by Django 5.0.4 on 2024-04-11 06:05
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("main", "0003_auto_20240410_1959"),
]
operations = []

View File

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

View File

@ -1,3 +1,2 @@
from .area import Area
from .county import County
from .post_office import PostOffice
from .cat_breed import CatBreed
from .person import Person

View File

@ -1,11 +0,0 @@
from django.db import models
class Area(models.Model):
name = models.CharField(max_length=100)
post_office = models.ForeignKey("PostOffice", on_delete=models.CASCADE)
county = models.ForeignKey("County", on_delete=models.CASCADE)
class Meta:
db_table = "areas"
ordering = ["name"]

View File

@ -0,0 +1,12 @@
from django.db import models
class CatBreed(models.Model):
name = models.CharField(max_length=100)
country = models.CharField(max_length=100)
origin = models.CharField(max_length=100)
coat = models.CharField(max_length=100)
pattern = models.CharField(max_length=100)
class Meta:
db_table = "cat_breeds"

View File

@ -1,9 +0,0 @@
from django.db import models
class County(models.Model):
name = models.CharField(max_length=100)
class Meta:
db_table = "counties"
ordering = ["name"]

View File

@ -0,0 +1,26 @@
from django.core.validators import MaxLengthValidator, MinLengthValidator
from django.db import models
class Person(models.Model):
name = 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:
db_table = "persons"

View File

@ -1,10 +0,0 @@
from django.db import models
class PostOffice(models.Model):
zip = models.PositiveIntegerField()
name = models.CharField(max_length=100)
class Meta:
db_table = "post_offices"
ordering = ["zip"]

View File

@ -6,6 +6,7 @@
content="width=100%, user-scalable=yes, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js" integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<script src="https://unpkg.com/htmx.org@1.9.11" integrity="sha384-0gxUXCCR8yv9FM2b+U3FDbsKthCI66oH5IA9fHppQq9DDMHuMauqq1ZHBpJxQ0J0" crossorigin="anonymous"></script>
<title>{{ title or "Django-html demo" }}</title>
</head>

View File

@ -0,0 +1,56 @@
{% macro inline_table_row(person, is_editing, 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 %}
{% if is_editing %}
<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) }}
</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">
<td>{{ person.name }}</td>
<td>{{ person.address }}</td>
<td>{{ person.city }}</td>
<td>
<button
class="btn btn-outline-primary"
hx-get="{{ url("table-inline-edit-row", pk=person.pk) }}"
>
<i class="bi bi-pencil-square"></i>
</button>
</td>
</tr>
{% endif %}
{% endmacro %}

View File

@ -1,22 +1,14 @@
{% macro no_js_alert() %}
<div class="alert alert-success d-flex align-items-center mb-5" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="text-success me-3" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
</svg>
<div>
No JavaScript is used creating this page.
</div>
<i class="bi bi-check-circle-fill me-3"></i>
No JavaScript is used creating this page.
</div>
{% endmacro %}
{% macro js_alert(content) %}
<div class="alert alert-warning d-flex align-items-center mb-5" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="text-warning me-3" viewBox="0 0 16 16">
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
</svg>
<div>
{{ content }}
</div>
<i class="bi bi-exclamation-triangle-fill me-3"></i>
{{ content }}
</div>
{% endmacro %}

View File

@ -1,7 +1,54 @@
{% extends "main/base/layout.html" %}
{% from "main/components/js_alert.html" import js_alert_work_in_progress %}
{% from "main/components/js_alert.html" import no_js_alert %}
{% block content %}
{{ js_alert_work_in_progress() }}
{{ no_js_alert() }}
<div class="card mb-2">
<div class="card-body">
<form
class="row g-3 align-items-center"
>
<div class="col-auto">
<label class="form-label mb-0">Breed:</label>
</div>
<div class="col-auto">
<input
type="text"
name="breed"
class="form-control"
hx-get="{{ url("filter-list-filter") }}"
hx-target="#cat-breeds-table"
hx-trigger="keyup"
hx-include="select[name='country']"
/>
</div>
<div class="col-auto">
<label class="form-label mb-0">Country:</label>
</div>
<div class="col-auto">
<select
name="country"
class="form-select"
hx-get="{{ url("filter-list-filter") }}"
hx-target="#cat-breeds-table"
hx-trigger="change"
hx-include="input[name='breed']"
>
<option value="">
- All -
</option>
{% for country in countries %}
<option value="{{ country }}">
{{ country }}
</option>
{% endfor %}
</select>
</div>
</form>
</div>
</div>
{% include "main/filter_list_content.html" %}
{% endblock %}

View File

@ -0,0 +1,22 @@
<table class="table" id="cat-breeds-table">
<thead>
<tr>
<th>Breed</th>
<th>Country</th>
<th>Origin</th>
<th>Coat</th>
<th>Pattern</th>
</tr>
</thead>
<tbody>
{% for breed in cat_breeds %}
<tr>
<td>{{ breed.name }}</td>
<td>{{ breed.country }}</td>
<td>{{ breed.origin }}</td>
<td>{{ breed.coat }}</td>
<td>{{ breed.pattern }}</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -1,7 +1,24 @@
{% extends "main/base/layout.html" %}
{% from "main/components/js_alert.html" import js_alert_work_in_progress %}
{% from "main/components/js_alert.html" import no_js_alert %}
{% from "main/components/inline_table_row.html" import inline_table_row %}
{% block content %}
{{ js_alert_work_in_progress() }}
{{ no_js_alert() }}
<table class="table align-middle">
<thead>
<tr>
<th style="width: 25%">Name</th>
<th>Address</th>
<th style="width: 25%">City</th>
<th style="width: 15%">&nbsp;</th>
</tr>
</thead>
<tbody>
{% for person in persons %}
{{ inline_table_row(person, is_editing=False) }}
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -0,0 +1,3 @@
{% from "main/components/inline_table_row.html" import inline_table_row %}
{{ inline_table_row(person, is_editing=is_editing, errors=errors) }}

View File

@ -4,8 +4,8 @@ from .complex_form.views import (
RouteModuleHandleView,
WarehouseManagementHandleView,
)
from .filter_list import FilterListView
from .filter_list import FilterListFilterView, FilterListView
from .form_validation import FormValidationView
from .home import HomeView
from .swap import SwapView
from .table_inline_edit import TableInlineEditView
from .table_inline_edit import TableInlineEditView, TableInlineEditRowView

View File

@ -1,7 +1,65 @@
from typing import Any, Optional
from django.db.models import Count, Q
from project.main.models import CatBreed
from project.main.views.demo_view_base import DemoViewBase
def get_countries() -> list[str]:
ann = (
CatBreed.objects.values("country")
.annotate(Count("country"))
.order_by("country")
)
return [a["country"] for a in ann]
def filter_cat_breeds(
breed_filter: Optional[str] = None, country_filter: Optional[str] = None
) -> list[CatBreed]:
q = Q()
if breed_filter:
q &= Q(name__icontains=breed_filter)
if country_filter:
q &= Q(country=country_filter)
return CatBreed.objects.filter(q).order_by("name")
class FilterListView(DemoViewBase):
template_name = "main/filter_list.html"
active_section = "filter-list"
title = "Filter List"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context_data = super().get_context_data(**kwargs)
context_data.update(
{
"cat_breeds": filter_cat_breeds(),
"countries": get_countries(),
}
)
return context_data
class FilterListFilterView(DemoViewBase):
template_name = "main/filter_list_content.html"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context_data = super().get_context_data(**kwargs)
cat_breeds = filter_cat_breeds(
breed_filter=self.request.GET.get("breed"),
country_filter=self.request.GET.get("country"),
)
context_data.update(
{
"cat_breeds": cat_breeds,
"countries": get_countries(),
}
)
return context_data

View File

@ -1,7 +1,79 @@
from typing import Any, Optional
from django.core.exceptions import ValidationError
from django.core.handlers.wsgi import WSGIRequest
from django.http import Http404, HttpResponse
from django.shortcuts import render
from project.main.models import Person
from project.main.views.demo_view_base import DemoViewBase
def get_person(pk: int) -> Person:
try:
return Person.objects.get(pk=pk)
except Person.DoesNotExist:
raise Http404("Person not found")
class TableInlineEditView(DemoViewBase):
template_name = "main/table_inline_edit.html"
active_section = "table-inline-edit"
title = "Table Inline Edit"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context_data = super().get_context_data(**kwargs)
persons = Person.objects.all()
context_data.update(
{
"persons": persons,
}
)
return context_data
class TableInlineEditRowView(DemoViewBase):
template_name = "main/table_inline_table_row.html"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context_data = super().get_context_data(**kwargs)
person = get_person(pk=kwargs.get("pk"))
action = self.request.GET.get("action", "edit")
context_data.update(
{
"person": person,
"is_editing": action == "edit",
}
)
return context_data
def post(self, request: WSGIRequest, *args, **kwargs) -> HttpResponse:
errors: Optional[dict[str, str]] = None
person = get_person(pk=kwargs.get("pk"))
person.name = request.POST.get("name")
person.address = request.POST.get("address")
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()
print(errors)
return render(
context={
"person": person,
"errors": errors,
"is_editing": errors is not None,
},
template_name=self.template_name,
request=request,
)

View File

@ -6,10 +6,12 @@ urlpatterns = [
path("", views.HomeView.as_view(), name="home"),
path("swap", views.SwapView.as_view(), name="swap"),
path("filter-list", views.FilterListView.as_view(), name="filter-list"),
path("filter-list-filter", views.FilterListFilterView.as_view(), name="filter-list-filter"),
path("form-validation", views.FormValidationView.as_view(), name="form-validation"),
path("complex-form", views.ComplexFormView.as_view(), name="complex-form"),
path("complex-form/handle/route-module", views.RouteModuleHandleView.as_view(), name="complex-form-handle-route-module"),
path("complex-form/handle/reports", views.ReportsHandleView.as_view(), name="complex-form-handle-reports"),
path("complex-form/handle/warehouse-management", views.WarehouseManagementHandleView.as_view(), name="complex-form-handle-warehouse-management"),
path("table-inline-edit", views.TableInlineEditView.as_view(), name="table-inline-edit"),
path("table-inline-edit/edit/<int:pk>", views.TableInlineEditRowView.as_view(), name="table-inline-edit-row"),
]