Search code examples
djangodjango-formsdjango-authentication

Making a form field compulsory only for specific users


Is it possible to make a form field, in a template, compulsory, or non compulsory, for specific user? I have a field which I'd like to be compulsory for everyone but the administrator.

My understanding is that it is not possible, since the null=False, blank=False in the model.py is valid for all the instances of the field. Am I wrong?

Edit - adding code

models.py

class Work(models.Model):
    [...]
    title = models.CharField(max_length=200) # max_length = required
    [...]

class Event(models.Model):
    [...]
    repertoire = models.ManyToManyField(Work, blank=True)
    [...]

forms.py

from .models import Work, Event
class EventForm(forms.ModelForm):

    required_css_class = 'required'

    class Meta:
        model = Event
        fields = [
            [...]
            'repertoire',
            [...]
                    }
    def __init__(self, *args, **kwargs):
        super(EventForm, self).__init__(*args, **kwargs)

views.py

from .forms import EventForm,
@never_cache
def event_create_view(request):
    active_user = request.user
    form_event = EventForm(request.POST or None, initial={'submitted_by' : active_user.profile.id})

    if request.method == "POST" and form_event.is_valid():

        this_event = form_event.save()
        return redirect('event-edit', id=this_event.id)

    else:
        messages.error(request, form_event.errors)

    context = {
            'form_event': form_event,
            }

template.html

<form id="eventForm" action='.' enctype="multipart/form-data" method='POST'>
[...]
{{ form_event.repertoire }}
[...]
    <input class="button" type='submit' value='Continue ->' />

</form>

Solution

  • You can make the field required for certain users. For example by adding an extra parameter:

    from .models import Work, Event
    
    class EventForm(forms.ModelForm):
        required_css_class = 'required'
    
        class Meta:
            model = Event
            fields = [
                # …
                'repertoire',
                # …
            ]
        def __init__(self, *args, repertoire_required=True, **kwargs):
            super(EventForm, self).__init__(*args, **kwargs)
            self.fields['repertoire'].required = repertoire_required

    In the view, we then specify the parameter, based on the fact if the logged in user is for example an is_admin:

    from .forms import EventForm
    from django.contrib.auth.decorators import login_required
    
    @never_cache
    @login_required
    def event_create_view(request):
        active_user = request.user
        if request.method == 'POST':
            form_event = EventForm(
                request.POST,
                repertoire_required=not active_user.is_superuser,
                initial={'submitted_by' : active_user.profile.id }
            )
            if form_event.is_valid():
                this_event = form_event.save()
                return redirect('event-edit', id=this_event.id)
            else:
                messages.error(request, form_event.errors)
        else:
            form_event = EventForm(
                request.POST,
                repertoire_required=not active_user.is_superuser
            )
        context = {
            'form_event': form_event,
        }
        # …