Munif
Munif

Reputation: 21

How to customize the django cms plugin

I am using Django CMS Frontend. I want to customize the plugins. For example, I want to add extra fields to the default Card plugin. I tried using Plugin Form

So far I have done this.

cms_plugins.py

class CustomPlugin(CMSPluginBase):
    form = CardForm
    name = "Custom Card"
    render_template = "siteindex/card_render.html"
    change_form_template = "siteindex/card.html"
    cache = False

    def render(self, context, instance, placeholder):
        context = super().render(context, instance, placeholder)
        return context


plugin_pool.register_plugin(CustomPlugin)

cms_forms.py

from djangocms_frontend.contrib.card.forms import CardForm
from django.db import models
class CustomForm(CardForm):
    title = forms.CharField(max_length=255, required=False, label="title")

    class Meta:
        model = CustomCard
        fields = "__all__"

card.html


{% extends "admin/cms/page/plugin/change_form.html" %}

card_render.html

{{ instance.title }}}

After that when I try to add a plugin I get this error (https://i.sstatic.net/2f7fjFSM.png)

Upvotes: 1

Views: 105

Answers (2)

Munif
Munif

Reputation: 21

I solved it by adding the title to the untangled_fields on the CustomForm.

cms_plugins.py

@plugin_pool.register_plugin
class CustomCardPlugin(CardPlugin):
    model = CustomCard
    render_template = "siteindex/card_render.html"
    change_form_template = "admin/custom_card/change_form.html"
    name = "Custom Card"
    form = CustomCardForm
    fieldsets = [
        (
            None,
            {
                "fields": (
                    "title",
                    "card_alignment",
                    (
                        "card_text_color",
                        "card_outline",
                    ),
                    "card_full_height",
                ),
            },
        ),
    ]

    def save_model(self, request, obj, form, change):
        if form.is_valid():
            title = form.cleaned_data.get("title")
            obj.title = title
            print(obj.__dict__)
        super().save_model(request, obj, form, change)

cms_models.py

class CustomCard(Card):
    title = models.CharField(max_length=255, blank=True, null=True)

cms_forms.py

class CustomCardForm(CardForm):
    title = forms.CharField(max_length=255, required=True)

def clean(self):
    super().clean()

class Meta:
    model = CustomCard
    exclude = []
    untangled_fields = [
        "title",
    ]

    entangled_fields = {
        "config": [
            "card_alignment",
            "card_outline",
            "card_text_color",
            "card_full_height",
            "attributes",
        ]
    }

card_render.html

<div class="bg-{{instance.background_context}} {{instance.margin_x}} {{instance.margin_y}}">
<h3 class="text-{{instance.card_text_color}}">{{ instance.title }}</h3>
<div class="card-content">
    <div class="layout-{{ instance.layout }}">
        <div class="card-type-{{ instance.card_type }}">
            <div class="text-alignment-{{ instance.text_alignment }}">
            </div>
        </div>
    </div>
</div>

Upvotes: 1

Fabian
Fabian

Reputation: 850

You attach a djangocms-frontend card form to your custom plugin that does not have the fields of the djangocms-frontend card plugins. Hence the error.

djangocms-frontend plugins are extensible as described in its documentation by using Mixins. This would allow you to extend the existing card plugin.

If you want to create your own card plugin, try subclassing

  • djangocms_frontend.contrib.cms_plugins.CardPlugin for updating the fieldsets and the render template
  • djangocms_frontend.contrib.forms.CardForm

Note that the forms use the django-entangled package which means you'll have to do something like:

from djangocms_frontend.contrib.card.forms import CardForm

class CustomForm(CardForm):
    title = forms.CharField(max_length=255, required=False, label="title")

    class Meta:
        entangled_fields = {
            "config": [
                "title",
            ]
        }

No need for any changes in the model. The entangled form stores the additional title field in a JSON field in "config".

Hope this helps. Let me know how you succeed.

Upvotes: 1

Related Questions