intending to document more about how our schemas work, i found our code currently buries this somewhere in `/nix/store`.
this change exposes that generated file in the project structure as well, facilitating inspection of our data schema in this more generic format.
Reviewed-on: Fediversity/Fediversity#351
Reviewed-by: Nicolas Jeannerod <nicolas.jeannerod@moduscreate.com>
Co-authored-by: Kiara Grouwstra <kiara@procolix.eu>
Co-committed-by: Kiara Grouwstra <kiara@procolix.eu>
this shows a proof of concept for generating Django forms from NixOS modules
note that the form behavior is still rather clumsy and doesn't exactly map to the module semantics:
- since forms can only be sent wholesale, empty form fields will show up as empty strings
and break validation without additional cleanup (not done here)
- it's not possible to faithfully translate `type = submodule { /* ... */}; default = {};`, since the default
is translated to an empty dict `{}`. this is because the JSON schema converter does not preserve type information.
this can be added by making it use `$defs` [1], but that would likely amount to half a rewrite
- there's a glitch in enum default values that needs to be fixed in `datamodel-code-generator` [0]
[0]: dd44480359/src/datamodel_code_generator/parser/base.py (L1015)
[1]: https://json-schema.org/understanding-json-schema/structuring#defs
a generated file will be placed into the source (by the development shell and the package respectively)
that declares Pydantic types from which to render the form. it looks something like this:
```python
from __future__ import annotations
from enum import Enum
from typing import Optional
from pydantic import BaseModel, Extra, Field
from drf_pydantic import BaseModel
class Domain(Enum):
fediversity_net = 'fediversity.net'
# ...
class Model(BaseModel):
class Config:
extra = Extra.forbid
domain: Optional[Domain] = Field(
'fediversity.net',
description='Apex domain under which the services will be deployed.\n',
)
# ...
```
This setup is greatly inspired by the one used for [0], although with
notable modifications, such as:
- a SASS preprocessor and CSS compressor
- more streamlined NixOS integration tests
- cleaned up service configuration
- a few notes on how to do things better in the future
[0]: https://github.com/Nix-Security-WG/nix-security-tracker/
Apart from cloning the Nix setup, there were additional steps:
- Create an empty `src` directory, since the package requires it
- In the development shell, run `django-admin startproject panel src`
Note that while you can already do
```bash
manage migrate
manage runserver
```
the NixOS integration tests will fail, since `settings.py` needs
careful massaging to expose knobs that can be turned from our systemd
wrapper. The required changes are introduced in the next commit to make
them observable.
Noteworthy related work:
- https://github.com/sephii/django.nix
Rather mature setup with a clean interface, uses Caddy as reverse proxy.
- https://git.dgnum.eu/mdebray/djangonix
A work-in-progress attempt to capture more moving parts through the
module system, in particular secrets.
- https://github.com/DavHau/django-nixos
Out of date and somewhat simplistic, but serves as a reasonable
example for what can be done
I chose the variant I'm intimately familiar with in order to be able to
pass on knowledge or help with maintenance. But for the future
I strongly recommend picking the good bits from the other
implementations that control complexity in static configuration parts
through Nix expressions.