Argus icon indicating copy to clipboard operation
Argus copied to clipboard

Add model to hold user preferences

Open hmpf opened this issue 1 year ago • 2 comments
trafficstars

Closes #505

For Uninett/argus-htmx-frontend#9, Uninett/argus-htmx-frontend#48

argus-htmx needs this, so far, for:

  • saving chosen theme
  • saving preferred date format

hmpf avatar Oct 02 '24 11:10 hmpf

Codecov Report

Attention: Patch coverage is 67.76316% with 49 lines in your changes missing coverage. Please review.

Project coverage is 82.84%. Comparing base (28d8216) to head (6d52c1f). Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/argus/auth/utils.py 23.33% 23 Missing :warning:
src/argus/auth/models.py 84.95% 17 Missing :warning:
src/argus/auth/context_processors.py 0.00% 9 Missing :warning:
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #889      +/-   ##
==========================================
- Coverage   83.39%   82.84%   -0.56%     
==========================================
  Files          98       99       +1     
  Lines        4156     4308     +152     
==========================================
+ Hits         3466     3569     +103     
- Misses        690      739      +49     

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

codecov-commenter avatar Oct 02 '24 11:10 codecov-commenter

perhaps instead of learning the namespace from the app_label and the classname, we can let the subclasses determine their own namespaces:

class MyPreferences(Preferences):
    NAMESPACE = 'my_prefs'

could alternatively name the attribute __namespace__

or we could go the class kwargs way:

class MyPreferences(Preferences, namespace='my_prefs):
    pass
class Preferences(model.Model):
    def __init_subclass__(cls, **kwargs):
        namespace = kwargs['namespace']
        ...

Although I guess the latter method may not work, since you'd not have the namespace available on the subclass anymore

elfjes avatar Oct 31 '24 09:10 elfjes

class MyPreferences(Preferences, namespace='my_prefs):
    pass
class Preferences(model.Model):
    def __init_subclass__(cls, **kwargs):
        namespace = kwargs['namespace']
        ...

Although I guess the latter method may not work, since you'd not have the namespace available on the subclass anymore

That should just be a matter of setting the attribute on the class after super in init_subclass. I'll check.

hmpf avatar Nov 01 '24 08:11 hmpf

class MyPreferences(Preferences, namespace='my_prefs):
    pass
class Preferences(model.Model):
    def __init_subclass__(cls, **kwargs):
        namespace = kwargs['namespace']
        ...

Although I guess the latter method may not work, since you'd not have the namespace available on the subclass anymore

That should just be a matter of setting the attribute on the class after super in init_subclass. I'll check.

Yeah, but then you might as well set the attribute directly on the subclass

elfjes avatar Nov 01 '24 09:11 elfjes

Although I guess the latter method may not work, since you'd not have the namespace available on the subclass anymore

That should just be a matter of setting the attribute on the class after super in init_subclass. I'll check.

Yeah, but then you might as well set the attribute directly on the subclass

.. which is the old-fashioned way to do it and possibly more readabale.

hmpf avatar Nov 01 '24 11:11 hmpf

One thing I am uncertain about: We have the constraint in preferences that the user and namespace together need to be unique, is this ensured somewhere to avoid that we don't get an internal server error due to that in case a user tries to do that

Do you by "user" mean somebody logged in to the frontend? No. Du you mean developer making a new preferences namespace? Oh yes, especially if they add new pages and don't reuse code like the "save_preference"-function.

There's a unique-constraint that may trigger a 500 yes.

The trick is to only use the methods and managers provided. By using Preferences.objects.create directly it is possible to trigger this. By using Preferences.save(force_insert) it is possible to trigger this. The code here doesn't use either, nor does the code in argus_htmx that depends on this. Adding guards to prevent this in future code I highly suspect is YAGNI, and may break other things in a domino-like fashion. Not worth it.

Making preferences manually via the admin should trigger this but the admin would catch it and make an error-message popup.

hmpf avatar Nov 11 '24 10:11 hmpf