{"id":21561456,"url":"https://github.com/phpdude/django-macros-url","last_synced_at":"2025-09-01T16:46:07.057Z","repository":{"id":17558814,"uuid":"20361762","full_name":"phpdude/django-macros-url","owner":"phpdude","description":"Django Macros URL. Routing must be simple as possible","archived":false,"fork":false,"pushed_at":"2017-08-08T13:14:10.000Z","size":106,"stargazers_count":138,"open_issues_count":0,"forks_count":14,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-08-16T01:37:00.332Z","etag":null,"topics":["django","django-routing","python","router","routing","urls"],"latest_commit_sha":null,"homepage":"http://phpdude.github.io/django-macros-url","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phpdude.png","metadata":{"files":{"readme":"README.markdown","changelog":"CHANGELOG.markdown","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-05-31T18:03:10.000Z","updated_at":"2025-05-09T21:38:52.000Z","dependencies_parsed_at":"2022-07-10T06:16:16.690Z","dependency_job_id":null,"html_url":"https://github.com/phpdude/django-macros-url","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/phpdude/django-macros-url","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpdude%2Fdjango-macros-url","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpdude%2Fdjango-macros-url/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpdude%2Fdjango-macros-url/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpdude%2Fdjango-macros-url/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phpdude","download_url":"https://codeload.github.com/phpdude/django-macros-url/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpdude%2Fdjango-macros-url/sbom","scorecard":{"id":732442,"data":{"date":"2025-08-11","repo":{"name":"github.com/phpdude/django-macros-url","commit":"4c413acad75af3f6356dff5c91f5a20c8121a79c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":1,"reason":"Found 4/25 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 9 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T14:48:45.409Z","repository_id":17558814,"created_at":"2025-08-22T14:48:45.409Z","updated_at":"2025-08-22T14:48:45.409Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273158299,"owners_count":25055859,"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","status":"online","status_checked_at":"2025-09-01T02:00:09.058Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["django","django-routing","python","router","routing","urls"],"created_at":"2024-11-24T09:22:48.440Z","updated_at":"2025-09-01T16:46:07.028Z","avatar_url":"https://github.com/phpdude.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# [Django Macros URL](https://github.com/phpdude/django-macros-url/) v0.4.0 - Routing must be simple as possible\n\nDjango Macros URL makes it easy to write (and read) URL patterns in your Django applications by using macros.\n\nYou can combine your prefixes with macro names with an underscore, for example, you can use a macro `:slug` \nand `:product_slug`. They both will be compiled to same regex pattern with their group names of course. \nMultiple underscores accepted too.\n\n[![Build Status](https://travis-ci.org/phpdude/django-macros-url.svg?branch=master)](https://travis-ci.org/phpdude/django-macros-url)\n\n### Supported macros by default\n\n```\nslug - [\\w-]+\nyear - \\d{4}\nmonth - (0?([1-9])|10|11|12)\nday - ((0|1|2)?([1-9])|[1-3]0|31)\nid - \\d+\npk - \\d+\npage - \\d+\nuuid - [a-fA-F0-9]{8}-?[a-fA-F0-9]{4}-?[1345][a-fA-F0-9]{3}-?[a-fA-F0-9]{4}-?[a-fA-F0-9]{12}\n```\n\nIf you want to offer more macros by default, you can fork and make a pull request.\n\n### Installation\n\nYou can install the library with PyPI.\n\n```\npip install django-macros-url\n```\n\n### Usage\n\nDjango Macros URLs used the same way as Django standard URLs. You just import this and declare your \npatterns with macros.\n\nAlso, you can register new macro (or maybe you want to replace default macro with your like regex\npattern) with `macrosurl.register(macro, pattern)` method.\n\nAn example of registration.\n\n```python\nimport macrosurl\n\nmacrosurl.register('myhash', '[a-f0-9]{9}')\n\nurlpatterns = patterns(\n    'yourapp.views',\n    macrosurl.url('^:myhash/$', 'myhash_main'),\n    macrosurl.url('^news/:news_myhash/$', 'myhash_news'),\n)\n```\n\nFeel free to register custom macro anywhere (i do it in main urls.py file). Macros URLs uses lazy \ninitialization. Macros will be compiled only on the first request.\n\n### URL normalization\n\nOnce Macros URL completed compile regex pattern, it makes normalization of it by rules:\n\n- Strip from left side all whitespace and ^\n- Strip from right side of pattern all whitespace and $\n- Add to left side ^\n- Add to right side $\n\nThis makes your URLs always very strong to adding any unexpected params into a path.\n\n### Auto-calling as_view() on CBV objects.\n\nLibrary check type of view and if a view is type object with defined 'as_view' function, call this. This allows \nyou omit \".as_view()\" calls in your urls.py files. But you can call this manual with params if you need.\n\nThis feature helps you to keep your urls.py files clean as possible. I hope you like this feature!\n\n### Examples\n\nMacros URL example urls.py file\n\n```python\nfrom django.conf.urls import patterns\nfrom macrosurl import url\nfrom project.portal.views import IndexView\n\nurlpatterns = patterns(\n    'yourapp.views',\n    url('^:category_slug/$', 'category'),\n    url(':category_slug/:product_slug/', 'category_product'),\n    url(':category_slug/:product_slug/:variant_id', 'category_product_variant'),\n    url('news/', 'news'),\n    url('news/:year/:month/:day', 'news_date'),\n    url('news/:slug', 'news_entry'),\n    url('^order/:id$', 'order'),\n    url('^$', IndexView),\n)\n```\n\nStandard Django urls example\n\n```python\nfrom django.conf.urls import patterns, url\nfrom project.portal.views import IndexView\n\n\nurlpatterns = patterns(\n    'yourapp.views',\n    url('^(?P\u003ccategory_slug\u003e[\\w-]+\u003e)/$', 'category'),\n    url('^(?P\u003ccategory_slug\u003e[\\w-]+\u003e)/(?P\u003cproduct_slug\u003e[\\w-]+\u003e)/$', 'category_product'),\n    url('^(?P\u003ccategory_slug\u003e[\\w-]+\u003e)/(?P\u003cproduct_slug\u003e[\\w-]+\u003e)/(?P\u003cvariant_id\u003e\\d+\u003e)$', 'category_product_variant'),\n    url('^news/$', 'news'),\n    url('^news/(?P\u003cyear\u003e\\d{4}\u003e)/(?P\u003cmonth\u003e(0?([1-9])|10|11|12)\u003e)/(?P\u003cday\u003e((0|1|2)?([1-9])|[1-3]0|31)\u003e)$', 'news_date'),\n    url('^news/(?P\u003cslug\u003e[\\w-]+\u003e)$', 'news_entry'),\n    url('^order/(?P\u003cid\u003e\\d+\u003e)$', 'order'),\n    url('^$', IndexView.as_view()),\n)\n```\n\nI think you understand the difference of ways :)\n\n#### Routing must be simple! ;-)\n\nI think raw URL regexp patterns needed in 1% case only. I prefer simple way to write (and read, this is \nimportant) fancy clean URLs.\n\n### Contributor\n\n[Alexandr Shurigin](https://github.com/phpdude/)\n\nYou are welcome to contribute by PR.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphpdude%2Fdjango-macros-url","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphpdude%2Fdjango-macros-url","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphpdude%2Fdjango-macros-url/lists"}