1fromtypingimportTYPE_CHECKING,Optional 2 3fromplain.auth.viewsimportAuthViewMixin 4fromplain.runtimeimportsettings 5fromplain.urlsimportreverse 6fromplain.utilsimporttimezone 7fromplain.viewsimport( 8TemplateView, 9) 10 11from..utilsimportget_gravatar_url 12from.registryimportregistry 13from.typesimportImg 14 15ifTYPE_CHECKING: 16from..cardsimportCard 17 18 19URL_NAMESPACE="admin" 20 21 22classAdminView(AuthViewMixin,TemplateView): 23admin_required=True 24 25title:str="" 26path:str="" 27image:Img|None=None 28 29# Leave empty to hide from nav 30# 31# An explicit disabling of showing this url/page in the nav 32# which importantly effects the (future) recent pages list 33# so you can also use this for pages that can never be bookmarked 34nav_title="" 35nav_section="" 36nav_icon="app" 37 38links:dict[str,str]={} 39 40parent_view_class:Optional["AdminView"]=None 41 42template_name="admin/page.html" 43cards:list["Card"]=[] 44 45defget_response(self): 46response=super().get_response() 47response.headers["Cache-Control"]=( 48"no-cache, no-store, must-revalidate, max-age=0" 49) 50returnresponse 51 52defget_template_context(self): 53context=super().get_template_context() 54context["title"]=self.get_title() 55context["image"]=self.get_image() 56context["slug"]=self.get_slug() 57context["links"]=self.get_links() 58context["parent_view_classes"]=self.get_parent_view_classes() 59context["admin_registry"]=registry 60context["cards"]=self.get_cards() 61context["render_card"]=lambdacard:card().render(self,self.request) 62context["time_zone"]=timezone.get_current_timezone_name() 63context["is_admin_view"]=True 64context["view_class"]=self.__class__ 65context["app_name"]=settings.APP_NAME 66context["get_gravatar_url"]=get_gravatar_url 67returncontext 68 69@classmethod 70defview_name(cls)->str: 71returnf"view_{cls.get_slug()}" 72 73@classmethod 74defget_slug(cls)->str: 75returnf"{cls.__module__}.{cls.__qualname__}".lower().replace(".","_") 76 77# Can actually use @classmethod, @staticmethod or regular method for these? 78defget_title(self)->str: 79returnself.title 80 81defget_image(self)->Img|None: 82returnself.image 83 84@classmethod 85defget_path(cls)->str: 86returncls.path 87 88@classmethod 89defget_parent_view_classes(cls)->list["AdminView"]: 90parents=[] 91parent=cls.parent_view_class 92whileparent: 93parents.append(parent) 94parent=parent.parent_view_class 95returnparents 96 97@classmethod 98defget_nav_title(cls)->str: 99ifcls.nav_title:100returncls.nav_title101102ifcls.title:103returncls.title104105raiseNotImplementedError(106f"Please set a title or nav_title on the {cls} class or implement get_nav_title()."107)108109@classmethod110defget_view_url(cls,obj=None)->str:111# Check if this view's path expects an id parameter112ifobjand"<int:id>"incls.get_path():113returnreverse(f"{URL_NAMESPACE}:"+cls.view_name(),id=obj.id)114else:115returnreverse(f"{URL_NAMESPACE}:"+cls.view_name())116117defget_links(self)->dict[str]:118returnself.links.copy()119120defget_cards(self):121returnself.cards.copy()