Request: pass request.user as a kwarg to WriteForm and ReplyForm

Issue #118 closed
Tylere Couture created an issue

That would allow for more options when defining a custom form. For example, I would like to limit the recipients queryset based on who the user is, kind of like an exchange filter that occurs up front (I can’t even get an exchange filter to work as a backup anyway, see my bug report)

Comments (9)

  1. Tylere Couture reporter

    Thanks for the reply!

    Here's what I'm trying, but all I'm getting is None.  How would I access the 'sender' in my custom form?

    class CustomWriteForm(WriteForm):
    
        recipients = CustomRecipientsField()
    
        def init(self, *args, **kwargs):
            sender = kwargs.get('sender')  # results in None
            super(WriteForm, self).__init__(*args, **kwargs)
    
            if not sender.is_staff:  # non-staff can only send messages to staff
                self.fields['recipients'].queryset = User.objects.filter(is_staff=True)
    
  2. Tylere Couture reporter
    args: ()
    kwargs: {'initial':{}, ‘prefix’:None, ‘channel’:None}
    

    stabbing in the dark I tried inheriting from BaseWriteForm, and also moving the call to super to the top, but no success.

  3. Patrick Samson repo owner

    Where your init() comes from? and how do you call it?

    It should be named __init__().

  4. Patrick Samson repo owner

    In your real code, super is called first and that’s a big difference, because ‘sender’ is kwargs.pop from there, so you won’t find it anymore afterwards with your kwargs.get.

    (same misunderstanding with super() syntax as reported in #117)

    In reports always mention actual code, never a transcription.

  5. Tylere Couture reporter

    I’ve fixed the super call, but the form still seems to not have all the kwargs I’m expecting.

    class HackerspaceWriteForm(WriteForm):
    
        recipients = CustomPostmanUserField()
    
        def __init__(self, *args, **kwargs):
            sender = kwargs.get('sender', None)
            print("KWARGS:", kwargs) # empty with GET, full with POST
    
            super().__init__(*args, **kwargs)
    

    Full code: https://github.com/timberline-secondary/hackerspace/blob/postman-custom/src/hackerspace_online/postman.py

    Here's my kwargsoutput when the form is initialized:

    KWARGS: {'initial': {}, 'prefix': None, 'channel': None}
    [17/Aug/2019 16:12:58] "GET /messages/write/ HTTP/1.1" 200 33632

    However, after I post the message, I can see the kwargs are all populated:

    KWARGS: {'initial': {}, 'prefix': None, 'data': <QueryDict: {'csrfmiddlewaretoken': ['2ZOcKeylN…..dkPqfZC8S'], 'recipients': ['1', '2'], 'subject': ['to myself'], 'body': ['asdasd']}>, 'files': <MultiValueDict: {}>, 'sender': <SimpleLazyObject: <User: 9999999>>, 'user_filter': None, 'exchange_filter': None, 'max': None, 'site': <Site: example.com>, 'channel': None}
    FILTERING!!!
    FILTERING!!!
    [17/Aug/2019 16:17:28] "POST /messages/write/?next=/messages/write/ HTTP/1.1" 200 33850

    Is there anything I can do to get the sender when the form is loaded with GET?

  6. Patrick Samson repo owner

    A possible solution is to implement a custom view.

    You should already have a custom postman urls.py because of your custom WriteForm. In it, change the standard WriteView.as_view(…) by, say, WriteView2.as_view(…), and implement:

    class WriteView2(WriteView):
        def get_form_kwargs(self):
            kwargs = super().get_form_kwargs()
            kwargs['sender'] = self.request.user
            return kwargs
    

    You may also code instead:

            if self.request.method == 'GET':
                kwargs['is_staff'] = self.request.user.is_staff
    

  7. Log in to comment