Lukasz Puchala
Lukasz Puchala

Reputation: 476

FormView validation on fields not from form

I am writing a FormView which will add for example a comment on Person object.

I want to check if current user wrote a comment for this Person and if he did I'd like to raise Http404.

Question: What is the best place for this validation? I don't want to call validation in get_context_data and form_valid. Is dispatch method a good place for this logic?

Upvotes: 0

Views: 580

Answers (2)

Timmy O'Mahony
Timmy O'Mahony

Reputation: 53998

Remember that form_valid will only be called when you POST the form so that won't work as GET requests will still render. You could therefore put it in the get method for the FormView which would prevent the view and template loading the initial form. The drawback is that people could technically still POST to that URL if they really wanted to.

As you mentioned, I would put it in the dispatch method. It is very early in the cycle of the FormView so you avoid unnecessary processing.

def dispatch(self, request, *args, **kwargs):
    # I'm just guessing your Comment/Person models
    user = self.request.user
    try:
        person = Person.objects.get(user=self.request.user)
    except:
        raise Http404("No user exists")
    if Comment.objects.filter(content_object=person).exist():
        raise Http404("Comment already exists")
    return super(MyFormView, self).dispatch(request, *args, **kwargs)

EDIT This is a good link describing the various ways you can decorate your class based view to add permission and user checking

Upvotes: 2

I wrote this mixin

class PermissionCheckMixin(object):

    def __init__(self, perm=None, obj=None):
        self.perm = perm
        self.obj = obj

    def dispatch(self, request, *args, **kwargs):
        if request.user.is_anonymous():
            if request.is_ajax():
                return JSONResponseForbidden()
            else:
                return HttpResponseForbidden()

        elif request.user.is_authenticated():
            if self.perm:
                if request.user.has_perm(self.perm, self.obj):
                    return super(PermissionCheckMixin, self).dispatch(request, *args, **kwargs)
                else:
                    if request.is_ajax():
                        return JSONResponseForbidden()
                    else:
                        return HttpResponseForbidden()
            else:
                if request.is_ajax():
                    return JSONResponseForbidden()
                else:
                    return HttpResponseForbidden()

And use it like this:

class TestFormView(PermissionCheckMixin, FormView):
    ...

You can easily adapt this mixin, somehow like this:

def __init__(self, pk):
    self.person_pk = pk

def dispatch(self, request, *args, **kwargs):
    if request.user.is_authenticated():
        if request.user.pk == self.person_pk:
            return HttpResponseNotFound()

Upvotes: 1

Related Questions