Skip to content

Instantly share code, notes, and snippets.

@dz0
Last active June 25, 2019 14:06
Show Gist options
  • Select an option

  • Save dz0/ca12e1f06754adcaaa38decba67e733e to your computer and use it in GitHub Desktop.

Select an option

Save dz0/ca12e1f06754adcaaa38decba67e733e to your computer and use it in GitHub Desktop.
constructed by `GroupObjectsPermission` as example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Experiment form</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
</body>
</html>
########### choose multiple objects (Bookable) for selected group+permission
from django.contrib.auth.models import Permission
## guardian/forms.py
from django import forms
from django.utils.translation import ugettext as _
from guardian.shortcuts import assign_perm, remove_perm, get_objects_for_group
class BasePermissionObjectsForm(forms.Form):
"""
Base form for object permissions management. Needs to be extended for usage
with users and/or groups.
"""
def __init__(self, permission: Permission, model_class=Bookable, *args, **kwargs):
"""
Constructor for BaseObjectPermissionsForm.
:param obj: Any instance which form would use to manage object
permissions"
"""
super().__init__(*args, **kwargs)
self.permission = permission
self.model_class = model_class # TODO: find out from permission codename?
self.field_name = 'objects' # self.get_obj_perms_field_name()
self.fields[self.field_name] = self.get_field()
def get_field_initial(self):
return []
def get_field(self):
"""
Returns field instance for object permissions management. May be
replaced entirely.
"""
field_class = forms.MultipleChoiceField
field = field_class(
label=_('Objects'),
choices=self.get_field_choices(),
initial=list(self.get_field_initial()),
widget=self.get_field_widget(),
required=False,
)
return field
def get_obj_perms_field_name(self):
"""
Returns name of the object permissions management field. Default:
``permission``.
"""
return 'permissions'
def get_queryset(self):
return self.model_class.objects.all().select_related(*self.model_class.__str__.select_related) # TODO: filter by team
def get_field_choices(self):
"""
Returns choices for object permissions management field. Default:
list of tuples ``(codename, name)`` for each ``Permission`` instance
for the managed object.
"""
choices = [(obj.id, str(obj)) for obj in self.get_queryset()]
return choices
def get_field_widget(self):
"""
Returns object permissions management field's widget base class.
Default: ``django.forms.SelectMultiple``.
"""
return forms.CheckboxSelectMultiple
# return forms.SelectMultiple
def save_objects(self):
"""
Must be implemented in concrete form class. This method should store
selected object permissions.
"""
raise NotImplementedError
class GroupPermissionObjectsForm(BasePermissionObjectsForm):
"""
Object level permissions management form for usage with ``Group`` instances.
Example usage::
from django.shortcuts import get_object_or_404
from myapp.models import Post
from guardian.forms import GroupObjectPermissionsForm
from guardian.models import Group
def my_view(request, post_slug, group_id):
group = get_object_or_404(Group, id=group_id)
post = get_object_or_404(Post, slug=post_slug)
form = GroupObjectPermissionsForm(group, post, request.POST or None)
if request.method == 'POST' and form.is_valid():
form.save_obj_perms()
...
"""
def __init__(self, group, *args, **kwargs):
self.group = group
super().__init__(*args, **kwargs)
def get_field_initial(self):
qs_objects = get_objects_for_group(self.group, self.permission.codename, klass=self.model_class)
return qs_objects.values_list('id', flat=True)
def save_objects(self):
"""
Saves selected object permissions by creating new ones and removing
those which were not selected but already exists.
Should be called *after* form is validated.
"""
qs = self.model_class.objects.all()
selected = set(self.cleaned_data[self.field_name])
all = set([c[0] for c in self.get_field_choices()])
initial = set(self.get_field_initial())
to_remove = (all - selected) & initial
remove_perm(self.permission.codename, self.group, qs.filter(id__in=to_remove))
to_assign = selected - initial
assign_perm(self.permission.codename, self.group, qs.filter(id__in=to_assign))
def demo_select_objects(request, group_name='teamX-groupA', permission_name='view_bookable'):
group = get_object_or_404(Group, name=group_name)
permission = get_object_or_404(Permission, codename=permission_name)
form = GroupPermissionObjectsForm(group, permission, request.POST or None)
if request.method == 'POST' and form.is_valid():
form.save_objects()
return render(request, '_experiment_permissions_form.html', context={'form':form})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment