developing.rst 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. .. _plugin_developing:
  2. Developing new Plugins
  3. ======================
  4. If you want to write a plugin, it's a very good idea to checkout existing
  5. plugins. A good starting point for example is the `Portal Plugin`_.
  6. Also make sure to check out the cookiecutter-flaskbb-plugin project, which is a
  7. cookiecutter template which helps you to create new plugins.
  8. For example, the structure of a plugin could look like this:
  9. .. sourcecode:: text
  10. your_package_name
  11. |-- setup.py
  12. |-- my_plugin
  13. |-- __init__.py
  14. |-- views.py
  15. |-- models.py
  16. |-- forms.py
  17. |-- static
  18. | |-- style.css
  19. |-- templates
  20. |-- myplugin.html
  21. |-- migrations
  22. |-- 59f7c49b6289_init.py
  23. Metadata
  24. --------
  25. FlaskBB Plugins are usually following the naming scheme of
  26. ``flaskbb-plugin-YOUR_PLUGIN_NAME`` which should make them better
  27. distinguishable from other PyPI distributions.
  28. A proper plugin should have at least put the following metadata into
  29. the ``setup.py`` file.
  30. .. sourcecode:: python
  31. setup(
  32. name="flaskbb-plugin-YOUR_PLUGIN_NAME", # name on PyPI
  33. packages=["your_package_name"], # name of the folder your plugin is located in
  34. version='1.0',
  35. url=<url to your project>,
  36. license=<your license>,
  37. author=<you>,
  38. author_email=<your email>,
  39. description=<your short description>,
  40. long_description=__doc__,
  41. include_package_data=True,
  42. zip_safe=False,
  43. platforms='any',
  44. entry_points={
  45. 'flaskbb_plugin': [
  46. 'unique_name_of_plugin = your_package_name.pluginmodule', # most important part
  47. ]
  48. }
  49. )
  50. The most important part here is the ``entry_point``. Here you tell FlaskBB the
  51. unique name of your plugin and where your plugin module is located inside
  52. your project. Entry points are a feature that is provided by setuptools.
  53. FlaskBB looks up the ``flaskbb_plugin`` entrypoint to discover its plugins.
  54. Have a look at the `setup script`_ documentation and the `sample setup.py`_
  55. file to get a better idea what the ``setup.py`` file is all about it.
  56. For a full example, checkout the `Portal Plugin`_.
  57. .. _`setup script`: https://docs.python.org/3.6/distutils/setupscript.html#additional-meta-data
  58. .. _`sample setup.py`: https://github.com/pypa/sampleproject/blob/master/setup.py
  59. .. _`Portal Plugin`: https://github.com/sh4nks/flaskbb-plugins/tree/master/portal
  60. Settings
  61. --------
  62. Plugins can create settings which integrate with the 'Settings' tab of
  63. the Admin Panel.
  64. The settings are stored in a dictionary with a given structure. The name of
  65. the dictionary must be ``SETTINGS`` and be placed in the plugin module.
  66. The structure of the ``SETTINGS`` dictionary is best explained via an
  67. example::
  68. SETTINGS = {
  69. # This key has to be unique across FlaskBB.
  70. # Using a prefix is recommended.
  71. 'forum_ids': {
  72. # Default Value. The type of the default value depends on the
  73. # SettingValueType.
  74. 'value': [1],
  75. # The Setting Value Type.
  76. 'value_type': SettingValueType.selectmultiple,
  77. # The human readable name of your configuration variable
  78. 'name': "Forum IDs",
  79. # A short description of what the settings variable does
  80. 'description': ("The forum ids from which forums the posts "
  81. "should be displayed on the portal."),
  82. # extra stuff like the 'choices' in a select field or the
  83. # validators are defined in here
  84. 'extra': {"choices": available_forums, "coerce": int}
  85. }
  86. }
  87. .. currentmodule:: flaskbb.utils.forms
  88. .. table:: Available Setting Value Types
  89. :widths: auto
  90. ======================================== =================
  91. Setting Value Type Parsed & Saved As
  92. ======================================== =================
  93. :attr:`SettingValueType.string` :class:`str`
  94. :attr:`SettingValueType.integer` :class:`int`
  95. :attr:`SettingValueType.float` :class:`float`
  96. :attr:`SettingValueType.boolean` :class:`bool`
  97. :attr:`SettingValueType.select` :class:`list`
  98. :attr:`SettingValueType.selectmultiple` :class:`list`
  99. ======================================== =================
  100. .. table:: Available Additional Options via the ``extra`` Keyword
  101. =========== ====================== ========================================
  102. Options Applicable Types Description
  103. =========== ====================== ========================================
  104. ``min`` string, integer, float **Optional.** The minimum required
  105. length of the setting value. If used on
  106. a numeric type, it will check the
  107. minimum value.
  108. ``max`` string, integer, float **Optional.** The maximum required
  109. length of the setting value. If used on
  110. a numeric type, it will check the
  111. maximum value.
  112. ``choices`` select, selectmultiple **Required.** A callable which returns
  113. a sequence of (value, label) pairs.
  114. ``coerce`` select, selectmultiple **Optional.** Coerces the select values
  115. to the given type.
  116. =========== ====================== ========================================
  117. Validating the size of the integer/float and the length of the string fields
  118. is also possible via the ``min`` and ``max`` keywords::
  119. 'recent_topics': {
  120. ...
  121. 'extra': {"min": 1},
  122. },
  123. The ``select`` and ``selectmultiple`` fields have to provide a callback which
  124. lists all the available choices. This is done via the ``choices`` keyword.
  125. In addition to that they can also specify the ``coerce`` keyword which will
  126. coerce the input value into the specified type.::
  127. 'forum_ids': {
  128. ...
  129. 'extra': {"choices": available_forums, "coerce": int}
  130. }
  131. For more information see the :ref:`settings` chapter.