Skip to content

Commit 2a907b2

Browse files
committed
Add an AGENTS.md file
1 parent aceee19 commit 2a907b2

File tree

1 file changed

+246
-0
lines changed

1 file changed

+246
-0
lines changed

AGENTS.md

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
# Agent Instructions for django-content-editor
2+
3+
This document provides guidance for AI coding agents working on the django-content-editor codebase.
4+
5+
## Repository Overview
6+
7+
django-content-editor is a Django library for editing structured content in the admin interface. It extends Django's inlines mechanism to manage heterogeneous collections of content blocks (plugins) organized into regions, commonly used for CMS-style content editing.
8+
9+
**Key directories:**
10+
- `content_editor/` - Main package code
11+
- `tests/testapp/` - Test application and test suite
12+
- `docs/` - Sphinx documentation (reStructuredText)
13+
14+
**Core modules:**
15+
- `admin.py` - ContentEditor, ContentEditorInline, and admin check classes
16+
- `models.py` - PluginBase model and Region class
17+
- `contents.py` - Contents class and helpers for fetching/organizing content
18+
- `checks.py` - Django system checks
19+
20+
## Development Workflow
21+
22+
### Before Making Changes
23+
24+
1. **Always read files before editing them** - Use the Read tool to understand existing code structure
25+
2. **Check for existing tests** - Look in `tests/testapp/test_*.py` for related test coverage
26+
3. **Review system checks** - Changes to admin classes should consider the checks in `checks.py`
27+
4. **Check documentation** - Related docs may need updates in `docs/`
28+
29+
### Testing Requirements
30+
31+
**Run tests through tox:**
32+
```bash
33+
tox -e py312-dj52 # Run specific Python/Django version
34+
tox -l # List available test environments
35+
```
36+
37+
**Test suite structure:**
38+
- `test_content_editor.py` - Basic ContentEditor functionality
39+
- `test_contents.py` - Contents class and helpers
40+
- `test_checks.py` - Django system checks
41+
- `test_playwright.py` - Browser-based integration tests
42+
- `test_playwright_helpers.py` - Playwright utilities
43+
44+
**Important testing practices:**
45+
- Write tests for new functionality in appropriate test files
46+
- Place imports at the top of test files, not inside test methods
47+
- Playwright tests require Chromium installation (handled by tox)
48+
- Tests must pass before changes are considered complete
49+
- Integration tests use pytest-playwright and test real browser interactions
50+
51+
### Code Style
52+
53+
- Follow existing code style (project uses pre-commit hooks with ruff and biome)
54+
- Run `prek` to execute pre-commit hooks before committing
55+
- Keep code minimal and focused - avoid over-engineering
56+
- Prefer editing existing files over creating new ones
57+
- Don't add comments, docstrings, or type annotations to unchanged code
58+
- Only add error handling where truly necessary (at boundaries)
59+
60+
## Architecture Considerations
61+
62+
### Plugin System
63+
64+
**PluginBase model:**
65+
- Abstract base class for all content plugins
66+
- Provides `parent`, `region`, and `ordering` fields
67+
- Plugins are typically defined per-project (not in this library)
68+
69+
**ContentEditorInline:**
70+
- Specialized StackedInline for plugins
71+
- Used as a marker to differentiate plugins from regular inlines
72+
- Can restrict plugins to specific regions using `regions` attribute
73+
- Supports customization via `icon`, `color`, `button` attributes
74+
75+
**Important patterns:**
76+
- ContentEditor identifies plugins by checking `isinstance(inline, ContentEditorInline)`
77+
- The `.create()` classmethod dynamically creates inline classes
78+
- Plugins are rendered in regions using drag-and-drop interface
79+
80+
### Region System
81+
82+
**Regions organize content:**
83+
- Defined as a `regions` attribute/property on the model
84+
- Must return a list of `Region` instances
85+
- Each region has `key`, `title`, and optional `inherited` attributes
86+
- Region keys must be valid Python identifiers
87+
88+
**Contents class:**
89+
- Groups content blocks by region
90+
- Supports inheritance (empty regions can inherit from parent instances)
91+
- Access content via attribute (`contents.main`) or subscription (`contents["main"]`)
92+
- Unknown regions go to `_unknown_region_contents`
93+
94+
### System Checks
95+
96+
The library provides four system checks:
97+
- `content_editor.E001` - Missing region/ordering in fieldsets
98+
- `content_editor.E002` - Missing regions attribute on model
99+
- `content_editor.E003` - Regions not iterable
100+
- `content_editor.I001` - Non-abstract base classes warning
101+
102+
**Check implementation:**
103+
- Admin checks use custom `checks_class` on admin classes
104+
- Model checks use `@register()` decorator
105+
- All checks documented in `docs/checks.rst`
106+
107+
## Documentation Practices
108+
109+
### Sphinx Documentation Structure
110+
111+
Documentation is in `docs/` using reStructuredText:
112+
- `index.rst` - Main entry with toctree
113+
- `installation.rst` - Installation instructions
114+
- `quickstart.rst` - Getting started guide
115+
- `admin-classes.rst` - ContentEditor, ContentEditorInline, RefinedModelAdmin
116+
- `contents.rst` - Contents class and regions
117+
- `checks.rst` - System checks reference
118+
- `design-decisions.rst` - Architecture explanations
119+
- `changelog.rst` - Links to CHANGELOG.rst
120+
121+
### When Adding Documentation
122+
123+
1. Determine appropriate .rst file (or create new one if needed)
124+
2. Keep documentation concise and practical
125+
3. Use code-block directives with Python syntax highlighting
126+
4. Add new files to index.rst toctree
127+
5. Follow existing RST formatting conventions
128+
6. Assume readers have Django knowledge
129+
130+
### README.rst
131+
132+
Keep the README minimal - it just points to Read the Docs. Full documentation lives in `docs/`.
133+
134+
## Common Patterns
135+
136+
### Creating Plugin Inlines
137+
138+
Use the `.create()` classmethod for convenience:
139+
```python
140+
ContentEditorInline.create(
141+
model=MyPlugin,
142+
icon="description", # Material icon
143+
color="oklch(0.5 0.2 330)", # Custom color
144+
regions={"main"}, # Restrict to regions
145+
)
146+
```
147+
148+
### Region Restrictions
149+
150+
Two helper functions for restricting plugins to regions:
151+
- `allow_regions({"main", "sidebar"})` - Only allow these regions
152+
- `deny_regions({"footer"})` - Allow all except these regions
153+
154+
The `deny_regions` helper returns a callable that computes allowed regions dynamically.
155+
156+
### Contents Helpers
157+
158+
Prefer using helper functions over instantiating `Contents` directly:
159+
```python
160+
# Single item
161+
contents = contents_for_item(article, plugins=[RichText, Download])
162+
163+
# Multiple items (with batching)
164+
contents = contents_for_items(articles, plugins=[RichText, Download])
165+
166+
# With inheritance
167+
contents = contents_for_item(
168+
page,
169+
plugins=[RichText],
170+
inherit_from=page.ancestors().reverse(),
171+
)
172+
```
173+
174+
### Field Visibility
175+
176+
ContentEditorInline automatically hides `region` and `ordering` fields using `HiddenInput` widget. These fields must exist in fieldsets but won't be visible to users.
177+
178+
## Git and Version Control
179+
180+
- Repository is at `github.com/matthiask/django-content-editor`
181+
- Follow conventional commit messages
182+
- Don't commit unless explicitly requested
183+
- Never use `--no-verify` or skip hooks
184+
- Stage specific files by name (avoid `git add -A`)
185+
- Watch for sensitive files (.env, credentials) before staging
186+
187+
## File Organization
188+
189+
**Don't create unnecessary files:**
190+
- No new markdown/documentation files without explicit request
191+
- Don't create helper utilities for one-time operations
192+
- Don't add configuration for hypothetical future needs
193+
194+
**Static files:**
195+
- Admin CSS in `content_editor/static/content_editor/`
196+
- Admin JavaScript in same directory
197+
- Material icons CSS included
198+
199+
**Translations:**
200+
- Locale files in `content_editor/locale/`
201+
- Use Django's translation functions (`gettext`, `gettext_lazy`)
202+
203+
## When Stuck
204+
205+
If you need to understand complex behavior:
206+
1. Read the test files - they demonstrate real usage patterns
207+
2. Check `admin.py` for the ContentEditor implementation
208+
3. Look at `contents.py` for the Contents class and helpers
209+
4. Review `models.py` for PluginBase and Region
210+
5. Check Playwright tests for browser interaction behavior
211+
6. Look at `docs/` for architectural explanations
212+
213+
## JavaScript and Frontend
214+
215+
The content editor includes significant JavaScript:
216+
- `content_editor.js` - Main drag-and-drop functionality
217+
- `save_shortcut.js` - Ctrl+S / Cmd+S shortcuts
218+
- `tabbed_fieldsets.js` - Tabbed fieldset support
219+
220+
**Context object:**
221+
- JavaScript receives configuration via JSON script tag
222+
- Context includes plugins, regions, messages, permissions
223+
- Generated by `_content_editor_context()` method in admin
224+
225+
## Common Issues
226+
227+
**Plugin not appearing:**
228+
- Ensure inline uses `ContentEditorInline` (not just `StackedInline`)
229+
- Check if plugin is restricted to regions the model doesn't have
230+
- Verify model inherits from `PluginBase`
231+
232+
**Region errors:**
233+
- Model must have `regions` attribute (not method)
234+
- Regions must be iterable (list, tuple, set) not string
235+
- Region keys must be valid Python identifiers
236+
237+
**Fieldset validation:**
238+
- ContentEditorInline fieldsets must include `region` and `ordering`
239+
- These fields are automatically hidden (don't add HiddenInput manually)
240+
241+
## References
242+
243+
- Django documentation: https://docs.djangoproject.com/
244+
- Read the Docs: https://django-content-editor.readthedocs.io/
245+
- Related project FeinCMS: https://github.com/feincms/feincms/
246+
- Related project feincms3: https://feincms3.readthedocs.io/

0 commit comments

Comments
 (0)