0

I have to make a system which will allow users to progressively fill out surveys based on whether or not the initial survey was accepted.

What this means is that after the user has logged in, they need to be able to fill in a preliminary survey for screening purposes. Only once this preliminary screening survey has been approved by an administrative user (superuser) will the user have access to the second (and final) survey.

I have a survey model which looks like this:

class Screening_survey(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=20)
    surname = models.Charfield(max_length=20)
    salary = models.IntegerField()
    is_accepted = models.NullBooleanField()

When the user posts this initial survey, they only fill in the name, surname and salary fields. When the survey is initially posted, 'user' is set to the current logged in user (request.user) and is_accepted is simply set to 'unknown' automatically in the background. It is then up to the administrative superuser to change the is_accepted value to 'yes' or 'no'.

If the value of the is_accepted field is set to yes for a particular user's form, then that user should be able to access the next survey.

I have looked at Django permissions, but I do not think the default permissions will work for me seeing as I don't want users of a specific /group/ to have access to specific pages; rather I want users whose initial surveys have been approved to have access to the next view (the final survey).

I have also given the @user_passes_test decorator some thought, but again it seems as if it checks permissions only on a user basis and not on the basis of a user and a model that is linked to them.

I know this question seems simple -- I'm quite new to Django as well as programming in general).

Thank you for your help.

SimoneC
  • 5
  • 1
  • 6

1 Answers1

1

You're spot on - you will need to define your own logic to see if the user has been approved, not permissions. Permissions don't really allow you to test on a per-user or per-model basis the way you're looking for.

There are two places to define where this test will be. Either in the view itself, or via your own @user_passes_test decorator. You already have a Foreign Key to the user object, so you can write a test in the view, like this:

@login_required
def survey_view(request):
    survey = Screening_survey.objects.filter(user=request.user)
    if survey and survey.is_accepted is 'yes':
        # Do the remaining view logic
    else:
        raise PermissionDenied

If you want to put this logic in the @user_passes_test, that would work well too. The user object is passed directly (see the docs for an example)

Tristan
  • 141
  • 5
  • Thanks Tristan. This looks as if it will work. I'll implement it soon and upvote your answer. – SimoneC Mar 01 '16 at 07:12
  • Thanks, Tristan. The logic was correct. I did get an error, however, stating that the QuerySet (Screening_survey) does not have an attribute 'is_accepted'. I rewrote it slightly and then it worked: if Screening_survey.objects.filter(user=request.user, is_accepted="Yes"): [rest of logic follows]. Still, good logic! – SimoneC Mar 03 '16 at 11:49