This commit is contained in:
parent
87b8c3894e
commit
97aeace80a
@ -3,7 +3,7 @@ from ninja import Schema
|
|||||||
from ninja.security import APIKeyQuery
|
from ninja.security import APIKeyQuery
|
||||||
import datetime
|
import datetime
|
||||||
from ..accounts.models import User
|
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):
|
class ApiKey(APIKeyQuery):
|
||||||
@ -21,12 +21,31 @@ class ApiKey(APIKeyQuery):
|
|||||||
api = NinjaAPI(auth=ApiKey())
|
api = NinjaAPI(auth=ApiKey())
|
||||||
|
|
||||||
|
|
||||||
|
class View(Schema):
|
||||||
|
name: str
|
||||||
|
columns: dict
|
||||||
|
filters: dict
|
||||||
|
sort: str
|
||||||
|
|
||||||
|
|
||||||
class Thing(Schema):
|
class Thing(Schema):
|
||||||
id: int
|
id: int
|
||||||
data: dict
|
data: dict
|
||||||
type: str
|
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/")
|
@api.post("/thing/")
|
||||||
def sync_thing(request, thing: Thing):
|
def sync_thing(request, thing: Thing):
|
||||||
action = "none"
|
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
|
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):
|
class Thing(models.Model):
|
||||||
thing_id = models.PositiveIntegerField()
|
thing_id = models.PositiveIntegerField()
|
||||||
user = models.ForeignKey(User, related_name="things", on_delete=models.CASCADE)
|
user = models.ForeignKey(User, related_name="things", on_delete=models.CASCADE)
|
||||||
|
@ -1,3 +1,39 @@
|
|||||||
from django.shortcuts import render
|
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 django.urls import path, include
|
||||||
from debug_toolbar.toolbar import debug_toolbar_urls
|
from debug_toolbar.toolbar import debug_toolbar_urls
|
||||||
from apps.core.api import api
|
from apps.core.api import api
|
||||||
|
from apps.core import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("djadmin/", admin.site.urls),
|
path("djadmin/", admin.site.urls),
|
||||||
path("accounts/", include("allauth.urls")),
|
path("accounts/", include("allauth.urls")),
|
||||||
path("api/", api.urls),
|
path("api/", api.urls),
|
||||||
|
path("table/", views.table),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.DEBUG and not settings.IS_TESTING:
|
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