Architecture

Core Design: Grouper + Content Pattern

djangocms-custom-content uses a two-model pattern:

Grouper - One per item (e.g., Article)
  • Persistent identity

  • Minimal data

  • Links to many Content objects

Content - One per language (e.g., ArticleContent)
  • Language-specific data (title, body)

  • Version history automatically supported

  • Quick language switching

Why This Design?

  • Multilingual by default - Add language by creating new Content object

  • Version history - Old Content objects remain in database

  • Clean separation - Grouper is identity, Content is presentation

  • Efficient - One query per language

Example:

# One Article (grouper)
article = Article.objects.create(name="My Article")

# Multiple ArticleContent (per language)
content_en = ArticleContent.objects.create(
    article=article,
    language="en",
    title="English Title",
    body="English content..."
)

content_de = ArticleContent.objects.create(
    article=article,
    language="de",
    title="German Title",
    body="German content..."
)

M2M Relations Use Generic FK

Generic foreign keys allow flexible relationships:

class PersonRelation(AbstractCustomRelation):
    instance = ForeignKey(PersonContent)        # Which person
    content_type = ForeignKey(ContentType)      # What model type
    object_id = PositiveIntegerField()          # Which object
    related_field_name = CharField()             # "authors", "contributors", etc.

This single model stores relationships to ANY Django model without FK hardcoding.

See Also