{"id":25805667,"url":"https://github.com/scriptogre/django-samurai","last_synced_at":"2025-09-12T21:18:57.043Z","repository":{"id":243485306,"uuid":"812566579","full_name":"scriptogre/django-samurai","owner":"scriptogre","description":"Django Samurai combines views \u0026 templates into a single `.py` file. It also provides type-safety using Pydantic, and  adds file-based routing.","archived":false,"fork":false,"pushed_at":"2024-08-02T11:55:34.000Z","size":70,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-28T05:41:51.527Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scriptogre.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-09T09:08:40.000Z","updated_at":"2024-12-30T22:29:50.000Z","dependencies_parsed_at":"2025-02-27T20:14:02.677Z","dependency_job_id":"c8c00330-0717-4f78-8fc8-95d8d573a50b","html_url":"https://github.com/scriptogre/django-samurai","commit_stats":null,"previous_names":["scriptogre/django-samurai"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/scriptogre/django-samurai","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Fdjango-samurai","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Fdjango-samurai/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Fdjango-samurai/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Fdjango-samurai/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scriptogre","download_url":"https://codeload.github.com/scriptogre/django-samurai/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptogre%2Fdjango-samurai/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274879252,"owners_count":25367095,"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-12T02:00:09.324Z","response_time":60,"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":[],"created_at":"2025-02-27T19:39:14.213Z","updated_at":"2025-09-12T21:18:57.013Z","avatar_url":"https://github.com/scriptogre.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Django Samurai\nDjango Samurai combines views \u0026 templates into a single `.py` file. It also provides type-safety using Pydantic, and \nadds file-based routing.\n\nWhy?:\n- It make doing simple things simpler.\n- An equivalent \"modern\" feel that you get when working with FastAPI, but for working with HTML.\n- It pairs nicely with htmx.\n- Why not.\n \nThis idea is heavily inspired by Astro's `.astro` file extension syntax.\n\nHow?:\nLets see two examples of doing the same thing with a traditional setup, and with django-samurai:\n\n# Traditional Setup\n\n## urls.py\nDefine the /add-user-message route\n\n```python\nfrom django.urls import path\nfrom . import views\n\nurlpatterns = [\n    path('add-user-message/', views.add_user_message_view, name='add_user_message_view'),\n]\n```\n\n## views.py\nGet the message from form data, add HX-Trigger header to response\n\n```python\nfrom django import forms\nfrom django.shortcuts import render\nfrom django.views.decorators.http import require_http_methods\n\n\n@require_http_methods([\"POST\"])\ndef add_user_message_view(request):\n\tmessage = request.POST.get(\"message\")\n\tcontext = {'message': message}\n\theaders = {'HX-Trigger': 'chatMessageAdded'}\n    return render(request, context, headers=headers)\n```\n\n## template\n```html\n    \u003cdiv class=\"chat-message\"\u003e\n        \u003cspan\u003e{{ message }}\u003c/span\u003e\n    \u003c/div\u003e\n```\n\n# django-samurai setup\n```python\n## views/add-user-message.py\n# view logic goes here\n\nresponse: HttpResponse\nmessage: Form[str]\n\nresponse.headers['HX-Trigger'] = 'chatMessageAdded'\n\n\"\"\"\n\u003c!-- Response is the HTML defined here --\u003e\n\n\u003cdiv class=\"chat-message\"\u003e\n\t\u003cspan\u003e{{ message }}\u003c/span\u003e\n\u003c/div\u003e\n\"\"\"\n```\n\nExplanation:\n1. Route is defined using file-based routing:\n\t- \u003capp\u003e/views/add-user-message.py -\u003e /add-user-message\n2. message form data is retrieved using Form[str], like FastAPI/django-ninja (https://django-ninja.dev/guides/input/form-params/?h=form)\n3. Response can be accessed and modified by having the response defined with response: HttpRespone. This would require some magic to work, but is doable.\n4. The request could be accessed in the same way.\n5. The returned response would always be an HTML template, which will be delimited/defined at the bottom of the file using triple quotes \"\"\"You can think of these new files as view functions as files. Argument are defined using type hints, and the return value is always the HTML at the bottom.There's already an existing library that does 50% of what we need: https://github.com/jerivas/django-file-router/tree/main.\nWe can fork this and make it better.\nWe can also piggy back on django-ninja for the Pydantic validation.\nThe \"magic\"  would require most of the work.\n\n## Installation\n\n```\npip install django-samurai\n```\n\nAdd this to your `urls.py`:\n\n```python\nfrom samurai import file_patterns\n\nurlpatterns = [\n\tpath(\"admin/\", admin.site.urls),\n\t*file_patterns(\"myapp/views\"),\n]\n```\n\nWith that single call to `file_patterns` the function will generate URL patterns for all your views automatically based on their folder structure inside `myapp/views`. For the file we created earlier at `myapp/views/mymodel/add.py` this will result in a url of `/mymodel/add`. Then by simply creating more files and folders the URL patterns will be updated without any manual input.\n\n## Configuration\n\nThe `file_patterns` function accepts the following arguments:\n\n| Arg | Description |\n|---|---|\n| `append_slash` | Boolean. If `True` will add a trailing slash to the generated patterns. |\n| `exclude` | String (glob). If set each file will be checked against this pattern and excluded from the pattern generation process altogether. Useful if you want to completely avoid importing certain files (like tests). |\n\nAlternatively you can add `url` and `urlname` properties to your `view`:\n\n```python\ndef view(request):\n    ...\n\nview.url = \"custom/url/path\"\nview.urlname = \"my_custom_name\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscriptogre%2Fdjango-samurai","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscriptogre%2Fdjango-samurai","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscriptogre%2Fdjango-samurai/lists"}