{"id":39173418,"url":"https://github.com/secnot/django-param-field","last_synced_at":"2026-01-17T22:25:28.042Z","repository":{"id":57421167,"uuid":"76167164","full_name":"secnot/django-param-field","owner":"secnot","description":"A Django model field that uses a DSL to define, generate, and validate, custom forms","archived":false,"fork":false,"pushed_at":"2016-12-23T16:04:41.000Z","size":84,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-29T18:02:50.899Z","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":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/secnot.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":"2016-12-11T10:18:32.000Z","updated_at":"2019-08-01T17:35:36.000Z","dependencies_parsed_at":"2022-08-28T16:20:53.490Z","dependency_job_id":null,"html_url":"https://github.com/secnot/django-param-field","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/secnot/django-param-field","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secnot%2Fdjango-param-field","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secnot%2Fdjango-param-field/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secnot%2Fdjango-param-field/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secnot%2Fdjango-param-field/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/secnot","download_url":"https://codeload.github.com/secnot/django-param-field/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/secnot%2Fdjango-param-field/sbom","scorecard":{"id":809034,"data":{"date":"2025-08-11","repo":{"name":"github.com/secnot/django-param-field","commit":"5f2c3b29ef898fcb1d209216fa6f2f238c04845a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"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":"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":"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":"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU Lesser General Public License v3.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"}}]},"last_synced_at":"2025-08-23T12:36:34.305Z","repository_id":57421167,"created_at":"2025-08-23T12:36:34.305Z","updated_at":"2025-08-23T12:36:34.305Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28520372,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T22:11:28.393Z","status":"ssl_error","status_checked_at":"2026-01-17T22:11:27.841Z","response_time":85,"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":"2026-01-17T22:25:27.949Z","updated_at":"2026-01-17T22:25:28.037Z","avatar_url":"https://github.com/secnot.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# django-param-field\n\nA Django model field that uses a DSL to define, generate, and validate, custom forms.\n\n**ParamField** allows you to store something like this:\n\n```bash\nwidth: Decimal -\u003e max:50.0 min:5.0\nheight: Decimal -\u003e max:40.0 min:3.0\npainted : Bool-\u003e default:False\ninscription: Text-\u003e max_length:30\n```\n\nand generate the django equivalent form as needed:\n\n```python\nfrom django import forms\n\nclass CustomForm(forms.Form):\n\twidth = forms.DecimalField(max_value=50, min=5)\n\theight = forms.DecimalField(max_valur=40, min=3)\n\tpainted = forms.BooleanField()\n\tinscription = forms.CharField(max_length=30)\n```\t\n\nThis is useful for creating user defined forms, or custom per models forms.\n\n## Requirement\n\nIt has been tested on\n\n* Python 3\n* Django 1.9, 1.10\n\n\n## Installation\n\nFrom the repository\n\n```bash\n$ git clone https://github.com/secnot/django-param-field\n$ python setup.py install\n```\n\nor from pypi\n\n```bash\n$ pip intall django-param-field\n```\n\n## Usage\n\nAdd param_field to INSTALLED_APPS\n\n```python\n# settings.py\nINSTALLED_APPS = [\n\t...\n\t'param_field',\n]\n```\n\nAdd the field to your model:\n\n```python\n# models.py\nfrom djang.db import models\nfrom param_field import ParamField, ParamDict\n\nclass CustomProduct(models.Model):\n\tname = models.CharField(max_length=44)\n\t...\n\tparams = ParamField(blank=True, max_length=3000)\n```\n\nNow that you have a working model to create a new instance with its parameters write:\n\n```python\nparams = \"\"\"\n\twidth: Dimmension-\u003e max:50.0 min:5.0\n\theight: Dimmension-\u003e max:40.0 min:3.0\"\"\"\n\nCustomProduct.objects.create(\n\tname='Custom wooden box\",\n\tparams=params)\n```\n\n\nAnd the FormView that generates the forms from the model\n\n```python\n# views.py\nfrom django.shortcuts import render, get_object_or_404\nfrom django.views.generic import FormView\nfrom django import forms\nfrom .models import CustomProduct\n\nclass CustomProductFormView(FormView):\n\ttemplate_name = 'product_form.html'\n\tform_class = forms.Form\n\n\tdef dispatch(self, request, *args, **kwargs):\n\t\t\"\"\"Find requested CustomProduct it's needed both in post and get \n\t\trequests so the form can be genereted\"\"\"\n\t\tpk = self.kwargs['pk']\n\t\tself.product = get_object_or_404(CustomProduct, pk=pk)\n\t\treturn super().dispatch(request, *args, **kwargs)\n\t\n    def get_context_data(self, **kwargs):\n\t\t\"\"\"Send product info to template\"\"\"\n        context = super().get_context_data(**kwargs)\n        context['product'] = self.product\n        return context\n\n\tdef get_form(self, form_class=None):\n\t\t\"\"\"Generate form form param_field\"\"\"\n\t\t# NOTE: params.form(...) will return None when it doesn't\n\t\t# containt any field.\n\t\treturn self.product.params.form(**self.get_form_kwargs())\n\n\tdef form_valid(self, form):\n\t\t\"\"\"Do what ever you want with the form, at this point it's a\n\t\tvalidated django form like any other\"\"\"\n\t\tcustom_parameters = form.cleaned_data\n\t\t...\n```\n\nRead this [blog post](http://www.secnot.com/django-param-field-en.html) for a longer\ntutorial that includes an example on how to handle File and Image fields.\n\n\n## Syntax\n\nEach ParamField can have one or more fields with the following syntax\n\n```bash\nfieldname: type-\u003e property: value\n```\n\n* **fieldname** - A lowercase name starting with a letter and followed by letters, numbers, \n\tand/or underscores. The default max name length is 30 characters.\n\n* **type** - One of the supported field types (All starting with uppercase)    \n\t* Bool\n\t* Decimal\n\t* Dimmension\n\t* Integer\n\t* Text\n\t* TextArea\n\t* File\n\t* Image\n\n* **property** - One or more of the properties supported by the field type\n\tfollowed by a value.\n\t* ALL: hidden. required, label, help_text\n\t* Bool: default\n\t* Integer: default, even, odd, max, min, choices\n\t* Decimal: default, max, min, choices, max_digits, max_decimals\n\t* Text: default, max_length, min_length, choices\n\t* TextArea: default, max_length\n\t* File: (doesn't support hidden)\n\t* Image: (doesn't support hidden) \n\n* **value** - One of the value types supported by the property to its left\n\t* Boolean - True/False\n\t* Decimal - 1.33, 6.44\n\t* Integer - 44\n\t* String - \"string with scape \\\\\"chars\\\\\" \"\n\t* Value list - [value, value, value]\n\n\n## Configuration\n\nThe absolute limits for the fields properties are configurable through **settings.py**, \nfor example **PARAM_INT_MAX** controls the max allowed value for integer **max** property,\nso creating a new Integer field where **max** is bigger will fail.  \n\nThese are the available options with their default value:\n\n\n``` python\n# settings.py\n\n# Max lengths for label and help_text strings\nPARAM_LABEL_MAX_LENGTH = 40\nPARAM_HELP_TEXT_MAX_LENGTH = 200\nPARAM_NAME_MAX_LENGTH = 30\n\n# Max and Min integer values, these have been chosen so integers don't cause\n# problems when stored in any DB\nPARAM_INT_MAX =  2147483647\nPARAM_INT_MIN = -2147483648\n\n# The maximum number of digits allowed and the max decimal places\nPARAM_DECIMAL_MAX_DIGITS = 20\nPARAM_DECIMAL_MAX_DECIMALS = 4\n\n# Decimal max and min (must have valid number of digits/decimals)\nPARAM_DECIMAL_MAX = Decimal(\"9999999999999999.9999\") \nPARAM_DECIMAL_MIN = Decimal(\"-9999999999999999.9999\")\n\n# Dimmension digits/decimals\nPARAM_DIMMENSION_MAX_DIGITS = 12\nPARAM_DIMMENSION_MAX_DECIMALS = 4\n\n# Dimmension max and min\nPARAM_DIMMENSION_MAX = Decimal(\"99999999.9999\")\nPARAM_DIMMENSION_MIN = Decimal(\"0.0\")\n\n# Text/TextArea max length\nPARAM_TEXT_MAX_LENGTH = 300\n\n# max_length used by ParamField when it isn't supplied\nPARAM_FIELD_MAX_LENGTH = 3000\n```\n\n## Testing\n\nOnce the app has been added to settings.py, you can run the tests with:\n\n```bash\n$ python manage.py test param_field\n```\n\n## References\n\n* [Domain speficific languages python slide](http://es.slideshare.net/Siddhi/creating-domain-specific-languages-in-python)\n* [Small django-param-field tutorial](http://www.secnot.com/django-param-field-en.html) with a longer example than the one\nin this README.\n\n## TODO\n\n* Better parser error messages\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecnot%2Fdjango-param-field","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsecnot%2Fdjango-param-field","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecnot%2Fdjango-param-field/lists"}