django-permissionedforms


Namedjango-permissionedforms JSON
Version 0.1 PyPI version JSON
download
home_pagehttps://github.com/wagtail/django-permissionedforms
SummaryDjango extension for creating forms that vary according to user permissions
upload_time2022-02-28 19:40:27
maintainer
docs_urlNone
authorMatthew Westcott
requires_python>=3.7
licenseBSD
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            django-permissionedforms
========================

`django-permissionedforms` is an extension to Django's forms framework, allowing you to define forms where certain fields are shown or omitted according to the user's permissions.


Installation
------------

Run: `pip install django-permissionedforms`


Usage
-----

To add permission rules to a basic Django form, subclass `permissionedforms.PermissionedForm` in place of `django.forms.Form` and add an inner `Meta` class:

```python
from permissionedforms import PermissionedForm

class PersonForm(PermissionedForm):
    first_name = forms.CharField()
    last_name = forms.CharField()

    class Meta:
        field_permissions = {
            'last_name': 'myapp.change_last_name'
        }
```

`field_permissions` is a dict, mapping field names to permission codenames. For each field listed, that field will only be included in the final form if the user has the specified permission, as defined by the `user.has_perm()` method. See Django's documentation on [custom permissions](https://docs.djangoproject.com/en/stable/topics/auth/customizing/#custom-permissions) and [programmatically creating permissions](https://docs.djangoproject.com/en/4.0/topics/auth/default/#programmatically-creating-permissions) for details on how to set permissions up; alternatively, if you want to set a field as only available to superusers, you can use any arbitrary string (such as `'superuser'`) as the codename, since `has_perm` always returns True for them.

Then, when instantiating the form, pass the keyword argument `for_user`:

```python
form = PersonForm(for_user=request.user)
```

This will result in a form where the `last_name` field is only present if the logged-in user has the `change_last_name` permission.

The keyword argument `for_user` is optional, and if not passed, the form will behave as an ordinary form with all named fields available.

For a ModelForm, the procedure is the same, except that you should inherit from `permissionedforms.PermissionedModelForm` instead. `field_permissions` is added alongside the existing `Meta` options:

```python
from permissionedforms import PermissionedModelForm

class CountryForm(PermissionedModelForm):
    class Meta:
        model = Country
        fields = ['name', 'description']
        field_permissions = {
            'description': 'tests.change_country_description'
        }

form = CountryForm(instance=country, for_user=request.user)
```


Integrating with other base form classes
----------------------------------------

You may wish to integrate the permission handling from `django-permissionedforms` into some other base form class, such as `ClusterForm` from the [django-modelcluster](https://github.com/wagtail/django-modelcluster) package. If that base form class is a straightforward subclass of `django.forms.Form` or `django.forms.ModelForm`, then using multiple inheritance to additionally inherit from `PermissionedForm` or `PermissionedModelForm` should work:

```python
from fancyforms import FancyForm  # made up for example purposes
from permissionedforms import PermissionedForm

class FancyPermissionedForm(PermissionedForm, FancyForm):
    pass
```

However, this will fail if the base form class implements its own metaclass. In this case, you will need to define a new metaclass inheriting from both the existing one and `permissionedforms.PermissionedFormMetaclass`:

```python
from fancyforms import FancyForm
from permissionedforms import PermissionedForm, PermissionedFormMetaclass


FancyFormMetaclass = type(FancyForm)


class FancyPermissionedFormMetaclass(PermissionedFormMetaclass, FancyFormMetaclass):
    pass


class FancyPermissionedForm(PermissionedForm, FancyForm, metaclass=FancyPermissionedFormMetaclass):
    pass
```

This could still fail if the base form class incorporates a custom Options class to allow it to accept its own `class Meta` options. If so, it will be necessary to define a new Options class, again using multiple inheritance to subclass both the existing Options class and `permissionedforms.PermissionedFormOptionsMixin`, and then set this as `options_class` on the metaclass. The following recipe will work for `ClusterForm`:

```python
from modelcluster.forms import ClusterForm, ClusterFormMetaclass, ClusterFormOptions
from permissionedforms import PermissionedForm, PermissionedFormMetaclass, PermissionedFormOptionsMixin


class PermissionedClusterFormOptions(PermissionedFormOptionsMixin, ClusterFormOptions):
    pass


class PermissionedClusterFormMetaclass(PermissionedFormMetaclass, ClusterFormMetaclass):
    options_class = PermissionedClusterFormOptions


class PermissionedClusterForm(PermissionedForm, ClusterForm, metaclass=PermissionedClusterFormMetaclass):
    pass
```


Acknowledgements
----------------

`django-permissionedforms` was developed as part of [Wagtail](https://wagtail.org/)'s next-generation page editor, sponsored by Google.



            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/wagtail/django-permissionedforms",
    "name": "django-permissionedforms",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": "",
    "keywords": "",
    "author": "Matthew Westcott",
    "author_email": "matthew.westcott@torchbox.com",
    "download_url": "https://files.pythonhosted.org/packages/94/4b/364fe61a161ead607dc6af311901ba8e62f537f8fdab94b5252cb6efe6d7/django-permissionedforms-0.1.tar.gz",
    "platform": "",
    "description": "django-permissionedforms\n========================\n\n`django-permissionedforms` is an extension to Django's forms framework, allowing you to define forms where certain fields are shown or omitted according to the user's permissions.\n\n\nInstallation\n------------\n\nRun: `pip install django-permissionedforms`\n\n\nUsage\n-----\n\nTo add permission rules to a basic Django form, subclass `permissionedforms.PermissionedForm` in place of `django.forms.Form` and add an inner `Meta` class:\n\n```python\nfrom permissionedforms import PermissionedForm\n\nclass PersonForm(PermissionedForm):\n    first_name = forms.CharField()\n    last_name = forms.CharField()\n\n    class Meta:\n        field_permissions = {\n            'last_name': 'myapp.change_last_name'\n        }\n```\n\n`field_permissions` is a dict, mapping field names to permission codenames. For each field listed, that field will only be included in the final form if the user has the specified permission, as defined by the `user.has_perm()` method. See Django's documentation on [custom permissions](https://docs.djangoproject.com/en/stable/topics/auth/customizing/#custom-permissions) and [programmatically creating permissions](https://docs.djangoproject.com/en/4.0/topics/auth/default/#programmatically-creating-permissions) for details on how to set permissions up; alternatively, if you want to set a field as only available to superusers, you can use any arbitrary string (such as `'superuser'`) as the codename, since `has_perm` always returns True for them.\n\nThen, when instantiating the form, pass the keyword argument `for_user`:\n\n```python\nform = PersonForm(for_user=request.user)\n```\n\nThis will result in a form where the `last_name` field is only present if the logged-in user has the `change_last_name` permission.\n\nThe keyword argument `for_user` is optional, and if not passed, the form will behave as an ordinary form with all named fields available.\n\nFor a ModelForm, the procedure is the same, except that you should inherit from `permissionedforms.PermissionedModelForm` instead. `field_permissions` is added alongside the existing `Meta` options:\n\n```python\nfrom permissionedforms import PermissionedModelForm\n\nclass CountryForm(PermissionedModelForm):\n    class Meta:\n        model = Country\n        fields = ['name', 'description']\n        field_permissions = {\n            'description': 'tests.change_country_description'\n        }\n\nform = CountryForm(instance=country, for_user=request.user)\n```\n\n\nIntegrating with other base form classes\n----------------------------------------\n\nYou may wish to integrate the permission handling from `django-permissionedforms` into some other base form class, such as `ClusterForm` from the [django-modelcluster](https://github.com/wagtail/django-modelcluster) package. If that base form class is a straightforward subclass of `django.forms.Form` or `django.forms.ModelForm`, then using multiple inheritance to additionally inherit from `PermissionedForm` or `PermissionedModelForm` should work:\n\n```python\nfrom fancyforms import FancyForm  # made up for example purposes\nfrom permissionedforms import PermissionedForm\n\nclass FancyPermissionedForm(PermissionedForm, FancyForm):\n    pass\n```\n\nHowever, this will fail if the base form class implements its own metaclass. In this case, you will need to define a new metaclass inheriting from both the existing one and `permissionedforms.PermissionedFormMetaclass`:\n\n```python\nfrom fancyforms import FancyForm\nfrom permissionedforms import PermissionedForm, PermissionedFormMetaclass\n\n\nFancyFormMetaclass = type(FancyForm)\n\n\nclass FancyPermissionedFormMetaclass(PermissionedFormMetaclass, FancyFormMetaclass):\n    pass\n\n\nclass FancyPermissionedForm(PermissionedForm, FancyForm, metaclass=FancyPermissionedFormMetaclass):\n    pass\n```\n\nThis could still fail if the base form class incorporates a custom Options class to allow it to accept its own `class Meta` options. If so, it will be necessary to define a new Options class, again using multiple inheritance to subclass both the existing Options class and `permissionedforms.PermissionedFormOptionsMixin`, and then set this as `options_class` on the metaclass. The following recipe will work for `ClusterForm`:\n\n```python\nfrom modelcluster.forms import ClusterForm, ClusterFormMetaclass, ClusterFormOptions\nfrom permissionedforms import PermissionedForm, PermissionedFormMetaclass, PermissionedFormOptionsMixin\n\n\nclass PermissionedClusterFormOptions(PermissionedFormOptionsMixin, ClusterFormOptions):\n    pass\n\n\nclass PermissionedClusterFormMetaclass(PermissionedFormMetaclass, ClusterFormMetaclass):\n    options_class = PermissionedClusterFormOptions\n\n\nclass PermissionedClusterForm(PermissionedForm, ClusterForm, metaclass=PermissionedClusterFormMetaclass):\n    pass\n```\n\n\nAcknowledgements\n----------------\n\n`django-permissionedforms` was developed as part of [Wagtail](https://wagtail.org/)'s next-generation page editor, sponsored by Google.\n\n\n",
    "bugtrack_url": null,
    "license": "BSD",
    "summary": "Django extension for creating forms that vary according to user permissions",
    "version": "0.1",
    "project_urls": {
        "Homepage": "https://github.com/wagtail/django-permissionedforms"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e65b216157ff053f955b15b9dcdc13bfb6e406666445164fee9e332e141be96d",
                "md5": "a64ad0256c4d87addb39bc9751de57b4",
                "sha256": "d341a961a27cc77fde8cc42141c6ab55cc1f0cb886963cc2d6967b9674fa47d6"
            },
            "downloads": -1,
            "filename": "django_permissionedforms-0.1-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a64ad0256c4d87addb39bc9751de57b4",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": ">=3.7",
            "size": 5744,
            "upload_time": "2022-02-28T19:40:26",
            "upload_time_iso_8601": "2022-02-28T19:40:26.337198Z",
            "url": "https://files.pythonhosted.org/packages/e6/5b/216157ff053f955b15b9dcdc13bfb6e406666445164fee9e332e141be96d/django_permissionedforms-0.1-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "944b364fe61a161ead607dc6af311901ba8e62f537f8fdab94b5252cb6efe6d7",
                "md5": "cfb5cdeb602c00283ffc2bc5f929ac46",
                "sha256": "4340bb20c4477fffb13b4cc5cccf9f1b1010b64f79956c291c72d2ad2ed243f8"
            },
            "downloads": -1,
            "filename": "django-permissionedforms-0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "cfb5cdeb602c00283ffc2bc5f929ac46",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 5856,
            "upload_time": "2022-02-28T19:40:27",
            "upload_time_iso_8601": "2022-02-28T19:40:27.892580Z",
            "url": "https://files.pythonhosted.org/packages/94/4b/364fe61a161ead607dc6af311901ba8e62f537f8fdab94b5252cb6efe6d7/django-permissionedforms-0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2022-02-28 19:40:27",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "wagtail",
    "github_project": "django-permissionedforms",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "django-permissionedforms"
}
        
Elapsed time: 0.34938s