Add category page
This commit is contained in:
parent
df49afb5a4
commit
467c8002e2
6 changed files with 84 additions and 22 deletions
|
@ -12,7 +12,7 @@ class Category(models.Model):
|
||||||
parent = models.ForeignKey("self", on_delete=models.SET_NULL, blank=True, null=True)
|
parent = models.ForeignKey("self", on_delete=models.SET_NULL, blank=True, null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.parent is None:
|
if self.parent is None or self.parent == self:
|
||||||
return self.name
|
return self.name
|
||||||
return f"{self.parent}>{self.name}"
|
return f"{self.parent}>{self.name}"
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ class Category(models.Model):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tree(self):
|
def tree(self):
|
||||||
if self.parent is None:
|
if self.parent is None or self.parent == self:
|
||||||
return [self.name]
|
return [self.name]
|
||||||
return self.parent.tree + [self.name]
|
return self.parent.tree + [self.name]
|
||||||
|
|
||||||
|
@ -32,6 +32,12 @@ class Category(models.Model):
|
||||||
ordering = ["full_name"]
|
ordering = ["full_name"]
|
||||||
|
|
||||||
|
|
||||||
|
class CategoryForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Category
|
||||||
|
fields = ["name", "parent"]
|
||||||
|
|
||||||
|
|
||||||
class Transaction(models.Model):
|
class Transaction(models.Model):
|
||||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||||
name = models.CharField(max_length=256, default="Transaction")
|
name = models.CharField(max_length=256, default="Transaction")
|
||||||
|
@ -49,6 +55,9 @@ class Transaction(models.Model):
|
||||||
return f"{res} ({self.category})"
|
return f"{res} ({self.category})"
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ["-date"]
|
||||||
|
|
||||||
|
|
||||||
class TransactionForm(ModelForm):
|
class TransactionForm(ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -42,7 +42,6 @@
|
||||||
ul#categories {
|
ul#categories {
|
||||||
list-style-type: "– ";
|
list-style-type: "– ";
|
||||||
}
|
}
|
||||||
#categories ul {
|
ul#categories li.cat2 {margin-left: 1em}
|
||||||
list-style-type: "↳ ";
|
ul#categories li.cat3 {margin-left: 2em}
|
||||||
padding-left: 1.5em;
|
ul#categories li.cat4 {margin-left: 3em}
|
||||||
}
|
|
||||||
|
|
20
nummi/main/templates/main/category.html
Normal file
20
nummi/main/templates/main/category.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{% extends "main/base.html" %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<a href="{% url 'index' %}">Home</a>
|
||||||
|
|
||||||
|
<h1>{{ category.tree|join:" → " }}</h1>
|
||||||
|
|
||||||
|
<form action="{% url 'update_category' category.id %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form.as_p }}
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if transactions %}
|
||||||
|
<h2>Transactions ({{ transactions|length }})</h2>
|
||||||
|
<ul>
|
||||||
|
{{ transactions|unordered_list }}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
|
@ -37,7 +37,13 @@
|
||||||
|
|
||||||
{% if categories %}
|
{% if categories %}
|
||||||
<ul id="categories">
|
<ul id="categories">
|
||||||
{{ categories|unordered_list }}
|
{% for cat in categories %}
|
||||||
|
<li class="{% if cat.tree|length > 3 %}cat4{% else %}cat{{ cat.tree|length }}{% endif %}">
|
||||||
|
<a href="{% url 'category' cat.id %}">
|
||||||
|
{% if cat.tree|length > 3 %}{{ cat.tree|slice:"3:"|join:" → " }}{% else %}{{ cat.name }}{% endif %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -18,4 +18,7 @@ urlpatterns = [
|
||||||
name="del_invoice",
|
name="del_invoice",
|
||||||
),
|
),
|
||||||
path("invoice/<uuid>", views.invoice, name="invoice"),
|
path("invoice/<uuid>", views.invoice, name="invoice"),
|
||||||
|
path("category", views.category, name="category"),
|
||||||
|
path("category/<uuid>", views.category, name="category"),
|
||||||
|
path("category/<uuid>/update", views.update_category, name="update_category"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,29 +3,24 @@ from django.http import HttpResponse
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
|
|
||||||
from .models import Transaction, TransactionForm, Invoice, InvoiceForm, Category
|
from .models import (
|
||||||
|
Transaction,
|
||||||
|
TransactionForm,
|
||||||
|
Invoice,
|
||||||
|
InvoiceForm,
|
||||||
|
Category,
|
||||||
|
CategoryForm,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def index(request):
|
def index(request):
|
||||||
_transactions = Transaction.objects.order_by("-date")[:5]
|
_transactions = Transaction.objects.order_by("-date")[:5]
|
||||||
_categories = Category.objects.filter(parent=None)
|
_categories = Category.objects.all()
|
||||||
|
|
||||||
def _cat_list(cat):
|
|
||||||
children = []
|
|
||||||
for child in Category.objects.filter(parent=cat):
|
|
||||||
children += _cat_list(child)
|
|
||||||
if len(children) == 0:
|
|
||||||
return (cat.name,)
|
|
||||||
return cat.name, children
|
|
||||||
|
|
||||||
_cats = []
|
|
||||||
for cat in _categories:
|
|
||||||
_cats += _cat_list(cat)
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"transactions": _transactions,
|
"transactions": _transactions,
|
||||||
"categories": _cats,
|
"categories": _categories,
|
||||||
}
|
}
|
||||||
return render(request, "main/index.html", context)
|
return render(request, "main/index.html", context)
|
||||||
|
|
||||||
|
@ -91,3 +86,33 @@ def del_invoice(request, uuid, invoice_id):
|
||||||
_invoice = get_object_or_404(Invoice, id=invoice_id)
|
_invoice = get_object_or_404(Invoice, id=invoice_id)
|
||||||
_invoice.delete()
|
_invoice.delete()
|
||||||
return redirect(transaction, uuid=uuid)
|
return redirect(transaction, uuid=uuid)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def category(request, uuid=None):
|
||||||
|
if uuid is None:
|
||||||
|
_category = Category()
|
||||||
|
_transactions = None
|
||||||
|
else:
|
||||||
|
_category = get_object_or_404(Category, id=uuid)
|
||||||
|
_transactions = Transaction.objects.filter(category=_category)
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"main/category.html",
|
||||||
|
{
|
||||||
|
"category": _category,
|
||||||
|
"form": CategoryForm(instance=_category),
|
||||||
|
"transactions": _transactions,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def update_category(request, uuid):
|
||||||
|
try:
|
||||||
|
_category = Category.objects.get(id=uuid)
|
||||||
|
except Category.DoesNotExist:
|
||||||
|
_category = Category(id=uuid)
|
||||||
|
_form = CategoryForm(request.POST, instance=_category)
|
||||||
|
_form.save()
|
||||||
|
return redirect(category, uuid=uuid)
|
||||||
|
|
Loading…
Reference in a new issue