Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model/validate contents of user preferences jsonblob is needed #158

Open
hmpf opened this issue Oct 2, 2024 · 10 comments
Open

Model/validate contents of user preferences jsonblob is needed #158

hmpf opened this issue Oct 2, 2024 · 10 comments
Labels
backend Needs change in argus-server discussion

Comments

@hmpf
Copy link
Collaborator

hmpf commented Oct 2, 2024

See Uninett/Argus#889 for the place to store the jsonblob
See #9, #48 for why.

How do we model the user preferences?

We need it for the htmx frontend and don't need to make it visible in the API as of yet. We will be validating a json-blob. It is handy to use a django form when validating, well, form-data. I'd love to pass around a dataclass and generate anything else needed but generating is the problem.

I was thinking either flat

{  
  "theme": "dark",
  "page_size": 10,
  "datetime_format": "LOCALE"
}

or namespaced

{
  "argus-htmx": {
    "theme": "dark",
    "page_size": 10,
    "datetime_format": "LOCALE"
  }
}

The namespacing can also be added by adding a field to the preferences-model and making it a ForeignKey to our User instead of a OneToOneField.

@hmpf
Copy link
Collaborator Author

hmpf commented Oct 2, 2024

I have a branch with a form (and no namespacing) in progress.

@hmpf hmpf added backend Needs change in argus-server discussion labels Oct 2, 2024
@hmpf hmpf changed the title Model/validate contents og user preferences jsonblob Model/validate contents of user preferences jsonblob Oct 2, 2024
@hmpf hmpf changed the title Model/validate contents of user preferences jsonblob Model/validate contents of user preferences jsonblob is needed Oct 2, 2024
@hmpf
Copy link
Collaborator Author

hmpf commented Oct 2, 2024

There are dead libraries for converting between Django Forms and DRF serializers. A DRF serializer can be rendered as a form (with the help of a template tag), but cannot validate as a form.

@elfjes
Copy link
Contributor

elfjes commented Oct 3, 2024

I like (the idea of) the namespaced method. That way third parties (us) can easily add preferences as a serializer, and the form can be generated dynamically and we get validation out-of-the-box. Without namespacing it feels like this may be somewhat trickier. Also, it avoid collisions, and I have the feeling that if we don't do namespacing, then we'll end up with a pattern where we prefix the field names anyway, such as argus_theme and geant_beep

wrt namespaced objects being FK'd. I guess you'd want a unique key on (user_id, namespace)? Or even (user_id, namespace_id) and have another table that includes all valid namespaces, although that sounds overengineerd at first glance

@hmpf
Copy link
Collaborator Author

hmpf commented Oct 3, 2024

The thought was (user_id, namespace) yes. The form (without namespace) is shipped around and the using system looks for its namespace to store the form.cleaned_data.

Currently there is only "primitive" python types that are all JSON compatible that we need to store so no need for a serialization-step. That might change, but the serializer is in control of the using system anyway. Our existing frontend don't need this, so no API endpoint for that. Our source-systems are also technically users but they shouldn't use this system, if they ever need preferences that should go on the source model or source system model, maybe via a new model. Not currently a problem.

Maybe a registry-system like the admin. preference_users.register(USING_SYSTEM_TOKEN). Bah, better names needed.

@elfjes
Copy link
Contributor

elfjes commented Oct 3, 2024

The form (without namespace) is shipped around and the using system looks for its namespace to store the form.cleaned_data.

I'm not quite sure what you mean by that

Maybe a registry-system like the admin. preference_users.register(USING_SYSTEM_TOKEN). Bah, better names needed.

I like the concept of a registry for registering namespaces. I don't know what the USING_SYSTEM_TOKEN variable is supposed to be

@hmpf
Copy link
Collaborator Author

hmpf commented Oct 3, 2024

sigh Why do I keep forgetting about Proxy Models.

The USING_SYSTEM_TOKEN is the namespace, we could simply use the app-name since that must be unique anyway.

@elfjes
Copy link
Contributor

elfjes commented Oct 3, 2024

Ok I'd think registering would require a namespace + serializer

Using proxy models would also be interesting. You'd have class ArgusUserPreferences(models.Model): and we'd create class GeantUserPreferences(models.Model). If I understand my django correctly we'd still need to create the serializer though, right? And we still need to register that serializer to argus-htmx. But we'd be able to drop the namespacing most likely. And have better type consistency

@hmpf
Copy link
Collaborator Author

hmpf commented Oct 3, 2024

How to abuse proxy-models for fun and profit.

  • Have a model with a namespacing field
  • Have the proxy model enforce what to put in that field
  • Have the queryset/manager on that field only look up instances with the proxy's namespace in use
  • Have a a .clean-method on the model that is proxy-specific

@hmpf
Copy link
Collaborator Author

hmpf commented Oct 3, 2024

We wouldn't need to register this way. Naive base model in argus, proxy-models with all the implementation in apps.

@hmpf
Copy link
Collaborator Author

hmpf commented Oct 3, 2024

I abused proxy models in easydmp. Here's the mother model:

https://github.com/hmpf/easydmp/blob/de532aee33b03f9b580404dbf273713b12bd6275/src/easydmp/dmpt/models/base.py#L1461

The proxies are in easydmp.dmpt.models.questions.

(Background: Each model defines validation for one field, and its location in a dynamically morphing form. Each field is a node in a state machine. What you answer defines what questions you will later see.)

Argus's needs are different, there won't be a need to send around querysets with multiple types of proxies unless we make an API endpoint for backup purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend Needs change in argus-server discussion
Projects
Status: 🏗 In progress
Development

No branches or pull requests

2 participants