django-slugify-processor


Namedjango-slugify-processor JSON
Version 1.7.0 PyPI version JSON
download
home_pagehttps://django-slugify-processor.git-pull.com
Summarypipeline for slugification edgecases in django
upload_time2024-08-17 20:44:57
maintainerNone
docs_urlNone
authorTony Narlock
requires_python<4.0,>=3.8
licenseMIT
keywords django slug text
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-slugify-processor

Custom-[`slugify()`](https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.text.slugify)
support for django.

[![Python Package](https://img.shields.io/pypi/v/django-slugify-processor.svg)](https://pypi.org/project/django-slugify-processor/)
[![Build Status](https://github.com/tony/django-slugify-processor/workflows/tests/badge.svg)](https://django-slugify-processor.git-pull.com/)
[![Docs](https://github.com/tony/django-slugify-processor/workflows/docs/badge.svg)](https://github.com/tony/django-slugify-processor/actions?query=workflow%3Adocs)
[![Code Coverage](https://codecov.io/gh/tony/django-slugify-processor/branch/master/graph/badge.svg)](https://codecov.io/gh/tony/django-slugify-processor)
[![License](https://img.shields.io/github/license/tony/django-slugify-processor.svg)](https://github.com/tony/django-slugify-processor/blob/master/LICENSE)

# What are slugs?

_Slugs_ are URL's, typically generated from post titles, that you want to be both human readable and
a valid URL. They are SEO friendly.

Django provides a [`slugify()`](https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.text.slugify)
function which is also made available as a [default filter](https://github.com/django/django/blob/4.2.6/django/template/defaultfilters.py#L253-L261).

Django slugs can be automatically generated in django models via packages such as:

- [django-autoslug](https://pypi.python.org/pypi/django-autoslug)
  ([docs](https://pythonhosted.org/django-autoslug/),
  [github](https://github.com/neithere/django-autoslug))
- [django-extensions](https://pypi.python.org/pypi/django-extensions) via
  [AutoSlugField](https://django-extensions.readthedocs.io/en/latest/field_extensions.html)
  ([docs](https://django-extensions.readthedocs.io/en/latest/),
  [github](https://github.com/django-extensions/django-extensions))

# The problem

This project is based on an article from [devel.tech](https://devel.tech) covering
[django's import strings](https://devel.tech/tips/n/djms3tTe/how-django-uses-deferred-imports-to-scale/).

Corner cases exist with slugification. For instance:

| Term | [`django.utils.text.slugify`] | What you want |
| ---- | ----------------------------- | ------------- |
| C    | c (correct)                   | n/a           |
| C++  | c                             | cpp           |
| C#   | c                             | c-sharp       |

To make matters worse, if using a specialized model field like `AutoSlugField` from django-autoslug
or django-extensions, the default behavior may be to name the slugs for C++ and C# to "c-1", "c-2"
after "c" is taken.

Here's another case, acronyms / shorthands:

| Term               | [`django.utils.text.slugify`] | What you (may) want |
| ------------------ | ----------------------------- | ------------------- |
| New York City      | new-york-city                 | nyc                 |
| Y Combinator       | y-combinator                  | yc                  |
| Portland           | portland                      | pdx                 |
| Texas              | texas                         | tx                  |
| $                  | '' (empty)                    | usd, aud, etc?      |
| US$                | us                            | usd                 |
| A$                 | a                             | aud                 |
| bitcoin            | bitcoin                       | btc                 |
| United States      | united-states                 | usa                 |
| League of Legends  | league-of-legends             | league              |
| AppleĀ® iPod Touch | apple-ipod-touch              | ipod-touch          |

Each website and niche has its own edge cases for slugs. So we need a solution that can scale, where
you can craft your own functions.

# How django-slugify-processor helps

This builds on top of [`django.utils.text.slugify`] to handle your django project's edgecases. By
default, django-slugify-processor will be a pass through to django's default behavior. Adding
slugification functions via your Django project's settings file allows you to adjust.

[`django.utils.text.slugify`]: https://github.com/django/django/blob/4.2.6/django/template/defaultfilters.py#L253-L261

# Installation

```console
$ pip install django-slugify-processor
```

# Configure

To create a processor, create a function that accepts a string, and returns a string. Assume this is
_project/app/slugify_processors.py_:

```python
def my_processor(value):
   value = value.replace('++', 'pp')
   return value
```

Inside of your settings, add a `SLUGIFY_PROCESSORS` list of strings that points to the function.
Anything that's compatible with
[import_string](https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.module_loading.import_string),
in your settings file:

```python
SLUGIFY_PROCESSORS = [
   'project.app.slugify_processors.my_processor'
]
```

# Usage

## In normal django code

Import `slugify` from `django_slugify_processor.text`:

```python
from django_slugify_processor.text import slugify

print(slugify('C++'))
> 'cpp'
```

## Template code

django-slugify-processor is designed to override the built-in`slugify` filter.

### via load

You can load by default via `{% load django_slugify_processor %}` in your template.

In your settings `INSTALLED_APPS`:

```python
INSTALLED_APPS = [
    'django_slugify_processor'
]
```

In your template:

```django
{% load slugify_processor %}
{{"C++"|slugify}}
```

### via built-in

To make this available in all templates, in the `OPTIONS` of your template engine, add
`django_slugify_processor.template_tags`:

```python
TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'OPTIONS': {
        'builtins': [
            'django_slugify_processor.templatetags.slugify_processor',
        ],
    },
}]
```

From within the template file:

```django
{{"C++"|slugify}}
```

Output should be: cpp

## Models

For the most up to date documentation, view the documentation for the plugin you're using (e.g.
django-autoslug or django-extensions).

To use django-slugify-processor's `slugify` instead of django's default, there will be a field
option to use the function.

### django-extensions

Tested with 1.9.7 (2017-11-26):

```python
from django.db import models

from django_extensions.db.fields import AutoSlugField
from django_slugify_processors.text import slugify

class MyModel(models.Model):
    title = models.CharField(max_length=255)
    slug = AutoSlugField(
        populate_from='title',
        slugify_function=slugify
    )
```

### django-autoslug

Tested with 1.9.3 (2017-11-26):

```python
from django.db import models

from autoslug import AutoSlugField
from django_slugify_processors.text import slugify

class MyModel(models.Model):
    title = models.CharField(max_length=255)
    slug = AutoSlugField(
        populate_from='title',
        slugify=slugify
    )
```

# Credits

- tox.ini based off DRF's (BSD 2-clause licensed)
- yapf configuration based off RTD / devel.tech's (MIT-licensed)

# Project details

- python support >= 3.8, pypy3
- django support > 3.2,
- Source https://github.com/tony/django-slugify-processor
- Docs https://django-slugify-processor.git-pull.com
- API https://django-slugify-processor.git-pull.com/api.html
- Changelog https://django-slugify-processor.git-pull.com/history.html
- Issues https://github.com/tony/django-slugify-processor/issues
- Test Coverage https://codecov.io/gh/tony/django-slugify-processor
- pypi https://pypi.python.org/pypi/django-slugify-processor
- Open Hub https://www.openhub.net/p/django-slugify-processor
- License MIT
- git repo

  ```bash
  $ git clone https://github.com/tony/django-slugify-processor.git
  ```

## Development

Install stable:

```console
$ pip install django-slugify-processor
```

Local installation:

```console
$ git clone https://github.com/tony/django-slugify-processor.git
```

```console
$ cd ./django-slugify-processor
```

```console
$ poetry shell
```

```console
$ poetry install
```

Test:

```console
$ make test
```


            

Raw data

            {
    "_id": null,
    "home_page": "https://django-slugify-processor.git-pull.com",
    "name": "django-slugify-processor",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.8",
    "maintainer_email": null,
    "keywords": "django, slug, text",
    "author": "Tony Narlock",
    "author_email": "tony@git-pull.com",
    "download_url": "https://files.pythonhosted.org/packages/fe/f6/c9d54539722c488b39516e703fbaf4d015c25606b40dd51fcb09a00e658d/django_slugify_processor-1.7.0.tar.gz",
    "platform": null,
    "description": "# django-slugify-processor\n\nCustom-[`slugify()`](https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.text.slugify)\nsupport for django.\n\n[![Python Package](https://img.shields.io/pypi/v/django-slugify-processor.svg)](https://pypi.org/project/django-slugify-processor/)\n[![Build Status](https://github.com/tony/django-slugify-processor/workflows/tests/badge.svg)](https://django-slugify-processor.git-pull.com/)\n[![Docs](https://github.com/tony/django-slugify-processor/workflows/docs/badge.svg)](https://github.com/tony/django-slugify-processor/actions?query=workflow%3Adocs)\n[![Code Coverage](https://codecov.io/gh/tony/django-slugify-processor/branch/master/graph/badge.svg)](https://codecov.io/gh/tony/django-slugify-processor)\n[![License](https://img.shields.io/github/license/tony/django-slugify-processor.svg)](https://github.com/tony/django-slugify-processor/blob/master/LICENSE)\n\n# What are slugs?\n\n_Slugs_ are URL's, typically generated from post titles, that you want to be both human readable and\na valid URL. They are SEO friendly.\n\nDjango provides a [`slugify()`](https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.text.slugify)\nfunction which is also made available as a [default filter](https://github.com/django/django/blob/4.2.6/django/template/defaultfilters.py#L253-L261).\n\nDjango slugs can be automatically generated in django models via packages such as:\n\n- [django-autoslug](https://pypi.python.org/pypi/django-autoslug)\n  ([docs](https://pythonhosted.org/django-autoslug/),\n  [github](https://github.com/neithere/django-autoslug))\n- [django-extensions](https://pypi.python.org/pypi/django-extensions) via\n  [AutoSlugField](https://django-extensions.readthedocs.io/en/latest/field_extensions.html)\n  ([docs](https://django-extensions.readthedocs.io/en/latest/),\n  [github](https://github.com/django-extensions/django-extensions))\n\n# The problem\n\nThis project is based on an article from [devel.tech](https://devel.tech) covering\n[django's import strings](https://devel.tech/tips/n/djms3tTe/how-django-uses-deferred-imports-to-scale/).\n\nCorner cases exist with slugification. For instance:\n\n| Term | [`django.utils.text.slugify`] | What you want |\n| ---- | ----------------------------- | ------------- |\n| C    | c (correct)                   | n/a           |\n| C++  | c                             | cpp           |\n| C#   | c                             | c-sharp       |\n\nTo make matters worse, if using a specialized model field like `AutoSlugField` from django-autoslug\nor django-extensions, the default behavior may be to name the slugs for C++ and C# to \"c-1\", \"c-2\"\nafter \"c\" is taken.\n\nHere's another case, acronyms / shorthands:\n\n| Term               | [`django.utils.text.slugify`] | What you (may) want |\n| ------------------ | ----------------------------- | ------------------- |\n| New York City      | new-york-city                 | nyc                 |\n| Y Combinator       | y-combinator                  | yc                  |\n| Portland           | portland                      | pdx                 |\n| Texas              | texas                         | tx                  |\n| $                  | '' (empty)                    | usd, aud, etc?      |\n| US$                | us                            | usd                 |\n| A$                 | a                             | aud                 |\n| bitcoin            | bitcoin                       | btc                 |\n| United States      | united-states                 | usa                 |\n| League of Legends  | league-of-legends             | league              |\n| Apple\u00ae iPod Touch | apple-ipod-touch              | ipod-touch          |\n\nEach website and niche has its own edge cases for slugs. So we need a solution that can scale, where\nyou can craft your own functions.\n\n# How django-slugify-processor helps\n\nThis builds on top of [`django.utils.text.slugify`] to handle your django project's edgecases. By\ndefault, django-slugify-processor will be a pass through to django's default behavior. Adding\nslugification functions via your Django project's settings file allows you to adjust.\n\n[`django.utils.text.slugify`]: https://github.com/django/django/blob/4.2.6/django/template/defaultfilters.py#L253-L261\n\n# Installation\n\n```console\n$ pip install django-slugify-processor\n```\n\n# Configure\n\nTo create a processor, create a function that accepts a string, and returns a string. Assume this is\n_project/app/slugify_processors.py_:\n\n```python\ndef my_processor(value):\n   value = value.replace('++', 'pp')\n   return value\n```\n\nInside of your settings, add a `SLUGIFY_PROCESSORS` list of strings that points to the function.\nAnything that's compatible with\n[import_string](https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.module_loading.import_string),\nin your settings file:\n\n```python\nSLUGIFY_PROCESSORS = [\n   'project.app.slugify_processors.my_processor'\n]\n```\n\n# Usage\n\n## In normal django code\n\nImport `slugify` from `django_slugify_processor.text`:\n\n```python\nfrom django_slugify_processor.text import slugify\n\nprint(slugify('C++'))\n> 'cpp'\n```\n\n## Template code\n\ndjango-slugify-processor is designed to override the built-in`slugify` filter.\n\n### via load\n\nYou can load by default via `{% load django_slugify_processor %}` in your template.\n\nIn your settings `INSTALLED_APPS`:\n\n```python\nINSTALLED_APPS = [\n    'django_slugify_processor'\n]\n```\n\nIn your template:\n\n```django\n{% load slugify_processor %}\n{{\"C++\"|slugify}}\n```\n\n### via built-in\n\nTo make this available in all templates, in the `OPTIONS` of your template engine, add\n`django_slugify_processor.template_tags`:\n\n```python\nTEMPLATES = [{\n    'BACKEND': 'django.template.backends.django.DjangoTemplates',\n    'OPTIONS': {\n        'builtins': [\n            'django_slugify_processor.templatetags.slugify_processor',\n        ],\n    },\n}]\n```\n\nFrom within the template file:\n\n```django\n{{\"C++\"|slugify}}\n```\n\nOutput should be: cpp\n\n## Models\n\nFor the most up to date documentation, view the documentation for the plugin you're using (e.g.\ndjango-autoslug or django-extensions).\n\nTo use django-slugify-processor's `slugify` instead of django's default, there will be a field\noption to use the function.\n\n### django-extensions\n\nTested with 1.9.7 (2017-11-26):\n\n```python\nfrom django.db import models\n\nfrom django_extensions.db.fields import AutoSlugField\nfrom django_slugify_processors.text import slugify\n\nclass MyModel(models.Model):\n    title = models.CharField(max_length=255)\n    slug = AutoSlugField(\n        populate_from='title',\n        slugify_function=slugify\n    )\n```\n\n### django-autoslug\n\nTested with 1.9.3 (2017-11-26):\n\n```python\nfrom django.db import models\n\nfrom autoslug import AutoSlugField\nfrom django_slugify_processors.text import slugify\n\nclass MyModel(models.Model):\n    title = models.CharField(max_length=255)\n    slug = AutoSlugField(\n        populate_from='title',\n        slugify=slugify\n    )\n```\n\n# Credits\n\n- tox.ini based off DRF's (BSD 2-clause licensed)\n- yapf configuration based off RTD / devel.tech's (MIT-licensed)\n\n# Project details\n\n- python support >= 3.8, pypy3\n- django support > 3.2,\n- Source https://github.com/tony/django-slugify-processor\n- Docs https://django-slugify-processor.git-pull.com\n- API https://django-slugify-processor.git-pull.com/api.html\n- Changelog https://django-slugify-processor.git-pull.com/history.html\n- Issues https://github.com/tony/django-slugify-processor/issues\n- Test Coverage https://codecov.io/gh/tony/django-slugify-processor\n- pypi https://pypi.python.org/pypi/django-slugify-processor\n- Open Hub https://www.openhub.net/p/django-slugify-processor\n- License MIT\n- git repo\n\n  ```bash\n  $ git clone https://github.com/tony/django-slugify-processor.git\n  ```\n\n## Development\n\nInstall stable:\n\n```console\n$ pip install django-slugify-processor\n```\n\nLocal installation:\n\n```console\n$ git clone https://github.com/tony/django-slugify-processor.git\n```\n\n```console\n$ cd ./django-slugify-processor\n```\n\n```console\n$ poetry shell\n```\n\n```console\n$ poetry install\n```\n\nTest:\n\n```console\n$ make test\n```\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "pipeline for slugification edgecases in django",
    "version": "1.7.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/tony/django-slugify-processor/issues",
        "Changes": "https://github.com/tony/django-slugify-processor/blob/master/CHANGES",
        "Documentation": "https://django-slugify-processor.git-pull.com",
        "Homepage": "https://django-slugify-processor.git-pull.com",
        "Repository": "https://github.com/tony/django-slugify-processor"
    },
    "split_keywords": [
        "django",
        " slug",
        " text"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8901e5e5aadf796906555445420f58ab3b4de04a47eb1ae0aeadb77b0447aee3",
                "md5": "dda837cbac484a01012bfab0646a817a",
                "sha256": "a8ac43fef1835eac735ef5f8f99379afe948c689d808bedb5af5e46d0df90ab6"
            },
            "downloads": -1,
            "filename": "django_slugify_processor-1.7.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "dda837cbac484a01012bfab0646a817a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.8",
            "size": 7613,
            "upload_time": "2024-08-17T20:44:56",
            "upload_time_iso_8601": "2024-08-17T20:44:56.356606Z",
            "url": "https://files.pythonhosted.org/packages/89/01/e5e5aadf796906555445420f58ab3b4de04a47eb1ae0aeadb77b0447aee3/django_slugify_processor-1.7.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fef6c9d54539722c488b39516e703fbaf4d015c25606b40dd51fcb09a00e658d",
                "md5": "801f88e5902596c2b40d79bd5966c4c0",
                "sha256": "1446c13f5cdbea1cd6d85f5f72df09d6b954ecb119f1a02c69ad7e4979c48852"
            },
            "downloads": -1,
            "filename": "django_slugify_processor-1.7.0.tar.gz",
            "has_sig": false,
            "md5_digest": "801f88e5902596c2b40d79bd5966c4c0",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.8",
            "size": 10048,
            "upload_time": "2024-08-17T20:44:57",
            "upload_time_iso_8601": "2024-08-17T20:44:57.661996Z",
            "url": "https://files.pythonhosted.org/packages/fe/f6/c9d54539722c488b39516e703fbaf4d015c25606b40dd51fcb09a00e658d/django_slugify_processor-1.7.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-08-17 20:44:57",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "tony",
    "github_project": "django-slugify-processor",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "django-slugify-processor"
}
        
Elapsed time: 0.31655s