如何在 Django Wagtail 的小部件中找出当前登录的用户 models.py

问题描述

我一直在寻找一种方法来找出当前登录用户在 Django Wagtail 中的身份,以便我可以创建一个小部件来将基本设置字段呈现为可编辑/不可编辑。我能够使一些基本逻辑正常工作,但无法弄清楚如何找到当前登录用户是谁。有人可以帮我找出解决此问题的最佳和最安全的方法吗?

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 

小部件.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)

解决方法

我终于通过使用 ThreadLocals 弄明白了,我认为这是更简单快捷的方法。

中间件.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 

小部件.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)
,

我找到了另一种方法来做到这一点!这可能比 ThreadLocal 更好,因为我听到了很多关于它的坏消息。我希望这会在将来对某人有所帮助。

panels.py

class RequestBoundFieldPanel(FieldPanel):
    def on_request_bound(self):
        if self.widget:
            setattr(self.widget,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,**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 

小部件.py

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

    def render(self,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)