Search code examples
djangodjango-cms

How to update context in Django-CMS


I am trying add my apps' queryset of my ListView in context of my apphook, but i could not get the queryset. I have created two models my ServicePLuginModel and Service model.

class ServicePluginModel(CMSPlugin):

    title = models.CharField(_('title'),
        blank=True,
        help_text='Service Widget',
        max_length=64,
    )
class Service(CMSPlugin):
    # Attributes - Mandatory
    title = models.CharField(_('title'),
                    max_length=200, 
                    blank=False)

I have formed a ListView:

class ServiceListView(ListView):
    model = Service
    queryset = Service.objects.all()
    def get_context_data(self, **kwargs):
        context = super(ServiceListView).get_context_data(**kwargs)
        queryset = Service.objects.all()
        context["now"] = timezone.now()
        context.update({'object_list': queryset})
        context.update(kwargs)
        return super().get_context_data(**context)

        
    def render_to_response(self, context, **response_kwargs):
        # Shim to affect the CMS Toolbar only
        if self.request.toolbar and self.request.toolbar.edit_mode:
            menu = self.request.toolbar.get_or_create_menu('service-list-menu', 'Services')
            menu.add_break()

        return super(ServiceListView, self).render_to_response(context, **response_kwargs)

urls.py

app_name = 'services'
urlpatterns = [
    re_path('/', ServiceListView.as_view(), name='service-list'),
    re_path(r'^(?P<slug>[\w-]+)/?$', ServiceDetailView.as_view(), name='service_detail'),
]

my cms_plugins.py

@plugin_pool.register_plugin  # register the plugin
class ServicePluginPublisher(CMSPluginBase):
    model = ServicePluginModel # model where plugin data are saved
    module = _("Services")
    name = _("Service Plugin")  # name of the plugin in the interface
    cache = False
    render_template = "services/service_list.html"

    def render(self, context, instance, placeholder):
        context.update({'instance': instance })
        return context

cms_apps.py:

@apphook_pool.register  # register the application
class Servicesapphook(CMSApp):
    app_name = "services"
    name = "Services Application"

    def get_urls(self, page=None, language=None, **kwargs):
        return ["eldemmedya.apps.services.urls"]

and my service_list.html:

{% for service in object_list %}
  <li>
    <div class="cs_image_box cs_style_1">
      <div class="cs_image_box_number cs_primary_color cs_primary_font cs_fs_38 cs_semibold">{{ service.service_number }}</div>
      <a href="service-details.html" class="cs_image_box_img cs_radius_5 overflow-hidden">
        <img src="{% static 'img/studio-agency/service_img_1.jpeg' %}" alt="Service">
      </a>
      <div class="cs_image_box_info position-relative">
        <h2 class="cs_image_box_title cs_fs_29 cs_semibold"><a href="service-details.html">{{ service.title }}</a></h2>
        <p class="cs_image_box_subtitle mb-0">{{ service.content }}</p>
        <a href="service-details.html" class="cs_image_box_btn cs_center position-absolute rounded-circle">
          <img src="{{ service.photo|thumbnail_url:'service_image'}}" alt="{{ service.title }}" class="rounded-6">
        </a>
      </div>
    </div>
  </li>
  {% endfor %}

I cannot manage to add object_list to my context. Can you help me where to add context of my services queryset?

Thanks


Solution

  • So CMS plugins (instances of CMSPlugin) can be used on CMS pages. But when you create app hooks, plugins are handled differently.

    If these plugins are in use on other pages and you want to also bring them into the page(s) of your apphook, then you need to create a model instance in your app and then have a PlaceholderField on the model. Then you can render this model instance to a page and in turn, render the placeholder to display the attached plugins.

    CMS plugins need to be associated with a placeholder. You'll have these in your regular CMS templates I'd imagine, but when using apphooks things are a little different. Docs on placeholders outside of the CMS can be found here.

    It's a very complex application, but it's a very good example of how to implement the functionality of django-cms. Take a look over it's implementation of PlaceholderField here. In this you add a blog to a page and then create posts. Posts then get content added to them via PlaceholderField so that it feels like a regular page when you're editing and you can add all of the plugins that you regularly use.

    (And to clarify, I'm tech lead for the django-cms association.)