# Filter permissions on a form.

**URL:** <https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172>\
**Category:** Forms & APIs\
**Created:** [June 17, 2024, 6:16pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172 "2024-06-17T18:16:51Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [June 17, 2024, 6:16pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/1 "2024-06-17T18:16:51Z")

</div>

I’m trying to filter the permissions on a form and display only the name.

I have come up with two possible solutions but they do not cover the requirements

The first shows the permissions correctly but shows a validation error saying that the selection is not valid.

```auto
class Permisos(ModelChoiceField):
    def label_from_instance(self, obj):
        return "{}".format(obj.name)
		

class UsuarioCreateForm(forms.ModelForm):
    user_permissions = Permisos( queryset=Permission.objects.filter(content_type=ContentType.objects.get_for_model(RightsSupport)),
         to_field_name='pk', widget=forms.SelectMultiple(), label='Permisos de usuario', required=False,
         help_text="Permisos específicos para este usuario.", )

    class Meta:
        model = Usuario

```

The second one has no errors but shows application|model|permission. I just want the permission to show.

```auto
class UsuarioCreateForm(forms.ModelForm):
    class Meta:
        model = Usuario

        fields = [
            'user_permissions',
        ]
		
    def __init__ (self, *args, **kwargs):
        super(). __init__ (*args, **kwargs)
        self.fields['user_permissions'].queryset = Permission.objects.filter(content_type=ContentType.objects.get_for_model(RightsSupport))	

```

What could I do to achieve it?  
Thanks

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 17, 2024, 6:44pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/2 "2024-06-17T18:44:07Z")

</div>

Your first option superficially looks correct. Can you show the rendered HTML created for that form field?

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [June 17, 2024, 6:49pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/3 "2024-06-17T18:49:25Z")

</div>

```auto
<select name="user_permissions" aria-describedby="id_user_permissions_helptext" id="id_user_permissions" multiple="">
<option value="">---------</option>
<option value="21">Crear usuarios</option>
<option value="23">Eliminar usuarios</option>
<option value="22">Modificar usuarios</option>
</select>

```

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 17, 2024, 6:52pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/4 "2024-06-17T18:52:10Z")

</div>

And if you select one of these named options, you get the validation error?

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [June 17, 2024, 7:01pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/5 "2024-06-17T19:01:06Z")

</div>

Yes, any option generates a validation error.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 17, 2024, 7:06pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/6 "2024-06-17T19:06:03Z")

</div>

Please post the view that is using this form.

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [June 17, 2024, 7:10pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/7 "2024-06-17T19:10:40Z")

</div>

```auto
class ViewCreate(LoginRequiredMixin, PermissionRequiredMixin, SuccessMessageMixin, CreateView):
    template_name = 'crud/baseformcreate.html'
    success_message = REGISTRO_CREADO
    permission_required = ['usuarios.add_usuario']
    model = Usuario
    form_class = UsuarioCreateForm
    success_url = reverse_lazy('usuarios')	

    def __init__ (self):
        super(). __init__ ()
        enctype = ""
        self.extra_context = {'title': 'Agregar ' + self.model._meta.verbose_name,
                              'enctype': enctype,
                              'success_url': self.success_url}

```

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 17, 2024, 7:21pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/8 "2024-06-17T19:21:50Z")

</div>

In your template, are you rendering the entire form as `{{form}}`, or are you rendering the field individually?

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [June 17, 2024, 7:24pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/9 "2024-06-17T19:24:45Z")

</div>

Individually. The two options show identical html, except for the permission name and only the first option gives a validation error, the second works correctly except for the compound name part.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 17, 2024, 7:26pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/10 "2024-06-17T19:26:14Z")

</div>

I just noticed that you don’t have the `fields` attribute in the `Meta` class in your first form. (Is it there and you just don’t show it? What else is in that form?)

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [June 17, 2024, 7:30pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/11 "2024-06-17T19:30:48Z")

</div>

Second option

```auto
<select name="user_permissions" aria-describedby="id_user_permissions_helptext" id="id_user_permissions" multiple="">
<option value="21" selected="">Core | rights support | Crear usuarios</option>
<option value="23">Core | rights support | Eliminar usuarios</option>
<option value="22">Core | rights support | Modificar usuarios</option>
</select>

```

It gives the same validation error by setting the fields attribute or not.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [June 17, 2024, 7:40pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/12 "2024-06-17T19:40:11Z")

</div>

Please post the complete form that you are using in the first version.

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [June 17, 2024, 7:45pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/13 "2024-06-17T19:45:18Z")

</div>

```auto
class Permisos(ModelChoiceField):
    def label_from_instance(self, obj):
        return "{}".format(obj.name)

class UsuarioCreateForm(forms.ModelForm):
    password1 = forms.CharField(
        label="Contraseña",
        strip=False,
        widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
        help_text=password_validation.password_validators_help_text_html(),
    )
    password2 = forms.CharField(
        label="Repita la contraseña",
        widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
        strip=False,
        help_text="Entre la misma contraseña anterior para su verificación.",
    )
    user_permissions = Permisos(
        queryset=Permission.objects.filter(content_type=ContentType.objects.get_for_model(RightsSupport)),
        to_field_name='pk', widget=forms.SelectMultiple(), label='Permisos de usuario', required=False,
        help_text="Permisos específicos para este usuario.", )

    field_order = ['usuario',
                   'nombre',
                   'password1',
                   'password2',
                   'is_active',
                   'email',
                   'telefono',
                   ' __all__']

    class Meta:
        model = Usuario

        fields = [
            'usuario',
            'email',
            'nombre',
            'is_active',
            'telefono',
            'groups',
            #'user_permissions',
        ]

    def __init__ (self, *args, **kwargs):
        super(). __init__ (*args, **kwargs)
        self.fields['nombre'].required = True
        # self.fields['user_permissions'].queryset = Permission.objects.filter(content_type=ContentType.objects.get_for_model(RightsSupport))

    def clean(self):
        cleaned_data = super().clean()
        if 'email' in cleaned_data and cleaned_data['email'] is not None:
            if Usuario.objects.filter(email=cleaned_data['email'].lower()).exists():
                self.add_error('email', 'Este correo ya existe.')
        if 'usuario' in cleaned_data:
            if Usuario.objects.filter(usuario=cleaned_data['usuario'].lower()).exists():
                self.add_error('usuario', 'Este usuario ya existe.')
        if ('password1' in cleaned_data) and ('password2' in cleaned_data):
            if cleaned_data['password1'] != cleaned_data['password2']:
                self.add_error('password2', 'Las contraseñas no coinciden.')

    def clean_password1(self):
        password1 = self.cleaned_data.get('password1')
        try:
            password_validation.validate_password(password1, self.instance)
        except forms.ValidationError as error:

            # Method inherited from BaseForm
            self.add_error('password1', error)
        return password1

    @transaction.atomic
    def save(self):
        cleaned_data = self.cleaned_data
        p = cleaned_data.copy()
        clave = cleaned_data['password1']
        grupos = cleaned_data['groups']
        user_permissions = cleaned_data['user_permissions']
        del p['password1']
        del p['password2']
        del p['groups']
        del p['user_permissions']
        u = Usuario(**p)
        u.set_password(clave)
        u.date_joined = timezone.now()
        u.save()
        u.groups.set(grupos)
        u.user_permissions.set(user_permissions)
        u.save()
        return super()

```

---

<div class="post-metadata">

**Author:** ![felixq](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/felixq/32/8526_2.png) [@felixq](https://forum.djangoproject.com/u/felixq)\
**Post date:** [June 17, 2024, 8:37pm UTC](https://forum.djangoproject.com/t/filter-permissions-on-a-form/32172/14 "2024-06-17T20:37:33Z")

</div>

I found the error after running step by step and following the validation path.  
I was using the wrong inheritance, ModelChoiceField instead of ModelMultipleChoiceField.

```auto
class Permisos(ModelMultipleChoiceField):
    def label_from_instance(self, obj):
        return "{}".format(obj.name)

```
