This commit is contained in:
parent
87b8c3894e
commit
97aeace80a
@ -3,7 +3,7 @@ from ninja import Schema
|
||||
from ninja.security import APIKeyQuery
|
||||
import datetime
|
||||
from ..accounts.models import User
|
||||
from .models import ThingEdit, Thing as ThingModel
|
||||
from .models import ThingEdit, Thing as ThingModel, View as ViewModel
|
||||
|
||||
|
||||
class ApiKey(APIKeyQuery):
|
||||
@ -21,12 +21,31 @@ class ApiKey(APIKeyQuery):
|
||||
api = NinjaAPI(auth=ApiKey())
|
||||
|
||||
|
||||
class View(Schema):
|
||||
name: str
|
||||
columns: dict
|
||||
filters: dict
|
||||
sort: str
|
||||
|
||||
|
||||
class Thing(Schema):
|
||||
id: int
|
||||
data: dict
|
||||
type: str
|
||||
|
||||
|
||||
@api.post("/view/")
|
||||
def sync_view(request, view: View):
|
||||
ViewModel.objects.update_or_create(
|
||||
name=view.name,
|
||||
defaults=dict(
|
||||
columns=view.columns,
|
||||
filters=view.filters,
|
||||
sort=view.sort,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@api.post("/thing/")
|
||||
def sync_thing(request, thing: Thing):
|
||||
action = "none"
|
||||
|
32
apps/core/migrations/0004_view_alter_thing_deleted.py
Normal file
32
apps/core/migrations/0004_view_alter_thing_deleted.py
Normal file
@ -0,0 +1,32 @@
|
||||
# Generated by Django 5.2 on 2025-05-04 02:50
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("core", "0003_alter_thing_created_at"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="View",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=100)),
|
||||
("columns", models.JSONField()),
|
||||
("filters", models.JSONField()),
|
||||
("sort", models.CharField()),
|
||||
],
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="thing",
|
||||
name="deleted",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
@ -2,6 +2,13 @@ from django.db import models
|
||||
from ..accounts.models import User
|
||||
|
||||
|
||||
class View(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
columns = models.JSONField()
|
||||
filters = models.JSONField()
|
||||
sort = models.CharField()
|
||||
|
||||
|
||||
class Thing(models.Model):
|
||||
thing_id = models.PositiveIntegerField()
|
||||
user = models.ForeignKey(User, related_name="things", on_delete=models.CASCADE)
|
||||
|
@ -1,3 +1,39 @@
|
||||
from django.shortcuts import render
|
||||
from ..accounts.models import User
|
||||
from .models import Thing, View
|
||||
|
||||
# Create your views here.
|
||||
|
||||
def attr_then_dict(thing, field):
|
||||
try:
|
||||
return getattr(thing, field)
|
||||
except AttributeError:
|
||||
return thing.data.get(field, "")
|
||||
|
||||
|
||||
def thing_to_row(view, thing):
|
||||
"""convert one thing to corresponding row dict"""
|
||||
return [attr_then_dict(thing, col["field_name"]) for col in view.columns.values()]
|
||||
|
||||
|
||||
def table(request):
|
||||
token = request.GET.get("token")
|
||||
view_name = request.GET.get("view")
|
||||
user = User.objects.get(username=token)
|
||||
view = View.objects.get(name=view_name)
|
||||
things = Thing.objects.filter(user=user, deleted=False)
|
||||
for field, val in view.filters.items():
|
||||
if field == "type":
|
||||
things = things.filter(type=val)
|
||||
else:
|
||||
val = val.split(",")
|
||||
if len(val) == 1:
|
||||
things = things.filter(**{f"data__{field}": val})
|
||||
else:
|
||||
things = things.filter(**{f"data__{field}__in": val})
|
||||
|
||||
things = things.order_by(*[f"data__{sort}" for sort in view.sort.split(",")])
|
||||
|
||||
# execute query
|
||||
rows = (thing_to_row(view, thing) for thing in things)
|
||||
|
||||
return render(request, "thingtable.html", {"rows": rows, "view": view})
|
||||
|
@ -3,11 +3,13 @@ from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from debug_toolbar.toolbar import debug_toolbar_urls
|
||||
from apps.core.api import api
|
||||
from apps.core import views
|
||||
|
||||
urlpatterns = [
|
||||
path("djadmin/", admin.site.urls),
|
||||
path("accounts/", include("allauth.urls")),
|
||||
path("api/", api.urls),
|
||||
path("table/", views.table),
|
||||
]
|
||||
|
||||
if settings.DEBUG and not settings.IS_TESTING:
|
||||
|
20
templates/thingtable.html
Normal file
20
templates/thingtable.html
Normal file
@ -0,0 +1,20 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{% for col in view.columns %}
|
||||
<th>{{ col }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in rows %}
|
||||
<tr>
|
||||
{% for item in row %}
|
||||
<td>
|
||||
{{ item }}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
Loading…
Reference in New Issue
Block a user