{"id":13771346,"url":"https://github.com/mdaif/python-rest-model","last_synced_at":"2026-01-14T09:42:34.759Z","repository":{"id":44866864,"uuid":"44280451","full_name":"mdaif/python-rest-model","owner":"mdaif","description":"A standard way to consume a RESTful service, inspired by Django models, written in Python 3.4","archived":false,"fork":false,"pushed_at":"2022-01-21T19:00:55.000Z","size":32,"stargazers_count":11,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-21T10:39:51.575Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdaif.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}},"created_at":"2015-10-14T22:43:58.000Z","updated_at":"2018-06-21T09:53:33.000Z","dependencies_parsed_at":"2022-09-06T01:24:05.887Z","dependency_job_id":null,"html_url":"https://github.com/mdaif/python-rest-model","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/mdaif/python-rest-model","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdaif%2Fpython-rest-model","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdaif%2Fpython-rest-model/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdaif%2Fpython-rest-model/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdaif%2Fpython-rest-model/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdaif","download_url":"https://codeload.github.com/mdaif/python-rest-model/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdaif%2Fpython-rest-model/sbom","scorecard":{"id":632761,"data":{"date":"2025-08-11","repo":{"name":"github.com/mdaif/python-rest-model","commit":"68f0001f1c4a8cbec36fe87b7f850f8b451831bd"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","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":"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":"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":"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":"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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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":"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":"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":"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":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"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":"Vulnerabilities","score":4,"reason":"6 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-29gw-9793-fvw7","Warn: Project is vulnerable to: PYSEC-2022-12 / GHSA-pq7m-3gw7-gq5x","Warn: Project is vulnerable to: GHSA-9hjg-9r4m-mvj7","Warn: Project is vulnerable to: GHSA-9wx4-h78v-vm56","Warn: Project is vulnerable to: PYSEC-2023-74 / GHSA-j8r2-6x86-q33q","Warn: Project is vulnerable to: PYSEC-2018-28 / GHSA-x84v-xcm2-53pg"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T08:21:28.710Z","repository_id":44866864,"created_at":"2025-08-21T08:21:28.710Z","updated_at":"2025-08-21T08:21:28.710Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28416120,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T08:38:59.149Z","status":"ssl_error","status_checked_at":"2026-01-14T08:38:43.588Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":"2024-08-03T17:00:50.441Z","updated_at":"2026-01-14T09:42:34.744Z","avatar_url":"https://github.com/mdaif.png","language":"Python","readme":"Build Status [![Circle CI](https://circleci.com/gh/mdaif/python-rest-model/tree/master.svg?style=svg)](https://circleci.com/gh/mdaif/python-rest-model/tree/master)\n\nIntroduction\n============\nPython Rest Model exists to solve the common problem of consuming RESTful services.\n\nThe Problem\n============\nIn an OOP language as Python, developers tend to think of their data as objects and associated attributes and behaviors. When it comes to consuming a RESTful service, you typically wrap the actual communication using functions, methods or classes and spend some time to design your handler(s). That typically results in repetitive and not-so-readable code. Also different developers usually have different approaches on how to handle this issue. If you want to make sure you are passing the right data types that would be a totally different story !\n\nThe Solution\n============\nPython Rest Model solves these issues by treating the RESTful endpoints as they should be ... endpoints to resources !\nIt lets you define your own resources like you do in Django models, by extending a class and defining some attributes, and that's it ! You can have objects that handles data type validation on attributes, define the endpoints once at a single location, and the operations can be chained.\n\nInstallation\n============\nPython Rest Model is available on PyPi and can be installed using pip\n\n```\n    pip install python-rest-model\n```\n\nQuick Start\n============\n\nAfter you install Python Rest Model you can use it as following.\n```\n    from rest_model import models         # import models\n\n    class Student(models.RestModel):       # extend models.RestModel\n      name = models.StringField()\n      age = models.PositiveIntegerField()\n      gpa = models.PositiveFloatField()\n\n      class Meta:             # An inner meta class is required to define endpoints\n        post = \"http://shangri-la/students/\"  # each entry should map to an HTTP action\n        put = \"http://shangri-la/students/{id}\"\n        delete = \"http://shangri-la/students/{id}\"\n        get = \"http://shangri-la/classes/{class_id}/{student_id}\"\n```\n\nAfter you define your resource and the endpoints you need, you can use them as following ...\n```\n    student = Student()\n    student.post(name='Bob', age=27, gpa=3.6)\n```\n\nIf you try to assign an attribute a wrong data type a TypeError will be raised\n```\n    \u003e\u003e\u003e student.post(name=7, age=27, gpa=3.6)\n```\n```  \n    Traceback (most recent call last):\n    ...\n    TypeError: expected \u003cclass 'str'\u003e\n```\n\nYou can format the endpoints at each request using the format method,\nwhich makes it very easy to follow the DRY principle and at the same time dealing with multiple resources of the\nsame type based on a different id. For example if you need to get students with ids in range 13 to 20 at a\nclass with id 15 you can do the following ...\n\n```\n    for i in range(13, 21):\n      student = student.format(class_id=15, student_id=i).get()\n      response = student.response\n```\n\neach returned object from get, post, ...etc methods is a requests\nresponse object: http://docs.python-requests.org/en/latest/\n\nThe attributes are sent as query string unless you set the json_body argument at format method to be True, they\nwill be sent as JSON body with the proper header.\n\n```\n    student.format(json_body=True, id=18).put(name='Alice', age=27, gpa=3.6)\n```\nthe post, put, ... etc methods used in the examples are dynamically generated based on what you define in the\ninner Meta class, if you try to call an undefined action an AttributeError will be raised.\nYou can find additional examples in the tests directory.\n\nCurrently supported data types\n============\n - StringField\n - IntegerField\n - FloatField\n - ListField\n - PositiveIntegerField\n - PositiveFloatField\n","funding_links":[],"categories":["ODM, ORM, Active Record"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdaif%2Fpython-rest-model","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdaif%2Fpython-rest-model","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdaif%2Fpython-rest-model/lists"}