Closes #268: Add display_expression for composite custom object names#586
Closes #268: Add display_expression for composite custom object names#586bctiemann wants to merge 8 commits into
Conversation
Adds a Jinja2 display_expression field to CustomObjectType. When set, CustomObject.__str__() renders it with all field values as context instead of falling back to the single primary-field display name. - models.py: display_expression CharField(max_length=500, blank=True) on CustomObjectType; CustomObject._render_display_expression() helper renders it via a SandboxedEnvironment (security); any rendering error silently falls through to the existing primary-field fallback - migration 0015 - forms.py: Display fieldset with display_expression - serializers.py: display_expression in CustomObjectTypeSerializer - customobjecttype.html: shows expression in code block when set - 5 tests: composite render, missing-field fallback, empty expression, rendering error, empty-result fallback Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Group verbose_name, verbose_name_plural, group_name, and display_expression into a Display fieldset positioned between Name and URL path/slug. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@claude /review |
|
Claude finished @bctiemann's task in 1m 48s —— View job PR Review: Add
|
…m, trailing separator docs
- Move _compile_display_template() after imports (not in the middle of them)
- Cache compiled Jinja2 templates via functools.lru_cache(maxsize=256)
keyed by expression string; avoids N recompilations on list views
- Move custom_object_type access inside the try block so RelatedObjectDoesNotExist
and deserialization errors also fall through silently
- Shorten _render_display_expression docstring to one line; move the
performance/caching note to inline comments
- Add clean_display_expression() to CustomObjectTypeForm: parses the
expression via SandboxedEnvironment().parse() and surfaces a
ValidationError with the Jinja2 error message on syntax errors
- Add display_expression (plus verbose_name, verbose_name_plural,
group_name) to CustomObjectTypeImportForm
- Extend help_text to warn about trailing separators when referenced
fields are blank, with the recommended {% if %} pattern
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…alues to ''
- _render_display_expression: coerce None return from get_display_value()
to '' so unset nullable fields render as empty string rather than 'None'
- test_trailing_separator_with_blank_optional_field: documents and tests
the dangling-separator behaviour vs the {% if %} guard pattern
- DisplayExpressionFormValidationTestCase: 4 tests covering valid expression,
blank expression, invalid Jinja2 syntax, and unclosed block tag
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes: #268
Summary
Adds a
display_expressionJinja2 template field toCustomObjectTypethat lets administrators compose the object display name from multiple field values, replacing the single-fieldprimarymarker approach when set.Example: a COT with
make,model, andserialfields can use{{ make }} - {{ model }}as its display expression so objects display asCisco - ASR1001instead of just the primary field value.How it works
display_expressionis aCharField(max_length=500, blank=True)onCustomObjectTypeCustomObject.__str__()calls a new_render_display_expression()helper that renders the expression via a Jinja2SandboxedEnvironmentwith all field values as contextjinja2.Undefined)Form layout
The form now has a Display fieldset grouping
verbose_name,verbose_name_plural,display_expression, andgroup_name— all fields that control how the type appears to users — positioned between the Name field and the URL path/slug field.Surface area
_render_display_expression()helper (separately testable/mockable)display_expressioninCustomObjectTypeSerializer<code>when setTest plan
makeandmodeltext fields; setdisplay_expression = {{ make }} - {{ model }}; verify objects display asMake - Model{% bad %}) falls back silently🤖 Generated with Claude Code