{"id":16992811,"url":"https://github.com/jamesturk/django-markupfield","last_synced_at":"2025-04-04T16:13:35.716Z","repository":{"id":573265,"uuid":"205216","full_name":"jamesturk/django-markupfield","owner":"jamesturk","description":"📑 a MarkupField for Django","archived":false,"fork":false,"pushed_at":"2023-12-09T07:32:28.000Z","size":235,"stargazers_count":194,"open_issues_count":2,"forks_count":40,"subscribers_count":10,"default_branch":"main","last_synced_at":"2024-10-15T03:30:55.993Z","etag":null,"topics":["database","django","markdown","markup","restructuredtext"],"latest_commit_sha":null,"homepage":"http://pypi.python.org/pypi/django-markupfield","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"mattbaird/elastigo","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamesturk.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.txt","dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"jamesturk","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2009-05-19T21:08:41.000Z","updated_at":"2024-03-13T19:48:16.000Z","dependencies_parsed_at":"2024-06-18T18:35:20.284Z","dependency_job_id":"a66625b5-1e1f-4021-9091-e91f53ad0244","html_url":"https://github.com/jamesturk/django-markupfield","commit_stats":{"total_commits":235,"total_committers":18,"mean_commits":"13.055555555555555","dds":"0.32765957446808514","last_synced_commit":"e7e7b6e0d23ec887731f6b0372fa4b37e2ec755d"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesturk%2Fdjango-markupfield","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesturk%2Fdjango-markupfield/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesturk%2Fdjango-markupfield/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesturk%2Fdjango-markupfield/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamesturk","download_url":"https://codeload.github.com/jamesturk/django-markupfield/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208139,"owners_count":20901570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","django","markdown","markup","restructuredtext"],"created_at":"2024-10-14T03:30:17.004Z","updated_at":"2025-04-04T16:13:35.700Z","avatar_url":"https://github.com/jamesturk.png","language":"Python","funding_links":["https://github.com/sponsors/jamesturk"],"categories":["Python"],"sub_categories":[],"readme":"==================\ndjango-markupfield\n==================\n\n.. image:: https://github.com/jamesturk/django-markupfield/workflows/Test/badge.svg\n\n.. image:: https://img.shields.io/pypi/v/django-markupfield.svg\n    :target: https://pypi.python.org/pypi/django-markupfield\n\nAn implementation of a custom MarkupField for Django.  A MarkupField is in \nessence a TextField with an associated markup type.  The field also caches\nits rendered value on the assumption that disk space is cheaper than CPU \ncycles in a web application.\n\nInstallation\n============\n\nThe recommended way to install django-markupfield is with\n`pip \u003chttps://pypi.python.org/pypi/pip\u003e`_\n\nIt is not necessary to add ``'markupfield'`` to your ``INSTALLED_APPS``, it\nmerely needs to be on your ``PYTHONPATH``. However, to use titled markup you\neither add ``'markupfield'`` to your ``INSTALLED_APPS`` or add the\ncorresponding translations to your project translation.\n\nRequirements\n------------\n\nRequires Django \u003e= 2.2 and 3.6+\n\n* 1.5.x is the last release to officially support Django \u003c 2.2 or Python 2.7\n* 1.4.x is the last release to officially support Django \u003c 1.11\n* 1.3.x is the last release to officially support Django 1.4 or Python 3.3\n\nSettings\n========\n\nTo best make use of MarkupField you should define the\n``MARKUP_FIELD_TYPES`` setting, a mapping of strings to callables that\n'render' a markup type::\n\n    import markdown\n    from docutils.core import publish_parts\n\n    def render_rest(markup):\n        parts = publish_parts(source=markup, writer_name=\"html4css1\")\n        return parts[\"fragment\"]\n\n    MARKUP_FIELD_TYPES = (\n        ('markdown', markdown.markdown),\n        ('ReST', render_rest),\n    )\n\nIf you do not define a ``MARKUP_FIELD_TYPES`` then one is provided with the\nfollowing markup types available:\n\nhtml:\n    allows HTML, potentially unsafe\nplain:\n    plain text markup, calls urlize and replaces text with linebreaks\nmarkdown:\n    default `markdown`_ renderer (only if `markdown`_ is installed)\nrestructuredtext:\n    default `ReST`_ renderer (only if `docutils`_ is installed)\n\nIt is also possible to override ``MARKUP_FIELD_TYPES`` on a per-field basis\nby passing the ``markup_choices`` option to a ``MarkupField`` in your model\ndeclaration.\n\n.. _`ReST`: http://docutils.sourceforge.net/rst.html\n.. _`markdown`: https://pypi.python.org/pypi/Markdown\n.. _`docutils`: http://docutils.sourceforge.net/\n\nUsage\n=====\n\nUsing MarkupField is relatively easy, it can be used in any model definition::\n\n    from django.db import models\n    from markupfield.fields import MarkupField\n\n    class Article(models.Model):\n        title = models.CharField(max_length=100)\n        slug = models.SlugField(max_length=100)\n        body = MarkupField()\n\n``Article`` objects can then be created with any markup type defined in\n``MARKUP_FIELD_TYPES``::\n\n    Article.objects.create(title='some article', slug='some-article',\n                           body='*fancy*', body_markup_type='markdown')\n\nYou will notice that a field named ``body_markup_type`` exists that you did\nnot declare, MarkupField actually creates two extra fields here \n``body_markup_type`` and ``_body_rendered``.  These fields are always named\naccording to the name of the declared ``MarkupField``.\n\nArguments\n---------\n\n``MarkupField`` also takes three optional arguments.  Either\n``default_markup_type`` and ``markup_type`` arguments may be specified but\nnot both.\n\n``default_markup_type``:\n    Set a markup_type that the field will default to if one is not specified.\n    It is still possible to edit the markup type attribute and it will appear\n    by default in ModelForms.\n\n``markup_type``:\n    Set markup type that the field will always use, ``editable=False`` is set\n    on the hidden field so it is not shown in ModelForms.\n\n``markup_choices``:\n    A replacement list of markup choices to be used in lieu of\n    ``MARKUP_FIELD_TYPES`` on a per-field basis.\n\n``escape_html``:\n    A flag (False by default) indicating that the input should be regarded\n    as untrusted and as such will be run through Django's ``escape`` filter.\n\n\nExamples\n~~~~~~~~\n\n``MarkupField`` that will default to using markdown but allow the user a choice::\n\n    MarkupField(default_markup_type='markdown')\n\n``MarkupField`` that will use ReST and not provide a choice on forms::\n\n    MarkupField(markup_type='restructuredtext')\n\n``MarkupField`` that will use a custom set of renderers::\n\n    CUSTOM_RENDERERS = (\n        ('markdown', markdown.markdown),\n        ('wiki', my_wiki_render_func)\n    )\n    MarkupField(markup_choices=CUSTOM_RENDERERS)\n\n.. note::\n    When using ``markdown``, be sure to use ``markdown.markdown`` and not\n    the ``markdown.Markdown`` class, the class requires an explicit ``reset``\n    to function properly in some cases.  (See [issue #40](https://github.com/jamesturk/django-markupfield/issues/40)\n    for details.)\n\n\nAccessing a MarkupField on a model\n----------------------------------\n\nWhen accessing an attribute of a model that was declared as a ``MarkupField``\na special ``Markup`` object is returned.  The ``Markup`` object has three\nparameters:\n\n``raw``:\n    The unrendered markup.\n``markup_type``:\n    The markup type.\n``rendered``:\n    The rendered HTML version of ``raw``, this attribute is read-only.\n\nThis object has a ``__unicode__`` method that calls\n``django.utils.safestring.mark_safe`` on ``rendered`` allowing MarkupField\nobjects to appear in templates as their rendered selfs without any template\ntag or having to access ``rendered`` directly.\n\nAssuming the ``Article`` model above::\n\n    \u003e\u003e\u003e a = Article.objects.all()[0]\n    \u003e\u003e\u003e a.body.raw\n    u'*fancy*'\n    \u003e\u003e\u003e a.body.markup_type\n    u'markdown'\n    \u003e\u003e\u003e a.body.rendered\n    u'\u003cp\u003e\u003cem\u003efancy\u003c/em\u003e\u003c/p\u003e'\n    \u003e\u003e\u003e print unicode(a.body)\n    \u003cp\u003e\u003cem\u003efancy\u003c/em\u003e\u003c/p\u003e\n\nAssignment to ``a.body`` is equivalent to assignment to ``a.body.raw`` and\nassignment to ``a.body_markup_type`` is equivalent to assignment to \n``a.body.markup_type``.\n\n.. important::\n    Keeping in mind that ``body`` is MarkupField instance is particullary important with ``default`` or ``default_if_none`` filter for model that could be blank. If ``body``'s ``rendered`` is ``None`` or empty string (``\"\"``) these filters will *not* evaluate ``body`` as falsy to display default text::\n    \n        {{ a.body|default:\"\u003cmissing body\u003e\" }}\n    \n    That's because ``body`` is regular non-``None`` MarkupField instance. To let ``default`` or ``default_if_none`` filters to work evaluate ``rendered`` MarkupField attribute instead. To prevent escaping HTML for the case ``rendered`` is truethy, finish chain with ``safe`` filter::\n    \n        {{ a.body.rendered|default:\"\u003cmissing body\u003e\"|safe }} \n\n.. note::\n    a.body.rendered is only updated when a.save() is called\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesturk%2Fdjango-markupfield","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesturk%2Fdjango-markupfield","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesturk%2Fdjango-markupfield/lists"}