patricia patricia - 28 days ago 11
Python Question

Django-CMS custom plugin not showing data in published pages

I created a custom plugin for my project in Django/Django-CMS and the plugin has a list of testimonials that the user pick when adding the plugin to the page. The model is this:

class TestimonialsPlugin(CMSPlugin):
n_testimonials = models.PositiveIntegerField(
verbose_name=_('Number of Testimonials'), default=5)

speed_autoplay = models.PositiveIntegerField(
verbose_name=_('Speed of slider (milliseconds)'), default=3000)

picked_testimonials = models.ManyToManyField(Testimonials,
verbose_name=_('picked_testimonials'),
blank=True, null=True)


In the edit mode I can se the testimonials in my page and I can publish without errors but when I see the published page the testimonials doesn't show. The plugin template is being rendered but the picked_testimonials gives
None
. Here's the template:

<div class="max-width1440 block clearfix relative">
<div class="small-only-text-left small-12 small-offset-0 medium-text-center medium-offset-1 medium-10 large-offset-1 large-10 column pt-px60 pb-px40 pl-px40 pr-px40 slider-testimonials">
{% for testimonial in instance.picked_testimonials.all %}
{% if forloop.counter0 < instance.n_testimonials %}
<div class="slider column">
<blockquote class="acta_mediumitalic size36 pl-px80 pr-px80 line-height140">
{% render_model testimonial "description" %}
</blockquote>

<div class="mt-px30">
<p class="acta_book size20 softblack">{{ testimonial.author }},<span>{{ testimonial.city }}</span>
</p>
</div>
</div>

{% endif %}
{% endfor %}
</div>
</div>

Answer

When a page is published, a copy of a plugin is created - which does include plugin's fields but not any relations. There is a provision in the CMS to provide copy method for exactly this purpose, see example from documentation:

class ArticlePluginModel(CMSPlugin):
    title = models.CharField(max_length=50)
    sections = models.ManyToManyField(Section)

    def copy_relations(self, oldinstance):
        self.sections = oldinstance.sections.all()

The important bit is the copy_relations, which ensures that the new object has the same relational links.

In your case, something along these lines should work:

class TestimonialsPlugin(CMSPlugin):
    n_testimonials = models.PositiveIntegerField(
        verbose_name=_('Number of Testimonials'), default=5)

    speed_autoplay = models.PositiveIntegerField(
        verbose_name=_('Speed of slider (milliseconds)'), default=3000)

    picked_testimonials = models.ManyToManyField(Testimonials,
                                                 verbose_name=_('picked_testimonials'),
                                                 blank=True, null=True)

    def copy_relations(self, oldinstance):
        self.picked_testimonials = oldinstance.picked_testimonials.all()
Comments