{"id":13610075,"url":"https://github.com/WiserTogether/django-remote-forms","last_synced_at":"2025-04-12T22:32:38.940Z","repository":{"id":3785112,"uuid":"4862966","full_name":"WiserTogether/django-remote-forms","owner":"WiserTogether","description":"A platform independent django form serializer","archived":false,"fork":false,"pushed_at":"2024-05-07T12:11:29.000Z","size":39,"stargazers_count":223,"open_issues_count":22,"forks_count":113,"subscribers_count":38,"default_branch":"master","last_synced_at":"2024-08-01T19:54:16.504Z","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/WiserTogether.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}},"created_at":"2012-07-02T17:52:00.000Z","updated_at":"2024-05-16T21:08:48.000Z","dependencies_parsed_at":"2023-07-08T22:01:34.953Z","dependency_job_id":null,"html_url":"https://github.com/WiserTogether/django-remote-forms","commit_stats":{"total_commits":50,"total_committers":9,"mean_commits":5.555555555555555,"dds":"0.33999999999999997","last_synced_commit":"43db311becc576daaba5ff1f844760f1ba370028"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiserTogether%2Fdjango-remote-forms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiserTogether%2Fdjango-remote-forms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiserTogether%2Fdjango-remote-forms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WiserTogether%2Fdjango-remote-forms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WiserTogether","download_url":"https://codeload.github.com/WiserTogether/django-remote-forms/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223549104,"owners_count":17163595,"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","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-01T19:01:40.975Z","updated_at":"2024-11-07T16:30:35.121Z","avatar_url":"https://github.com/WiserTogether.png","language":"Python","readme":"# django-remote-forms\n\nA package that allows you to serialize django forms, including fields and widgets into Python\ndictionary for easy conversion into JSON and expose over API\n\nPlease go through my [djangocon US 2012 talk](http://www.slideshare.net/tarequeh/django-forms-in-a-web-api-world)\nto understand the problem sphere, motivations, challenges and implementation of Remote Forms\n\n## Sample Implementation\n\nIf you don't mind digging around a little bit to learn about different the components that might be\nnecessary for an implementation of django-remote-forms, check out\ndjango Remote Admin [django-remote-admin](https://github.com/tarequeh/django-remote-admin)\n\n## Usage\n\n### Minimal Example\n\n```python\nfrom django_remote_forms.forms import RemoteForm\n\nform = LoginForm()\nremote_form = RemoteForm(form)\nremote_form_dict = remote_form.as_dict()\n```\n\nUpon converting the dictionary into JSON, it looks like this:\n\n```json\n{\n    \"is_bound\": false,\n    \"non_field_errors\": [],\n    \"errors\": {},\n    \"title\": \"LoginForm\",\n    \"fields\": {\n        \"username\": {\n            \"title\": \"CharField\",\n            \"required\": true,\n            \"label\": \"Username\",\n            \"initial\": null,\n            \"help_text\": \"This is your django username\",\n            \"error_messages\": {\n                \"required\": \"This field is required.\",\n                \"invalid\": \"Enter a valid value.\"\n            },\n            \"widget\": {\n                \"title\": \"TextInput\",\n                \"is_hidden\": false,\n                \"needs_multipart_form\": false,\n                \"is_localized\": false,\n                \"is_required\": true,\n                \"attrs\": {\n                    \"maxlength\": \"30\"\n                },\n                \"input_type\": \"text\"\n            },\n            \"min_length\": 6,\n            \"max_length\": 30\n        },\n        \"password\": {\n            \"title\": \"CharField\",\n            \"required\": true,\n            \"label\": \"Password\",\n            \"initial\": null,\n            \"help_text\": \"\",\n            \"error_messages\": {\n                \"required\": \"This field is required.\",\n                \"invalid\": \"Enter a valid value.\"\n            },\n            \"widget\": {\n                \"title\": \"PasswordInput\",\n                \"is_hidden\": false,\n                \"needs_multipart_form\": false,\n                \"is_localized\": false,\n                \"is_required\": true,\n                \"attrs\": {\n                    \"maxlength\": \"128\"\n                },\n                \"input_type\": \"password\"\n            },\n            \"min_length\": 6,\n            \"max_length\": 128\n        }\n    },\n    \"label_suffix\": \":\",\n    \"prefix\": null,\n    \"csrfmiddlewaretoken\": \"2M3MDgfzBmkmBrJ9U0MuYUdy8vgeCCgw\",\n    \"data\": {\n        \"username\": null,\n        \"password\": null\n    }\n}\n```\n\n### An API endpoint serving remote forms\n\n```python\nfrom django.core.serializers.json import simplejson as json, DjangoJSONEncoder\nfrom django.http import HttpResponse\nfrom django.middleware.csrf import CsrfViewMiddleware\nfrom django.views.decorators.csrf import csrf_exempt\n\nfrom django_remote_forms.forms import RemoteForm\n\nfrom my_awesome_project.forms import MyAwesomeForm\n\n\n@csrf_exempt\ndef my_ajax_view(request):\n    csrf_middleware = CsrfViewMiddleware()\n\n    response_data = {}\n    if request.method == 'GET':\n        # Get form definition\n        form = MyAwesomeForm()\n    elif request.raw_post_data:\n        request.POST = json.loads(request.raw_post_data)\n        # Process request for CSRF\n        csrf_middleware.process_view(request, None, None, None)\n        form_data = request.POST.get('data', {})\n        form = MyAwesomeForm(form_data)\n        if form.is_valid():\n            form.save()\n\n    remote_form = RemoteForm(form)\n    # Errors in response_data['non_field_errors'] and response_data['errors']\n    response_data.update(remote_form.as_dict())\n\n    response = HttpResponse(\n        json.dumps(response_data, cls=DjangoJSONEncoder),\n        mimetype=\"application/json\"\n    )\n\n    # Process response for CSRF\n    csrf_middleware.process_response(request, response)\n    return response\n```\n\n## djangocon Proposal\n\nThis is a bit lengthy. But if you want to know more about my motivations behind developing django-remote-forms\nthen read on.\n\n\n\u003eIn our quest to modularize the architecture of web applications, we create self-containing backend\n\u003esystems that provide web APIs for programmatic interactions. This gives us the flexibility to\n\u003eseparate different system components. A system with multiple backend components e.g. user profile\n\u003eengine, content engine, community engine, analytics engine may have a single frontend application\n\u003ethat fetches data from all of these components using respective web APIs.\n\n\u003eWith the increased availability of powerful JavaScript frameworks, such frontend applications are\n\u003eoften purely JS based to decrease application footprint, increase deployment flexibility and\n\u003eseparate presentation from data. The separation is very rewarding from a software engineering\n\u003estandpoint but imposes several limitations on system design. Using django to construct the API for\n\u003earbitrary consumers comes with the limitation of not being able to utilize the powerful django form\n\u003esubsystem to drive forms on these consumers. But is there a way to overcome this restriction?\n\n\u003eThis is not a trivial problem to solve and there are only a few assumptions we can make about the\n\u003eweb API consumer. It can be a native mobile or desktop - application or browser. We advocate that\n\u003eweb APIs should provide sufficient information about 'forms' so that they can be faithfully\n\u003ereproduced at the consumer end.\n\n\u003eEven in a API backend built using django, forms are essential for accepting, filtering, processing\n\u003eand saving data. The django form subsystem provides many useful features to accomplish these tasks.\n\u003eAt the same time it facilitates the process of rendering the form elements in a browser\n\u003eenvironment. The concepts of form fields combined with widgets can go a long way in streamlining\n\u003ethe interface to interact with data.\n\n\u003eWe propose an architecture to serialize information about django forms (to JSON) in a framework\n\u003eindependent fashion so that it can be consumed by any frontend application that renders HTML. Such\n\u003einformation includes but is not limited to basic form configurations, security tokens (if\n\u003enecessary), rendering metadata and error handling instructions. We lovingly name this architecture\n\u003edjango-remote-forms.\n\n\u003eAt WiserTogether, we are in the process of building a component based architecture that strictly\n\u003eprovides data endpoints for frontend applications to consume. We are working towards developing\n\u003eour frontend application for web browsers using backbone.js as MVC and handlebars as the templating\n\u003eengine. django-remote-forms helps us streamline our data input interface with the django forms\n\u003eliving at the API backend.\n","funding_links":[],"categories":["Forms","资源列表","Python","表单","Forms [🔝](#readme)","Awesome Python"],"sub_categories":["表单","Forms"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWiserTogether%2Fdjango-remote-forms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FWiserTogether%2Fdjango-remote-forms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FWiserTogether%2Fdjango-remote-forms/lists"}