{"id":31034535,"url":"https://github.com/sanshain/django-ui-widgets","last_synced_at":"2025-09-14T02:23:59.333Z","repository":{"id":57422473,"uuid":"294600401","full_name":"Sanshain/django-ui-widgets","owner":"Sanshain","description":"The most relevant improved ui widgets and fields for classic django","archived":false,"fork":false,"pushed_at":"2022-03-16T17:24:38.000Z","size":269,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-12T07:52:42.262Z","etag":null,"topics":["django","django-forms","django-ui-widgets","fields","forms","widgets"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sanshain.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}},"created_at":"2020-09-11T05:13:06.000Z","updated_at":"2023-07-17T15:52:37.000Z","dependencies_parsed_at":"2022-09-13T15:40:31.225Z","dependency_job_id":null,"html_url":"https://github.com/Sanshain/django-ui-widgets","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Sanshain/django-ui-widgets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sanshain%2Fdjango-ui-widgets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sanshain%2Fdjango-ui-widgets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sanshain%2Fdjango-ui-widgets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sanshain%2Fdjango-ui-widgets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sanshain","download_url":"https://codeload.github.com/Sanshain/django-ui-widgets/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sanshain%2Fdjango-ui-widgets/sbom","scorecard":{"id":125988,"data":{"date":"2025-08-11","repo":{"name":"github.com/Sanshain/django-ui-widgets","commit":"4d364c3ca5d19a1238f65795af0b5c5c05531adf"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENCE:0","Info: FSF or OSI recognized license: GNU Affero General Public License v3.0: LICENCE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"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-16T03:50:46.910Z","repository_id":57422473,"created_at":"2025-08-16T03:50:46.910Z","updated_at":"2025-08-16T03:50:46.910Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275051775,"owners_count":25397010,"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-14T02:00:10.474Z","response_time":75,"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-forms","django-ui-widgets","fields","forms","widgets"],"created_at":"2025-09-14T02:23:51.982Z","updated_at":"2025-09-14T02:23:57.367Z","avatar_url":"https://github.com/Sanshain.png","language":"Python","readme":"# django-ui-widgets\n\nAdd-on for the **django framework** consisting of improved widgets and fields with an expanded viewing interface and advanced features. Django widgets are taken as a basis.\n\n### Package contains:\n\n- [DynamicMultiSelect](#dynamicmultiselect)\n- [DynamicSelect](#dynamicselect)\n- [DynamicModelField](#dynamicmodelfield)\n- [CustomImageField](#customimagefield)\n- [AutoUrlInput](#autourlinput)\n- [JSONViewWidget](#jsonviewwidget)\n- [DateWidget](#datewidget)\n- [DivHyperModelForm](#divhypermodelform)\n\n\n## DynamicMultiSelect\n\nThis is a replacement for `SelectMultiple`. In fact, it is an analog of django-autocomplete without using jquery.\n\nUsage example:\n\n```python\nfrom ui.widgets import DynamicMultiSelect\n\nclass ProfileUpdateForm(ModelForm): \n\n    labels = ModelMultipleChoiceField(\n        queryset=SkillLabel.objects.all(),\n        widget=DynamicMultiSelect(reverse_lazy('tag_filter'))\n    )\n\n    class Meta:\n        model = Profile\n\n    def __init__(self, *args, **kwargs):\n\n        super().__init__('submit', *args, **kwargs)\n        if 'data' not in kwargs:\n            self.fields['labels'].queryset = SkillLabel.objects.filter(profile=self.instance)\n            self.fields['labels'].widget.choices = ModelChoiceIterator(self.fields['labels'])\n```\nIn example above `tag_filter` is name of the view url, which consists of filter returning `JsonResponse` object with a list of `dict`s contained `id` and `name` keys:\n\n```python\ndef tag_filter(request: HttpRequest):\n\n    pattern = request.GET.get('query', '')\n    result = SkillLabel.objects\\\n        .filter(name__startswith=pattern)\\\n        .extra(select={'hint': 'name'}) \\\n        .values('id', 'name') if pattern else ()\n\n    return JsonResponse(list(result), safe=False)\n```\nYou can also use `.annotate(value=F('name')` instead of `extra` for receiving proper name `name` for view in template.\n\nAlso pay attention to the choice assignment when transmitting data. This is necessary for correct form validation when checking primary keys\n\n## DynamicSelect\n\nLike `DynamicMultiSelect` *DynamicSelect* is replacement standart `Select` django widget for `ForeignKey` model fields with asynchronius autofillng from specified url. Works without jquery. Using like `DynamicMultiSelect` or through `DynamicModelField` (recomended):\n\n## DynamicModelField\n\n**DynamicModelField** is field using `DynamicSelect` widget. \n\nThe simplest usage example:\n\n```python\nform.fields['type'] = DynamicModelField(\n    reverse('tag_filter'),\n    SkillLabel.objects.filter(id=form.instance.type_id),\n    'Field Placeholder',\n)\n```\n\nIn constructor you also can specify `class_name` and optional `attrs` for DynamicSelect widget:\n\n```python\nform.fields['type'] = DynamicModelField(\n    reverse('tag_filter'),\n    SkillLabel.objects.filter(id=form.instance.type_id),\n    placeholder='Placeholder',\n    class_name='my_class',\n    attrs={'style': 'margin-bottom:0'}\n)\n```\nyou can use several of these fields on the same page and in the same form\n\n## CustomImageField\n\nA field that hides input with the file type and allows you to set the css class for the label pointing to it. \nThis is a common (and almost default) practice of decorating 'input[type=file]' in classic frontend development, which requires a lot of actions. \nWith this component, you can do it in one line. Recommended usage:\n\n```python\n    image = CustomImageField(label_css_class='image_icon', back_image='photo_up.jpg')\n```\n\nIn above sample by default inside CustomImageField is used `ImageWidget`. You can override this widget if you want. \nHowever, this is not recommended, since in this case you will need to manually implement the display of the image when it is updated\n\n## AutoUrlInput\n\nReplacement for URLInput. Adds an automatic 'https://' extension at the beginning of the line if the address is invalid\n\n**Attention!**\nfor this widget to work correctly, you must explicitly specify links to media resources in the template after the form, such as: `{{ form.media }}`\n\n\n## DateWidget\n\nCustomized *DateInput* widget:\n\n![alt JSONViewWidget](./doc/time.PNG)\n\n## JSONViewWidget\n\n**JSONViewWidget** - widget for displaying the content of `model.JSONField` (a field officially added in django 3.1). Designed specifically for usage inside admin interface. Usage example:\n\n```python\nclass SkillAdmin(admin.ModelAdmin):\n    formfield_overrides = {\n            models.JSONField: {            \n                'widget': JSONViewWidget(                \n            ) \n        },\n    }\n```\n\n![alt JSONViewWidget](./doc/json.PNG)\n\n`JSONViewWidget` inspired by [SplitJSONWidget](https://github.com/abbasovalex/django-SplitJSONWidget-form). But it has the following features that are missing in `SplitJSONWidget`, currently:\n\n- adding and removing notes of the tree first level\n- editing for array entries of the tree first level\n- view, editing and deleting for the notes of embedded levels\n\n# forms\n\n\n## DivHyperModelForm\n\ncustom ModelForm with two new methods:\n\n- **as_ht()** - works like `as_p` in template, but it already contains all the necessary content of the form tag. It means, small calling `{{form.as_p}}` by rendering\ndeploys to following code:\n\n```html\n\u003cform method=\"post\" {{cssclass}}\u003e\n    {% csrf_token %}\n    {{form.as_p}}\n    \u003cinput type=\"submit\" value=\"{{submit}}\"\u003e\n\u003c/form\u003e\n```\n\n- **as_div** - works like *as_ht*, but instaed of `p` tag to display each item of the form fields it takes `div`\n\nOptional attributes:\n\n- *action* - specify `action` attribute for the `\u003cform\u003e` tag\n- *css_class* - specify `class` attribute for the `\u003cform\u003e` tag\n- *submit* - specify `value` attribute for `\u003csubmit\u003e` tag inside tag form\n\nUsage:\n\n```python\nclass ProfileUpdateForm(DivHyperModelForm):  \n\n    class Meta:\n        model = Profile\n        exclude = ('user',)\n\n    def __init__(self, *args, **kwargs):\n\n        super().__init__('submit', 'form_class', *args, **kwargs)\n\tself.action = reverse('some_next_page')\n```\nor \n```python\nclass ProfileUpdateForm(DivHyperModelForm):  \n    action = '/'\n    submit = 'ok'\n    css_class = 'form_class'\n    \n    class Meta:\n        model = Profile\n        exclude = ('user',)\n```\n\nCreate instance and pass to template:\n\n```python\ncontext = {'form': ProfileUpdateForm(submit='ok', request=request)}\nrender('template_name.html', context, request)\n```\n\nin template:\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"ru\"\u003e\n\u003chead\u003e\n    \u003cmeta charset=\"UTF-8\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\t\n\u003c/head\u003e\n\u003cbody\u003e\n\t{{form.as_div}}\n\t{{form.media}}\n\u003c/body\u003e\n```\n\nin above sample usage `{{form.media}}` is optionally like standart form\n\n\n\n\n# Installation:\n\nThere are two steps:\n- First step: install through *pip* utility from one of the following sources:\n    - *pypi*\n    ```\n    pip install django-ui-widgets\n    ```\n\n    - *github* (*latest version*) (*recomended*)\n    ```\n    pip install git+http://github.com/Sanshain/django-ui-widgets\n    ```\n- Second step: add **\"ui\"** app to `INSTALLED_APPS` inside `settings.py` of your project:\n\n   ```py\n   INSTALLED_APPS = [\n    'django.contrib.admin',\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.messages',\n    'django.contrib.staticfiles',\n    \n    #...\n    \n    'ui',\n    \n    #...\n   ]\n   ```\n\nFinish\n\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanshain%2Fdjango-ui-widgets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsanshain%2Fdjango-ui-widgets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanshain%2Fdjango-ui-widgets/lists"}