fix(admin): register moved hogflow and cdp admins via package init#60652
Merged
Conversation
The workflows and cdp model moves left their admin classes split across submodules of an admin/ package with an empty __init__. autodiscover_modules only imports the package __init__, so HogFlow, HogFunction, Plugin, and PluginConfig stopped appearing in Django admin. Import the submodules from each package __init__ so their @admin.register decorators fire, and add a regression test.
These workflows models had no Django admin before. Register read-oriented admins (FK fields readonly so they don't trigger full-table select widgets) and extend the registration regression test to cover them.
Contributor
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
posthog/admin/test_admin.py:178-182
The team prefers parameterised tests. A `for` loop over models in a single test method means a failure on the first unregistered model silences all subsequent ones. `@pytest.mark.parametrize` gives independent pass/fail signals per model and clearer CI output.
```suggestion
@pytest.mark.parametrize(
"model",
[HogFlow, HogFlowTemplate, HogFlowBatchJob, HogFunction, Plugin, PluginConfig],
ids=lambda m: m.__name__,
)
def test_moved_product_models_are_registered(self, model):
# Tests skip the lazy admin registry, so trigger registration explicitly.
register_all_admin()
assert admin.site.is_registered(model), f"{model.__name__} is not registered in Django admin"
```
Reviews (1): Last reviewed commit: "feat(admin): add HogFlowTemplate and Hog..." | Re-trigger Greptile |
Independent pass/fail signal per model instead of a single loop that stops at the first failure.
meikelmosby
approved these changes
Jun 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The recent move of the workflows and CDP models into their product apps (#60248) also relocated their Django admin classes into
admin/packages (products/cdp/backend/admin/andproducts/workflows/backend/admin/), split across submodules — but the package__init__.pyfiles were left empty.PostHog registers admins lazily through
autodiscover_modules("admin"), which imports only each app's top-leveladminmodule — i.e. the package's__init__.py. With an empty__init__, the submodules holding the@admin.registerdecorators were never imported, soHogFlow,HogFunction,Plugin, andPluginConfigsilently disappeared from Django admin. Every other product uses a singleadmin.pyfile, which autodiscover imports directly, so only these two packaged products were affected.Changes
Fix the regression — import the decorator-bearing submodules from each package
__init__.pyso their@admin.registerdecorators fire during autodiscover. This restores exactly the four admins that existed before the move (HogFlow,HogFunction,Plugin,PluginConfig).New admins (net-new, not part of the regression) — while verifying the workflows admin section, two workflows models had never had a Django admin at all. This PR adds them:
HogFlowTemplate— workflow templates, grouped under Workflows.HogFlowBatchJob— batch/broadcast job runs, grouped under Workflows.Both are read-oriented: foreign-key fields (
team,created_by, andhog_flowfor the batch job) are declaredreadonlyso the admin change pages don't render full-table<select>widgets, and JSON payload fields are readonly.team/hog_flowrender as links to their respective admin change pages.Regression test —
posthog/admin/test_admin.py::TestProductAdminRegistrationasserts all six models are registered afterregister_all_admin().How did you test this code?
I manually tested with locally checked out branch that all the models load as they should.
I'm an agent — I did not do manual UI testing. Automated verification only:
admin.site.is_registered(...): before the fix the four moved models returnedFalse; after, allTrue. Confirmed the two new models register and their admin change/changelist URLs reverse cleanly.__init__.pyfix and passes with it.ruff check/ruff formatclean; pre-commit hooks includingty checkpassed.🤖 Agent context
Authored by Claude Code at the request of the PR author.
Root cause traced to #60248: that move turned two products'
adminmodules into packages whose__init__.pywas empty, breaking theautodiscover_modules("admin")registration path. Chose explicit submodule imports over the central registry's dynamicpkgutil.iter_modulesapproach since there are only a few files and it's clearer/grep-friendly. After confirming nothing was missing relative to the pre-move baseline, the author asked to also add admins for the two previously-unregistered workflows models (HogFlowTemplate,HogFlowBatchJob) — these are additive.plugin_attachment_inlineis intentionally not imported explicitly: it has no@admin.registerdecorator and is already pulled in transitively byplugin_config_admin.Note for reviewers:
HogFlowBatchJobhas apost_savesignal that enqueues a real job invocation on create. The admin allows creates by default (consistent with other admins); flag if you'd prefer add disabled there.https://claude.ai/code/session_01JaMLKbh61S5uYBQvBgCM77