o 3aU@sbddlZddlmZddlmZddlmZddlmZddl m Z m Z ddl m Z ddlmZdd lmZdd lmZdd lmZmZmZdd lmZdd lmZmZmZmZddlm Z ddl!m"Z"ddl#m$Z$ddl%m&Z'm(Z(ddl)m*Z*ddl+m,Z,ddl-m.Z.ddl/m0Z0eZ1Gddde2Z3Gddde2Z4GdddZ5Gddde Z6e6Z7dS)N)update_wrapper)WeakSet)apps)settings) ModelAdminactions)AutocompleteJsonView)REDIRECT_FIELD_NAME)ImproperlyConfigured) ModelBase)Http404HttpResponsePermanentRedirectHttpResponseRedirect)TemplateResponse)NoReverseMatch Resolver404resolvereverse) LazyObject) import_string)capfirst)gettext gettext_lazy) never_cache)no_append_slash) csrf_protect)JavaScriptCatalogc@ eZdZdS)AlreadyRegisteredN__name__ __module__ __qualname__r#r#ddZddZddZd>ddZddZddZeddZddZd?dd Zd!d"Zed#d$Z d%d&Z!d>d'd(Z"d>d)d*Z#d>d+d,Z$e%d>d-d.Z&e%d>d/d0Z'd1d2Z(e)d3d4Z*d>d5d6Z+d7d8Z,e%d>d9d:Z-d>d;d<Z.dS)@ AdminSiteal An AdminSite object encapsulates an instance of the Django admin application, ready to be hooked in to your URLconf. Models are registered with the AdminSite using the register() method, and the get_urls() method can then be used to access Django view functions that present a full admin interface for the collection of registered models. zDjango site adminzDjango administrationzSite administration/T-NadmincCs2i|_||_dtji|_|j|_t|dS)Ndelete_selected) _registrynamerr+_actionscopy_global_actions all_sitesaddselfr-r#r#r$__init__Hs   zAdminSite.__init__cCsZ|durt}t|}g}dd|jD}|D]}|jjj|vr*|| q|S)zl Run the system checks on all ModelAdmins, except if they aren't customized at all. Ncss|] }|jtur|VqdSN) __class__r).0or#r#r$ Ysz"AdminSite.check..) rget_app_configssetr,valuesmodel_meta app_configextendcheck)r4 app_configserrors modeladmins modeladminr#r#r$rBOszAdminSite.checkcKs|pt}t|tr |g}|D]X}|jjrtd|j||jvrJt|j|}d|j}| dr@|dt dd|7}t ||d|7}t ||jj sf|r^t|d<td |j|f|}||||j|<qd S) a Register the given model(s) with the given admin class. The model(s) should be Model classes, not instances. If an admin class isn't given, use ModelAdmin (the default admin options). If keyword arguments are given -- e.g., list_display -- apply them as options to the admin class. If a model is already registered, raise AlreadyRegistered. If a model is abstract, raise ImproperlyConfigured. z@The model %s is abstract, so it cannot be registered with admin.z#The model %s is already registered z .ModelAdminz in app %r.z \.ModelAdmin$zwith %r.r!z%sAdminN)r isinstancer r?abstractr r r,strendswithresubrswappedtype)r4model_or_iterable admin_classoptionsr>registered_adminmsgr#r#r$register_s.     zAdminSite.registercCs>t|tr|g}|D]}||jvrtd|j|j|=q dS)zs Unregister the given model(s). If a model isn't already registered, raise NotRegistered. zThe model %s is not registeredN)rHr r,r&r )r4rPr>r#r#r$ unregisters   zAdminSite.unregistercCs ||jvS)zM Check if a model class is registered with this `AdminSite`. )r,)r4r>r#r#r$ is_registereds zAdminSite.is_registeredcCs"|p|j}||j|<||j|<dS)z> Register an action to be available globally. N)r r.r0)r4actionr-r#r#r$ add_actions  zAdminSite.add_actioncCs |j|=dS)zY Disable a globally-registered action. Raise KeyError for invalid names. N)r.r3r#r#r$disable_actions zAdminSite.disable_actioncCs |j|S)z Explicitly get a registered global action whether it's enabled or not. Raise KeyError for invalid names. )r0r3r#r#r$ get_action zAdminSite.get_actioncCs |jS)zM Get all the enabled actions as an iterable of (name, func). )r.itemsr4r#r#r$rr\zAdminSite.actionscCs|jjo|jjS)z| Return True if the given HttpRequest has permission to view *at least one* page in the admin site. )user is_activeis_staffr4requestr#r#r$has_permissionszAdminSite.has_permissionFcs8fdd}|s t|}tddst|}t|S)a Decorator to create an admin view attached to this ``AdminSite``. This wraps the view and provides permission checking by calling ``self.has_permission``. You'll want to use this from within ``AdminSite.get_urls()``: class MyAdminSite(AdminSite): def get_urls(self): from django.urls import path urls = super().get_urls() urls += [ path('my_view/', self.admin_view(some_view)) ] return urls By default, admin_views are marked non-cacheable using the ``never_cache`` decorator. If the view can be safely cached, set cacheable=True. csn|s,|jtdjdkrtdjd}t|Sddlm}||tdjdS|g|Ri|S)Nz admin:logout current_app admin:indexr)redirect_to_loginz admin:login)rdpathrr-rdjango.contrib.auth.viewsrh get_full_path)rcargskwargs index_pathrhr4viewr#r$inners   z#AdminSite.admin_view..inner csrf_exemptF)rgetattrrr)r4rp cacheablerqr#ror$ admin_views    zAdminSite.admin_viewc srddlm}ddlm}m}m}d fdd }|d|jdd |d jd d |d |jd d |d|j dddd |d|j dddd |d|j dd |d|j dddd |d||j dd g}g}jD]$\}} ||d|jj|jjf|| jg7}|jj|vr||jjql|rdd|d} ||| |jdd g7}jr||d|j|S)!Nr)views)includerire_pathFcs fdd}|_t|S)Ncs|i|Sr6)ru)rlrm)rtr4rpr#r$wrappersz1AdminSite.get_urls..wrap..wrapper) admin_siter)rprtryr^)rtrpr$wraps z AdminSite.get_urls..wraprGindex)r-zlogin/loginzlogout/logoutzpassword_change/T)rtpassword_changezpassword_change/done/password_change_donez autocomplete/ autocompletezjsi18n/jsi18nz)r/// view_on_sitez%s/%s/z^(?P|z)/$app_listz (?P.*)$F)django.contrib.contenttypesrv django.urlsrwrirxr|r}r~rrautocomplete_viewi18n_javascriptshortcutr,r]r? app_label model_nameurlsappendjoin app_indexfinal_catch_all_viewcatch_all_view) r4contenttype_viewsrwrirxr{ urlpatternsvalid_app_labelsr> model_adminregexr#r^r$get_urlssH   zAdminSite.get_urlscCs|d|jfSNr*)rr-r^r#r#r$r)szAdminSite.urlscCsH|jd}|jdkr|r|n|j}|j|j|||||d|jdS)z Return a dictionary of variables to put in the template context for *every* page in the admin site. For sites running on a subpath, use the SCRIPT_NAME value if site_url hasn't been customized. SCRIPT_NAMEr(F) site_title site_headersite_urlrdavailable_appsis_popupis_nav_sidebar_enabled)METArrrrd get_app_listenable_nav_sidebar)r4rc script_namerr#r#r$ each_context-s zAdminSite.each_contextcCstddlm}ddlm}td|jd}||i|||pid}|jdur,|j|d<|j|_|j d i||S) zX Handle the "change password" task -- both form display and validation. r)AdminPasswordChangeForm)PasswordChangeViewzadmin:password_change_donere) form_class success_url extra_contextN template_namer#) django.contrib.admin.formsrrjrrr-rpassword_change_templaterfas_view)r4rcrrrurldefaultsr#r#r$rAs    zAdminSite.password_changecCsVddlm}di|||pii}|jdur|j|d<|j|_|jdi||S)zE Display the "success" page after a password change. r)PasswordChangeDoneViewrNrr#)rjrrpassword_change_done_templater-rfr)r4rcrrrr#r#r$rRs   zAdminSite.password_change_donecCstjdgd|S)z Display the i18n JavaScript that the Django admin requires. `extra_context` is unused but present for consistency with the other admin views. zdjango.contrib.admin)packages)rr)r4rcrr#r#r$r_szAdminSite.i18n_javascriptcCs^ddlm}di||ddi|pii}|jdur!|j|d<|j|_|jdi||S) z~ Log out the user for the given HttpRequest. This should *not* assume the user is already logged in. r) LogoutViewrrdFNrr#)rjrrlogout_templater-rfr)r4rcrrrr#r#r$r~hs  zAdminSite.logoutcCs|jdkr||rtd|jd}t|Sddlm}ddlm}i| |t d| |j d}t|jvrHt|jvrHtd|jd|t<||pMi||jpT||jpXd d }|j|_|jd i||S) zC Display the login form for the given HttpRequest. GETrgrer)AdminAuthenticationForm) LoginViewzLog in)titleapp_pathusernamezadmin/login.html)rauthentication_formrNr#)methodrdrr-rrrrjrr_rkr_ get_usernamer rPOSTupdate login_formlogin_templaterfr)r4rcrrnrrcontextrr#r#r$r}~s,    zAdminSite.logincCstj|d|S)N)rz)rrrbr#r#r$rszAdminSite.autocomplete_viewcCsftjr1|ds1t|dd}z td|j|}Wn ty"Yt wt|jddr1td|j St )Nr(urlconfz%s/should_append_slashT) r APPEND_SLASHrKrsr path_inforfuncr rir )r4rcrrmatchr#r#r$rs  zAdminSite.catch_all_viewc sxi}rfdd|jD}n|j}|D]\}}|jj}||}|s(q||} d| vr4q||jjf} t|jj |jj | ddd} | dsR| drq| d | d<z t d | |j d | d <Wn typYnw| d rz t d | |j d | d<Wn tyYnw||vr||d| qt|j|t dd|i|j d|| gd||<qr| S|S)zt Build the app dictionary. The optional `label` parameter filters models of a specific app. cs"i|] \}}|jjkr||qSr#)r?r)r8mm_alabelr#r$ s  z-AdminSite._build_app_dict..TN)r- object_nameperms admin_urladd_urlchangerp view_onlyzadmin:%s_%s_changelistrerr2zadmin:%s_%s_addrmodelszadmin:app_listr)rmrf)r-rapp_urlhas_module_permsr)r,r]r?rhas_module_permissionget_model_permsr=rrverbose_name_pluralrgetrr-rrrget_app_config verbose_name) r4rcrapp_dictrr>rrrrinfo model_dictr#rr$_build_app_dictsb            zAdminSite._build_app_dictcCs@||}t|ddd}|D] }|djdddq|S)zp Return a sorted list of all the installed apps that have been registered in this site. cSs |dSNr-)lowerxr#r#r$s z(AdminSite.get_app_list..keyrcS|dSrr#rr#r#r$r)rsortedr=sort)r4rcrrappr#r#r$rs zAdminSite.get_app_listcCsH||}i|||jd|d|pi}|j|_t||jp!d|S)z Display the main admin index page, which lists all of the installed apps that have been registered in this site. N)rsubtitlerzadmin/index.html)rr index_titler-rfrindex_template)r4rcrrrr#r#r$r|s zAdminSite.indexcCs|||}|s td|djdddi||tdd|did|g|d |p/i}|j|_t||jp?d |d g|S) Nz(The requested admin page does not exist.rcSrrr#rr#r#r$rrz%AdminSite.app_index..rz%(app)s administrationrr-)rrrrzadmin/%s/app_index.htmlzadmin/app_index.html) rr rrrr-rfrapp_index_template)r4rcrrrrr#r#r$rs*  zAdminSite.app_index)r*r6r)/r r!r"__doc__rrrrrrempty_value_displayrrrrrrrrr5rBrUrVrWrYrZr[propertyrrdrurrrrrrrr~r}rrrrrr|rr#r#r#r$r'%s^   0   ,8      !  D r'c@seZdZddZdS)DefaultAdminSitecCsttdj}||_dSr)rrr default_site_wrapped)r4AdminSiteClassr#r#r$_setup0s zDefaultAdminSite._setupN)r r!r"rr#r#r#r$r/s r)8rL functoolsrweakrefr django.appsr django.confrdjango.contrib.adminrr'django.contrib.admin.views.autocompleterdjango.contrib.authr django.core.exceptionsr django.db.models.baser django.httpr r rdjango.template.responserrrrrrdjango.utils.functionalrdjango.utils.module_loadingrdjango.utils.textrdjango.utils.translationrrrdjango.views.decorators.cacherdjango.views.decorators.commonrdjango.views.decorators.csrfrdjango.views.i18nrr1 Exceptionrr&r'rsiter#r#r#r$s>