1

I am creating an expense submission system, which will be multi-user.

For the purpose of this question, there are two models: Claim and Journey. A user creates a claim and each claim can have multiple journeys. I have made a gist of the code snippet as it's quite long.

In this snippet, I have sucessfully:

  • Made ClaimListView.get_queryset filter by current user, so whoever's logged in can only see a list of their own claims.
  • Made ClaimCreateView.form_valid set the correct user when the form is submitted.
  • Made ClaimDetailView.get_queryset filter by current user. If someone tries the url for another user's claim detail, they get a 404 (perfect!)
  • Done the same as above for JourneyListView
  • Done the same as above for JourneyDetailView - again 404 if not authroised :D

However, when I access JourneyCreateView via the URL, the dropdown box for claim still shows claims for the other users.

dropdown box

How should I filter the user within the JourneyCreateView class, so that the claim field only shows claims assigned to the current user?

The closest to a solution I've got is this answer which suggests overriding the __init__ function in the JourneyForm which would leave me with this:

class JourneyForm(forms.ModelForm):
    class Meta:
        model = Journey
        fields = ['date', 'distance','claim']

    def __init__(self,alloweduser,*args,**kwargs):
        super (JourneyForm,self ).__init__(self,*args,**kwargs) # populates the post
        self.fields['claim'].queryset = Claim.objects.filter(tech_id=alloweduser)

However I'm not sure how to pass the alloweduser in from JourneyCreateView or, more to the point, obtain the current user in this class.

form_valid isn't any use in this case, as I'm trying to obtain the user prior to the form being submitted.

v25
  • 7,096
  • 2
  • 20
  • 36

1 Answers1

5

In views, the request the view is handling is stored in self.request, so you can obtain the user with self.request.user, and its id with self.request.user.id.

A Django view with the FormMixin [Django-doc] has a method that can be overwritten to pass parameters: get_form_kwargs() [Django-doc].

So we can implement this as:

from django.views.generic.edit import CreateView

class JourneyCreateView(CreateView):
    model = Journey
    form_class = JourneyForm

    def get_form_kwargs(self, *args, **kwargs):
        kwargs = super().get_form_kwargs(*args, **kwargs)
        kwargs['alloweduser'] = self.request.user.id
        return kwargs

    # ...
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Do you know if anything need to be changed to pass this `alloweduser` back to `JourneyForm`, as with this code edit I get the error **'JourneyForm' object has no attribute 'get'** – v25 Sep 04 '18 at 22:13
  • Dang, the error was in my code, as per: [this](https://snakeycode.wordpress.com/2016/02/29/django-error-form-object-has-no-attribute-get/). This is perfect, now the dropdown only shows the logged in user. – v25 Sep 04 '18 at 22:21