{"id":19249355,"url":"https://github.com/dori-dev/pirouz","last_synced_at":"2025-09-08T23:40:19.897Z","repository":{"id":131961181,"uuid":"610413623","full_name":"dori-dev/pirouz","owner":"dori-dev","description":"A web framework built with Python","archived":false,"fork":false,"pushed_at":"2023-03-10T13:29:06.000Z","size":42,"stargazers_count":28,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-31T21:16:52.174Z","etag":null,"topics":["gunicorn","jinja2","package","python","web-framework","website","werkzeug"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/pirouz/","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/dori-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null}},"created_at":"2023-03-06T18:15:10.000Z","updated_at":"2025-07-22T16:35:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"c1163670-9548-4b7b-a698-1e1066cb4f8a","html_url":"https://github.com/dori-dev/pirouz","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dori-dev/pirouz","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dori-dev%2Fpirouz","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dori-dev%2Fpirouz/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dori-dev%2Fpirouz/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dori-dev%2Fpirouz/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dori-dev","download_url":"https://codeload.github.com/dori-dev/pirouz/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dori-dev%2Fpirouz/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274231163,"owners_count":25245675,"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-08T02:00:09.813Z","response_time":121,"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":["gunicorn","jinja2","package","python","web-framework","website","werkzeug"],"created_at":"2024-11-09T18:13:48.566Z","updated_at":"2025-09-08T23:40:19.886Z","avatar_url":"https://github.com/dori-dev.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pirouz Web Framework\n\nA web framework built with Python.\n\n#\n\n## Sample Weblog Project\n\nThe simple weblog created with pirouz web framework.\nYou can see weblog sources [here](/weblog/) before that install `pirouz` with pip in your system.\n\n#\n\n## Install Pirouz\n\n```\npip install pirouz\n```\n\n#\n\n## Imports\n\n```python\nfrom pirouz import (\n    App, BaseMiddleware,\n    Render as Render_, TextResponse, redirect,\n    DB, ResultConfig, columns, OR\n)\nfrom pirouz.utils import cleaned_data, encrypt\n```\n\n#\n\n## Create App\n\n```python\napp = App(__file__)\n```\n\n#\n\n## Run Web Server\n\nFor run web server using python:\n\n```python\nif __name__ == '__main__':\n    app.run(port=8001)\n```\n\nRun server using gunicorn:\n\n```\ngunicorn -w 4 app:app --reload\n```\n\n#\n\n## Create Models\n\n```python\nclass User(DB):\n    username = columns.VarChar(unique=True, nullable=False)\n    password = columns.Text(nullable=False)\n    email = columns.Text()\n    first_name = columns.VarChar()\n    last_name = columns.VarChar()\n\n\nclass Post(DB):\n    title = columns.Text(nullable=False)\n    body = columns.Text()\n    author = columns.ForeignKey(User)\n    like_count = columns.SmallInt(default=0)\n    created = columns.Date()\n```\n\n#\n\n## Create Middleware\n\n```python\nclass AuthMiddleware(BaseMiddleware):\n    def process_request(self, request):\n        request.user = None\n        username = request.cookies.get('username')\n        password = request.cookies.get('password')\n        try:\n            user = User.filter(username=username).first()\n            if user.password == password:\n                request.user = user\n        except Exception:\n            pass\n        return request\n\n\napp.add_middleware(AuthMiddleware)\n```\n\n#\n\n## Serve Files\n\n```python\napp.serve_files()\n```\n\n#\n\n## Add Context Processor\n\n```python\n\nclass Render(Render_):\n    def get_context(self, request) -\u003e dict:\n        return {\n            'user': request.user,\n            'posts_count': Post.all().count(),\n        }\n\n```\n\n#\n\n## Function View\n\n```python\n@app.route('/')\ndef index(request):\n    context = {\n        'posts': Post.all(\n            config=ResultConfig(\n                order_by='id',\n                reverse=True,\n            )\n        ),\n    }\n    return Render(request, 'post/list.html', context=context)\n```\n\n#\n\n## Class View\n\nA detail view for detail of post.\n\n```python\n@app.route('/post/\u003cint:id\u003e/')\nclass PostDetail:\n    def get(self, request, id):\n        post = Post.filter(id=id).first()\n        if not post:\n            return TextResponse(f'Post with ID {id} not found!', status=404)\n        context = {\n            'post': post,\n            'author': User.filter(id=post.author).first(),\n        }\n        return Render(request, 'post/detail.html', context=context)\n\n    def post(self, request, id):\n        return self.get(request, id)\n```\n\n\u003cbr\u003e\nA create view for create new post.\n\n```python\n@app.route(\"/create/\", methods=[\"GET\", \"POST\"])\nclass PostCreate:\n    def get(self, request):\n        if not request.user:\n            return redirect('/login/')\n        return Render(request, 'post/create.html')\n\n    def post(self, request):\n        if not request.user:\n            return redirect('/login/')\n        cd = cleaned_data(request)\n        post = Post(\n            title=cd[\"title\"],\n            body=cd['body'],\n            author=request.user,\n            like_count=randint(1, 100),\n            created=str(datetime.now().date()),\n        )\n        return redirect(f'/post/{post.id}/')\n\n```\n\n#\n\n## Authentication\n\nRegister view for sign up a user.\n\n```python\n@app.route(\"/register/\", methods=[\"GET\", \"POST\"])\nclass Register:\n    def get(self, request):\n        return Render(request, 'post/register.html')\n\n    def post(self, request):\n        cd = cleaned_data(request)\n        password = encrypt(cd['password'])\n        username = cd['username']\n        try:\n            user = User.filter(username=username).first()\n            if user:\n                return Render(\n                    request,\n                    'post/register.html',\n                    context={'exists': True}\n                )\n        except Exception:\n            pass\n        User(\n            username=username,\n            password=password,\n            email=cd['email'],\n            first_name=cd['first_name'],\n            last_name=cd['last_name'],\n        )\n        response = redirect('/')\n        response.set_cookie('username', username)\n        response.set_cookie('password', password)\n        return response\n\n```\n\n\u003cbr\u003e\n\nLogin view for user login.\n\n```python\n@app.route(\"/login/\", methods=[\"GET\", \"POST\"])\nclass Login:\n    def get(self, request):\n        return Render(request, 'post/login.html')\n\n    def post(self, request):\n        cd = cleaned_data(request)\n        password = encrypt(cd['password'])\n        username = cd['username']\n        try:\n            user = User.filter(username=username).first()\n            if user and user.password == password:\n                response = redirect('/')\n                response.set_cookie('username', username)\n                response.set_cookie('password', password)\n                return response\n        except Exception:\n            pass\n        return Render(request, 'post/login.html', context={'wrong': True})\n\n```\n\n\u003cbr\u003e\nLogout view for logout the user\n\n```python\n\n\n@app.route('/exit/', methods=['GET'])\nclass Logout:\n    def get(self, request):\n        response = redirect('/')\n        response.delete_cookie('username')\n        response.delete_cookie('password')\n        return response\n\n```\n\n#\n\n## Search View\n\n```python\n@app.route('/search/')\nclass Search:\n    def get(self, request):\n        query = request.args.get('search')\n        context = {\n            'search': True,\n        }\n        if query:\n            posts = Post.filter(\n                OR(\n                    title__like=f'%{query}%',\n                    body__like=f'%{query}%',\n                ),\n                config=ResultConfig(\n                    order_by='id',\n                    reverse=True,\n                )\n            )\n            context.update({\n                'posts': posts,\n            })\n        return Render(request, 'post/list.html', context=context)\n\n    def post(self, request):\n        return self.get(request)\n\n```\n\n#\n\n# Links\n\nDownload Source Code: [Click Here](https://github.com/dori-dev/pirouz/archive/refs/heads/main.zip)\n\nMy Github Account: [Click Here](https://github.com/dori-dev/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdori-dev%2Fpirouz","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdori-dev%2Fpirouz","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdori-dev%2Fpirouz/lists"}