-
Notifications
You must be signed in to change notification settings - Fork 9
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
add decorator which forces django template admin #565
Conversation
""" | ||
A list_display column containing a checkbox widget. | ||
""" | ||
del self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh
del [attr]
is to just my LSP up from complaining about unused attrs. del just removes the variable from local (function) context. When you're defining an actual method in a class its smart enough to ignore self
, but not here.
I was annoyed at having to do it at first, but grew to appreciate having a list of unused attrs at the top
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have time to play around with this locally but it seems like we would also need to override the templates for the admin? Right now they're being rendered with jinja, htmx, alpine in many cases. But maybe I'm just unclear on what this PR is solving
Good catch. I forgot to move over the settings change from my test app. I'm pointing DTL at a completely separate template dir. Correct me if this is a bad assumption, but I think it's cleanest to just completely divorce all template customization between the two loaders -- have two sets of customized templates (if we ever even want to customize any of the DTL templates, that is). |
@@ -211,7 +211,7 @@ | |||
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND | |||
"BACKEND": "django.template.backends.django.DjangoTemplates", | |||
# https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs | |||
"DIRS": [APP_DIR / "templates"], | |||
"DIRS": [APP_DIR / "dtl_templates"], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only problem I see with this is that now we need to check every time there is a django update if these files have changed. I can't think of a better way to divorce them though given the constraints
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to include the dtl_tempaltes dir in this PR as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all cases being adequately captured by this PR (not all but hopefully enough):
- The DTL will be used instead of Jinja2
- DTL will look for templates defined locally
- By default (unless we add one), it will never find a locally defined template, because even the base dir it's looking in does not exist
- It will default back to the base django templates
specifically
re django update collisions: I don't think this makes us any more vulnerable to collisions than we would otherwise be
re adding the dir: It'll fail gracefully if the file isn't found: https://github.com/django/django/blob/d1855c4847215f3afe3708736be13388bb6437eb/django/template/loaders/filesystem.py#L20 (I did not include the dir in my test project)
edit: to be more exact, it'll fail gracefully assuming it does eventually find a template. and since the admin does not expect you to have defined any templates locally, we can be confident it'll find a default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh sorry, I may have misinterpreted because of the line the comment was attached to -- If you're referring to the methods the decorator is overriding. yes absolutely that is vulnerable to the underlying django updating. I tried to minimize the surface area but it's a fundamentally hacky approach. EXTREMELY HAPPY to throw all of this away in favor of a less fragile approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No you had it right the first comment, I meant the templates. That's awesome that'll just fail and go back to the default in django so I'm good with that. The methods you mentioned don't seem to scary about being updated too often and us needing to fix
Known exceptions to PR
https://github.com/django/django/blob/b7a17b0ea0a2061bae752a3a2292007d41825814/django/contrib/admin/widgets.py#L245
Any field rendered through this widget wrapper. I have not found a sane way to inject a renderer into this
Dead Ends
Here are some dead ends I went down, preserved here so I feel better about the time spent
overwrite jinja renderer
example:
problem:
At this point in the code there is no context for whether the template is being rendered inside an admin template. The base admin templates include
"admin/"
in their path, but the sub-templates (e.g. fields) they render do not. You don't have any more helpful context here than is given to the regex which is already filtering out base admin templates correctly.However for debugging purposes something like this is helpful for identifying the templates that have fallen into jinja2-land
A loathsome global
example:
problem
This "works" in contrived local testing. However...
Globals are a code-smell on their own. And in this case I believe this would cause all kinds of nonsense in an async environment.
Notice also the
using=None
kwarg in theselect_template
function? That seemed promising, but django does not pass this value from anywhere sane, and in many cases passes no value. It's either a vestigial or overly-hopeful feature.Keep you in django template land once you find yourself there
example
problem
This was only a half-hearted attempt as mentioned above, django admin rarely passes any information about previously used renderers down to sub templates. It effectively does not matter how the parent template was rendered.
Other Notes
Throughout this whole process it has felt like I was just missing something especially around
https://github.com/django/django/blob/b7a17b0ea0a2061bae752a3a2292007d41825814/django/template/loader.py#L22
(and get_template above that)
Like there was some cleaner way to cut the gordion knot that I just wasn't seeing.
Digging into this problem has soured me a bit in general regarding django admin. There's a lot more competing organization and patterns than I had thought.