Skip to content

Commit b23806e

Browse files
committed
docs: Improved clarity
1 parent 0c46222 commit b23806e

File tree

4 files changed

+105
-49
lines changed

4 files changed

+105
-49
lines changed

docs/source/reference.rst

+13-9
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ plugins.
488488
Management commands
489489
*******************
490490

491-
Management commands are run by typing ``./manage.py frontend command`` in the
491+
Management commands are run by typing ``python -m manage frontend command`` in the
492492
project directory. ``command`` can be one of the following:
493493

494494
``migrate``
@@ -505,14 +505,18 @@ project directory. ``command`` can be one of the following:
505505
The drawback is, that references might become stale. This command prints all
506506
stale references, their plugins and pages/placeholder they belong to.
507507

508-
``sync_permissions users`` or ``sync_permissions groups``
509-
Django allows to set permissions for each user and group on a per plugin
510-
level. This might become somewhat tedious which is why this command
511-
will sync permissions. For each user or group it will copy the permissions
512-
of ``djangocms_frontend.models.FrontendUIItem`` to all installed
513-
``djangocms-frontend`` plugins. If you need to change permissions for all
514-
plugins this requires you only to change them for ``FrontendUIItem`` and
515-
then syncing the new permission with these commands.
508+
.. _sync_permissions:
509+
510+
``sync_permissions``
511+
This command syncs permissions for users or groups. It is run with one of
512+
the following arguments:
513+
514+
- ``users``: Syncs permissions for all users.
515+
- ``groups``: Syncs permissions for all groups.
516+
517+
Permissions are copied from the ``FrontendUIItem`` model to all installed
518+
plugins. This way you can set permissions for all plugins by setting them
519+
for ``FrontendUIItem`` and then syncing them.
516520

517521

518522
*************

docs/source/tutorial/custom_components.rst

+34-22
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,20 @@ Building Custom Frontend Components
99

1010
.. versionadded:: 2.0
1111

12-
custom frontend components are a powerful tool for content editors, allowing them to build pages without needing
13-
in-depth knowledge of design, HTML, or nested structures. Editors can simply add content to pre-defined
12+
Custom frontend components are a powerful tool for content editors, allowing them to build pages without
13+
needing in-depth knowledge of design, HTML, or nested structures. Editors can simply add content to pre-defined
1414
components, creating visually cohesive pages with ease.
1515

16-
When working with `Tailwind CSS <https://tailwindcss.com>`_, for example, you
17-
either create your custom frontend components or customize components from providers,
18-
e.g. `Tailwind UI <https://tailwindui.com>`_,
19-
`Flowbite <https://flowbite.com>`_, or the community
20-
`Tailwind Components <https://tailwindcomponents.com>`_.
16+
When working with `Tailwind CSS <https://tailwindcss.com>`_, for example, you either create your custom
17+
frontend components or customize components from providers, e.g. `Tailwind UI <https://tailwindui.com>`_,
18+
`Flowbite <https://flowbite.com>`_, or the community `Tailwind Components <https://tailwindcomponents.com>`_.
2119

2220
With django CMS you make your components available to the content editors to simply add them to a page by a
2321
click **and** frontend developers for use in templates from a single source.
2422

23+
Custom frontend components are more versatile than template components, but require some minimal Python coding.
24+
Technically, you create a custom frontend component by declaring its change form and rendering template.
25+
2526
Installation
2627
============
2728

@@ -32,8 +33,6 @@ If you do not use the built-in components, you do not need to add them to your `
3233
.. code-block:: python
3334
3435
INSTALLED_APPS = [
35-
# Optional dependencies
36-
'djangocms_icon',
3736
'easy_thumbnails',
3837
'djangocms_link', # Required if djangocms_frontend.contrib.link is used
3938
# Main frontend app - pre-built components not needed
@@ -71,7 +70,7 @@ Ensure your app has the following structure::
7170
migrations/
7271
models.py
7372
templates/
74-
components/
73+
theme/
7574
hero.html
7675
views.py
7776
admin.py
@@ -95,20 +94,19 @@ Add a ``cms_components.py`` file to the ``theme`` app (see structure above):
9594
class MyHeroComponent(CMSFrontendComponent):
9695
class Meta:
9796
# declare plugin properties
98-
name = "My Hero Component"
99-
render_template = "components/hero.html"
100-
allow_children = True
101-
mixins = ["Background"]
97+
name = "My Hero Component" # Name displayed in the CMS admin interface
98+
render_template = "theme/hero.html" # Template used to render the component
99+
allow_children = True # Allow child plugins inside this component
100+
mixins = ["Background"] # Add background styling options
102101
# for more complex components, you can add fieldsets
103102
104-
# declare fields
103+
# Declare fields for the component
105104
title = forms.CharField(required=True)
106105
slogan = forms.CharField(required=True, widget=forms.Textarea)
107106
hero_image = ImageFormField(required=True)
108107
109-
# add description for the structure board
110108
def get_short_description(self):
111-
return self.title
109+
return self.title # Display the title in the structure board
112110
113111
@components.register
114112
class MyButton(CMSFrontendComponent):
@@ -149,7 +147,10 @@ The templates could be, for example:
149147
{% endchildplugins %}
150148
</div>
151149
<div class="hidden lg:mt-0 lg:col-span-5 lg:flex">
152-
<img src="{{ instance.hero_image.url }}" alt="{{ instance.image_related.alt }}">
150+
{# Get the related object of the image field which itself is just a dict #}
151+
{% with image=instance.hero_image|get_related_object %}
152+
<img src="{{ image.url }}" alt="{{ image.alt }}">
153+
{% endwith %}
153154
</div>
154155
</div>
155156
</section>
@@ -167,8 +168,18 @@ The templates could be, for example:
167168
As always, django CMS manages styling and JavaScript dependencies with django-sekizai.
168169
In this example, we add the Tailwind CSS CDN to the ``js`` block.
169170

170-
Understanding the Code
171-
----------------------
171+
172+
.. note::
173+
174+
The component instance is available in the template as ``instance``. This is a proxy model of the
175+
``FrontendUIItem`` model, which is a subclass of Django's ``Model`` class. The instance has all the
176+
fields declared in the component class.
177+
178+
Additionally, if the component does not have a field called ``instance``, the fields themselves are
179+
available directly in the template. Both ways are equivalent::
180+
181+
{{ instance.title }} {{ title }}
182+
{{ instance.slogan }} {{ slogan }}
172183

173184

174185

@@ -179,8 +190,9 @@ Custom frontend components are a powerful tool for developers, but they have a l
179190

180191
**Limited Python code**: Custom components are (indirect) subclasses of Django's ``AdminForm`` class
181192
and can contain Python code to modify the behavior of a form. You cannot directly add Python code to
182-
the resulting plugin class with the exception of ``get_render_template()`` and ``save_model()``.
183-
Similarly, you cannot add Python code the model class, in this case with the exception of ``get_short_description()``.
193+
the resulting plugin class with the exception of ``get_render_template()``. Similarly, you cannot add
194+
Python code the model class, in this case with the exception of ``get_short_description()``.
195+
184196

185197
Conclusion
186198
==========

docs/source/tutorial/index.rst

+2-4
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@ that gets the job done for your project.
3434
but also the most complex, since template, plugin, and forms need to be created.
3535
For custom plugin development, see the :ref:`how-to-add-frontend-plugins` guide.
3636

37+
---------
3738

38-
Tutorials
39-
#########
40-
41-
39+
**Start with one of the following tutorials:**
4240

4341
.. toctree::
4442
:maxdepth: 1

docs/source/tutorial/template_components.rst

+56-14
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ If you do not use the built-in components, you do not need to add them to your `
3434
.. code-block:: python
3535
3636
INSTALLED_APPS = [
37-
# Optional dependencies
38-
'djangocms_icon',
3937
'easy_thumbnails',
4038
'djangocms_link', # Required if djangocms_frontend.contrib.link is used
4139
# Main frontend app - built-in components from contrib not needed
@@ -67,7 +65,7 @@ as required for ``djangocms-frontend`` template components.
6765
Directory Structure
6866
-------------------
6967

70-
The templte component lives in the template directory of any of your apps.
68+
The template component lives in the template directory of any of your apps.
7169
Ensure your DjangoCMS app has the following structure::
7270

7371
theme_app/
@@ -117,7 +115,10 @@ Then, add the following code::
117115
{% childplugins %}{% endchildplugins %}
118116
</div>
119117
<div class="hidden lg:mt-0 lg:col-span-5 lg:flex">
120-
<img src="{{ hero_image.url }}">
118+
{# Get the related object of the image field which itself is just a dict #}
119+
{% with image=instance.hero_image|get_related_object %}
120+
<img src="{{ image.url }}" alt="{{ image.alt }}">
121+
{% endwith %}
121122
</div>
122123
</div>
123124
</section>
@@ -133,7 +134,7 @@ Component Declaration
133134
{% cms_component "Hero" name=_("My Hero Component") %}
134135
135136
This tag **declares** the component and assigns it a name (``Hero``). This is used internally
136-
by django CMS to identify the plguin later. The ``name`` parameter is used to display the
137+
by django CMS to identify the plugin later. The ``name`` parameter is used to display the
137138
component in the CMS admin interface. Internally the command declares a ``CMSFrontendComponent``
138139
class. All named arguments are added to the component's Meta class.
139140

@@ -205,27 +206,36 @@ content, i.e. add/remove ``{% field %}`` tags, or change the ``{% cms_component
205206
the Django server to apply the changes.
206207

207208
1. Restart your Django server.
208-
2. Create a new page end edit it.
209+
2. Create a new page And edit it.
209210
3. Add a new **Hero component** to a page from the plugin picker.
210211
4. Fill in the **title**, **slogan**, and **hero image** fields.
211212
5. Save and publish the page.
212213

213214
Using the component in your templates
214215
-------------------------------------
215216

216-
To use the component in your templates, you can use the ``{% plugin %}`` tag with the component's name.
217-
For example, to render the **Hero component** in a template, use the following code::
217+
To use the component in your templates outside django CMS, you can use the ``{% plugin %}`` tag with the
218+
component's name. For example, to render the **Hero component** in a template, use the following code::
218219

219220
{% load frontend %}
220221
{% plugin "hero" title=_("Welcome to my new website") slogan=_("Building successful websites since 1896") %}
221222

223+
.. note::
224+
Do not forget to register the component with :attr:`CMS_COMPONENT_PLUGINS`. If you needed to list the single
225+
component in the setting, the hero component's dotted path to its plugin would be
226+
``djangocms_frontend.cms_plugins.HeroPlugin``.
227+
222228

223229
Adding inline-editing to the component
224230
--------------------------------------
225231

226-
When using `djangocms-text <https://github.com/django-cms/djangocms-text>`_, fields of the component can be
227-
marked as inline fields to activate inline editing. Simply replace ``{{ title }}`` and/or ``{{ slogan }}`` with
228-
``{% inline_field "title" %}`` and/or ``{% inline_field "slogan" %}``::
232+
When using `djangocms-text <https://github.com/django-cms/djangocms-text>`_, `CharField` and `HTMLFormField` fields
233+
of the component can be marked as inline fields to activate inline editing. Inline-editing fields can be changed in
234+
the edit endpoint by simply clicking inside and typing over the text - without the need to open an edit dialogue for
235+
the component.
236+
237+
Simply replace ``{{ title }}`` and/or ``{{ slogan }}`` with ``{% inline_field "title" %}`` and/or
238+
``{% inline_field "slogan" %}``::
229239

230240
<h1>{% inline_field "title" %}</h1>
231241
<p>{% inline_field "slogan" %}</p>
@@ -253,12 +263,44 @@ Template components are a powerful tool for developers, but they have some limit
253263
Classes are intantiated by default, for example. This is ok for ``widget=forms.Textarea``, but potentially not
254264
for more complex cases.
255265

266+
267+
Trouble Shooting
268+
================
269+
270+
If the component does not appear in the plugin picker, check the following:
271+
272+
1. **INSTALLED_APPS**: Verify that the app containing the component is listed in your ``INSTALLED_APPS`` setting.
273+
274+
2. **Template Location**: Ensure the template file is located in the correct directory structure:
275+
``templates/<app_name>/cms_components/`` inside your app.
276+
277+
3. **Server Restart**: Restart the Django server after creating or modifying the component template. Changes in
278+
the declarative part are only reflected after server restart.
279+
280+
4. **Rendering exceptions**: The template component will only be added if it renders without exception. Make
281+
sure it does not fail if the context is empty. Check the server logs for errors during startup. Missing
282+
dependencies or syntax errors in the template can prevent the component from being registered.
283+
284+
5. **Migration module**: Make sure the app has a migration module. If not, create one with
285+
``python -m manage makemigrations <app_name>``.
286+
287+
6. **Permissions**: Add the necessary permissions for the user/group if you are not the superuser.
288+
Also see :ref:`sync_permissions`.
289+
290+
If the issue persists, double-check the template syntax and ensure all required fields are properly defined.
291+
256292
Conclusion
257293
==========
258294

259-
You have successfully created a **djangocms-frontend template component** using ``cms_component``!
260-
This structure allows editors to easily customize hero sections while maintaining a reusable
261-
and structured design.
295+
In this tutorial, you learned how to create a reusable **Hero component** using ``djangocms-frontend``.
296+
This approach allows you to:
297+
298+
- Simplify component creation for editors by offering inline editing.
299+
- Maintain consistent design across your website by reusing the component.
300+
- Extend functionality without writing Python code.
301+
302+
By following these steps, you can create additional components tailored to your project's needs.
303+
262304

263305
.. note::
264306

0 commit comments

Comments
 (0)