# django-link-shortener
[](https://github.com/ronaldgrn/django-link-shortener/actions/workflows/django-tests.yml)
[](https://pypi.org/project/django-link-shortener/)
[](https://pypi.org/project/django-link-shortener/)
[](https://codecov.io/gh/ronaldgrn/django-link-shortener)
django-link-shortener is a Django app for creating time-limited and usage-capped short URLs.
## Features
* Generate short links for URLs.
* Time-sensitive links (configurable lifespan).
* Usage-limited links (configurable maximum uses).
* Per-user override of default settings via Django admin.
* Test endpoint for easy shortcode creation during development.
* Character set for shortcodes excludes I, i, 1.
## Usage
1. Install with `pip install django-link-shortener`
2. Add `shortener` to your INSTALLED_APPS setting:
```python
INSTALLED_APPS = [
...
'shortener',
]
```
3. Include `shortener.urls` in your project urls.py:
```python
path('s/', include('shortener.urls')),
```
4. Run `python manage.py migrate` to create the shortener models.
5. Use `shortener.create(user, link)` to generate a shortcode.
```python
from shortener import shortener
user = User.objects.first()
shortener.create(user, "https://example.com")
```
6. To expand the shortcode use `shortener.expand(shorlink_id)`,
or visit `http://127.0.0.1:8000/s/<shortcode>/`.
## Test Endpoint
1. To enable the test endpoint, add the following to settings:
```python
SHORTENER_ENABLE_TEST_PATH = True
```
2. Start the development server and visit
`http://127.0.0.1:8000/s/test/<my-url-here>` to create a test shortcode.
3. Visit `http://127.0.0.1:8000/s/<shortcode>/` to be redirected
## Configuration Options
Place in settings.py. Each setting can be overridden on a per-user basis
using the UrlProfile section in the Django admin.
**SHORTENER_ENABLED**
Default: `True`
Controls whether users without a shortener profile can create shortlinks.
**SHORTENER_MAX_URLS**
Default: `-1`
Controls the default maximum limit of generated urls per account.
-1 sets infinite.
**SHORTENER_MAX_CONCURRENT**
Default: `-1`
Controls the default maximum limit of *concurrent* (active)
generated urls per account. -1 sets infinite.
**SHORTENER_LIFESPAN**
Default: `-1`
Sets the default lifespan of links in seconds. -1 sets infinite.
**SHORTENER_MAX_USES**
Default: `-1`
Sets the default amount of times a link can be followed. -1 sets infinite.
**SHORTENER_LENGTH**
Default: `5`
Note: Omitted from UrlProfile.
Sets how many digits should be used for links. Tries up to three
times to generate a unique shortcode where Each failure will result
in length temporarily being increased by 1.
**SHORTENER_ENABLE_TEST_PATH**
Default: `False`
If true, creates shortlinks on authenticated requests to `s/test/<url>/`
and returns a shortcode.
## Common Use Cases
goo.gl type usage (default). Unlimited concurrent links for an unlimited
length of time
```python
SHORTENER_ENABLED = True
SHORTENER_MAX_URLS = -1
SHORTENER_MAX_CONCURRENT = -1
SHORTENER_LIFESPAN = -1
SHORTENER_MAX_USES = -1
```
Internal temporary link usage.
100 active links with a lifespan of 1 hour. 1 usage per link.
```python
SHORTENER_ENABLED = True
SHORTENER_MAX_URLS = -1
SHORTENER_MAX_CONCURRENT = 100
SHORTENER_LIFESPAN = 600
SHORTENER_MAX_USES = 1
```
## Changelog
**v0.5**
- Replaced NullBooleanField with BooleanField (Credit: sen-den)
- Replaced travis-ci with github actions
**v0.4**
- Allow null values in UrlProfile; null fields will use global values
- str representation of UrlProfile in admin
- add user to str representation of UrlMap
- removed 256 char limit on full_url (Credit: Khaeshah)
Raw data
{
"_id": null,
"home_page": null,
"name": "django-link-shortener",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "url shortener, link shortener",
"author": null,
"author_email": "Petronald Green <petronaldgreen@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/65/ca/5aaffcc734f5a1117ffe5d6931243318de6a1ecc7707d96887d48f704934/django_link_shortener-1.0.1.tar.gz",
"platform": null,
"description": "# django-link-shortener\n\n[](https://github.com/ronaldgrn/django-link-shortener/actions/workflows/django-tests.yml)\n[](https://pypi.org/project/django-link-shortener/)\n[](https://pypi.org/project/django-link-shortener/)\n[](https://codecov.io/gh/ronaldgrn/django-link-shortener)\n\n\ndjango-link-shortener is a Django app for creating time-limited and usage-capped short URLs.\n\n\n## Features\n\n* Generate short links for URLs.\n* Time-sensitive links (configurable lifespan).\n* Usage-limited links (configurable maximum uses).\n* Per-user override of default settings via Django admin.\n* Test endpoint for easy shortcode creation during development.\n* Character set for shortcodes excludes I, i, 1.\n\n\n## Usage\n\n1. Install with `pip install django-link-shortener`\n\n2. Add `shortener` to your INSTALLED_APPS setting:\n\n ```python\n INSTALLED_APPS = [\n ...\n 'shortener',\n ]\n ```\n\n3. Include `shortener.urls` in your project urls.py:\n\n ```python\n path('s/', include('shortener.urls')),\n ```\n\n4. Run `python manage.py migrate` to create the shortener models.\n\n5. Use `shortener.create(user, link)` to generate a shortcode.\n\n ```python\n from shortener import shortener\n \n user = User.objects.first()\n shortener.create(user, \"https://example.com\")\n ```\n\n6. To expand the shortcode use `shortener.expand(shorlink_id)`, \n or visit `http://127.0.0.1:8000/s/<shortcode>/`.\n\n\n## Test Endpoint\n\n1. To enable the test endpoint, add the following to settings:\n ```python\n SHORTENER_ENABLE_TEST_PATH = True\n ```\n\n2. Start the development server and visit\n `http://127.0.0.1:8000/s/test/<my-url-here>` to create a test shortcode.\n\n3. Visit `http://127.0.0.1:8000/s/<shortcode>/` to be redirected\n\n\n## Configuration Options\n\nPlace in settings.py. Each setting can be overridden on a per-user basis\nusing the UrlProfile section in the Django admin.\n\n\n**SHORTENER_ENABLED** \nDefault: `True`\n\nControls whether users without a shortener profile can create shortlinks.\n\n\n**SHORTENER_MAX_URLS** \nDefault: `-1`\n\nControls the default maximum limit of generated urls per account.\n-1 sets infinite.\n\n\n**SHORTENER_MAX_CONCURRENT** \nDefault: `-1`\n\nControls the default maximum limit of *concurrent* (active)\ngenerated urls per account. -1 sets infinite.\n\n\n**SHORTENER_LIFESPAN** \nDefault: `-1`\n\nSets the default lifespan of links in seconds. -1 sets infinite.\n\n\n**SHORTENER_MAX_USES** \nDefault: `-1`\n\nSets the default amount of times a link can be followed. -1 sets infinite.\n\n\n**SHORTENER_LENGTH** \nDefault: `5`\n\nNote: Omitted from UrlProfile.\n\nSets how many digits should be used for links. Tries up to three\ntimes to generate a unique shortcode where Each failure will result\nin length temporarily being increased by 1.\n\n\n**SHORTENER_ENABLE_TEST_PATH** \nDefault: `False`\n\nIf true, creates shortlinks on authenticated requests to `s/test/<url>/` \nand returns a shortcode.\n\n\n## Common Use Cases\n\ngoo.gl type usage (default). Unlimited concurrent links for an unlimited\nlength of time\n\n```python\nSHORTENER_ENABLED = True\nSHORTENER_MAX_URLS = -1\nSHORTENER_MAX_CONCURRENT = -1\nSHORTENER_LIFESPAN = -1\nSHORTENER_MAX_USES = -1\n```\n\nInternal temporary link usage. \n100 active links with a lifespan of 1 hour. 1 usage per link.\n\n```python\nSHORTENER_ENABLED = True\nSHORTENER_MAX_URLS = -1\nSHORTENER_MAX_CONCURRENT = 100\nSHORTENER_LIFESPAN = 600\nSHORTENER_MAX_USES = 1\n```\n\n\n\n## Changelog\n\n**v0.5**\n\n- Replaced NullBooleanField with BooleanField (Credit: sen-den)\n- Replaced travis-ci with github actions\n\n**v0.4**\n\n- Allow null values in UrlProfile; null fields will use global values\n- str representation of UrlProfile in admin\n- add user to str representation of UrlMap\n- removed 256 char limit on full_url (Credit: Khaeshah)\n\n",
"bugtrack_url": null,
"license": null,
"summary": "A simple Django Url Shortener.",
"version": "1.0.1",
"project_urls": {
"Homepage": "https://github.com/ronaldgrn/django-link-shortener"
},
"split_keywords": [
"url shortener",
" link shortener"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9a366504a205241b1e567d9027754a64037d74f34be0527dd3d4296ddabda3eb",
"md5": "defe910c3d4d918d508ae9b541a5d017",
"sha256": "568e30ba1bb195df59085d64de1300a3fecb65ef628ffbb15f0ee6a9d8894327"
},
"downloads": -1,
"filename": "django_link_shortener-1.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "defe910c3d4d918d508ae9b541a5d017",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 10731,
"upload_time": "2025-07-08T21:51:31",
"upload_time_iso_8601": "2025-07-08T21:51:31.936552Z",
"url": "https://files.pythonhosted.org/packages/9a/36/6504a205241b1e567d9027754a64037d74f34be0527dd3d4296ddabda3eb/django_link_shortener-1.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "65ca5aaffcc734f5a1117ffe5d6931243318de6a1ecc7707d96887d48f704934",
"md5": "0db5fb624c63afe79a9ef763bf07d3d5",
"sha256": "0aa36a18fe74208e1a04b94835f8afbf70270a308f90cabad2628b1d80584571"
},
"downloads": -1,
"filename": "django_link_shortener-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "0db5fb624c63afe79a9ef763bf07d3d5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 7452,
"upload_time": "2025-07-08T21:51:33",
"upload_time_iso_8601": "2025-07-08T21:51:33.025986Z",
"url": "https://files.pythonhosted.org/packages/65/ca/5aaffcc734f5a1117ffe5d6931243318de6a1ecc7707d96887d48f704934/django_link_shortener-1.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-08 21:51:33",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ronaldgrn",
"github_project": "django-link-shortener",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "django-link-shortener"
}