0

I have been looking for a way to find out who the current logged-in user is in Django Wagtail so that I could create a widget to render a base setting field to be editable/non-editable. I was able to get some basic logic working but couldn't figure out how to find who the current logged-in user is. Can someone help me find out what's the best and most secure way to go about this?

models.py

    @register_setting
    class AdminSetting(BaseSetting):
      ...
      permitted_retries = models.IntegerField(null=False, default=10)
      panels =[
         FieldPanel('permitted_retries', widget=PermittedRetriesWidget())
      ]
      base_form_class = AdminSettingForm

admin_setting_forms.py

 class AdminSettingForm(WagtailAdminPageForm):

    def __init__(self, user=None, *args, **kwargs):
        self.user = user
        super(AdminSettingForm, self).__init__(*args, **kwargs)
        self.fields['permitted_retries'].widget.user = 'me' # This goes to widget

    def clean(self):
        cleaned_data = super().clean()
        return cleaned_data

    def save(self, commit=True):
        page = super().save(commit=False)
        if commit:
            page.save()
        return page 

widgets.py

    class PermittedRetriesWidget(forms.Widget):
         ...
        def render(self, name, value, attrs=None, renderer=None):
            if self.user.is_superuser:
               return format_html(f'<input type="hidden" name="{name}" value="{value}" id="id_{name}">')
            else:
               output = f'<div style="padding: 1.2em;">{value}</div>'
               input = f'<input type="hidden" name="{name}" value="{value}" id="id_{name}">'
               return format_html(output + input)

2 Answers 2

0

I finally figured it out by using ThreadLocals, I think it's the easier and faster way.

middleware.py

from django.utils.deprecation import MiddlewareMixin
import threading

_thread_locals = threading.local()


def get_current_request():
    return getattr(_thread_locals, 'request', None)


class ThreadLocals(MiddlewareMixin):
    """
    Middleware that gets various objects from the
    request object and saves them in thread local storage.
    """

    def process_request(self, request):
        _thread_locals.request = request

admin_settings_form.py

from app.contrib.middleware import get_current_request

 class AdminSettingForm(WagtailAdminPageForm):

    def __init__(self, user=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        current_user = current_request.user
        is_superuser = current_user.is_superuser or False
        self.fields['permitted_retries'].widget.is_superuser = is_superuser

    def clean(self):
        cleaned_data = super().clean()
        return cleaned_data

    def save(self, commit=True):
        page = super().save(commit=False)
        if commit:
            page.save()
        return page 

widgets.py

class PermittedRetriesWidget(forms.Widget):
     ...
    def render(self, name, value, attrs=None, renderer=None):
        is_superuser = self.is_superuser
        if is_superuser:
           # Shows the input as it is
           return format_html(f'<input type="number" name="{name}" value="{value}" id="id_{name}">')
        else:
           # Hide the input and show the value as uneditable 
           output = f'<div style="padding: 1.2em;">{value}</div>'
           input = f'<input type="hidden" name="{name}" value="{value}" id="id_{name}">'
           return format_html(output + input)
Sign up to request clarification or add additional context in comments.

Comments

0

I have found another way to do this! This is probably better than ThreadLocal as I have been hearing so much bad things about it. I hope this will help someone out in the future.

panels.py

class RequestBoundFieldPanel(FieldPanel):
    def on_request_bound(self):
        if self.widget:
            setattr(self.widget, 'request', self.request)

models.py

from .panels import RequestBoundFieldPanel(FieldPanel):

@register_setting
class AdminSetting(BaseSetting):
  ...
  permitted_retries = models.IntegerField(null=False, default=10)
  panels =[
     RequestBoundFieldPanel('permitted_retries', widget=PermittedRetriesWidget())
  ]
  base_form_class = AdminSettingForm

admin_settings_form.py

 class AdminSettingForm(WagtailAdminPageForm):

    def __init__(self, user=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        is_superuser = self.fields['permitted_retries'].widget.request.user.is_superuser or False

    def clean(self):
        cleaned_data = super().clean()
        return cleaned_data

    def save(self, commit=True):
        page = super().save(commit=False)
        if commit:
            page.save()
        return page 

widgets.py

class PermittedRetriesWidget(forms.Widget):
     ...
    def __init__(self, attrs=None, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super().__init__(*args, **kwargs)

    def render(self, name, value, attrs=None, renderer=None):
        is_superuser = self.request.user.is_superuser or False
        if is_superuser:
           # Shows the input as it is
           return format_html(f'<input type="number" name="{name}" value="{value}" id="id_{name}">')
        else:
           # Hide the input and show the value as uneditable 
           output = f'<div style="padding: 1.2em;">{value}</div>'
           input = f'<input type="hidden" name="{name}" value="{value}" id="id_{name}">'
           return format_html(output + input)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.