पर्यवेक्षित मशीन अनुवाद
यह सामग्री मानव-निर्मित शब्दावलियों और शैली गाइडों के मार्गदर्शन में मशीन जनरेशन द्वारा अनुवादित की गई है। चूँकि इस पाठ की समीक्षा लाइन-दर-लाइन मैन्युअल रूप से नहीं की गई है, इसलिए कभी-कभी त्रुटियाँ या अनाड़ी वाक्य-रचना हो सकती है।
किसी भी विसंगति की स्थिति में, मूल अंग्रेज़ी संस्करण ही प्रामाणिक स्रोत है।
प्लगइन
प्लगइन एक Python package है जो एक single constructor argument के ज़रिए starlette-admin को extend करता है। एक प्लगइन fields, templates, static assets, model converters, filters, import/export formats, storage backends, event subscribers, views, routes, middlewares, theme assets, और translation catalogs — इनमें से किसी भी combination को bundle कर सकता है।
प्लगइन का उपयोग करना
अपना Admin instance बनाते समय प्लगइन को plugins argument के ज़रिए pass करें:
from starlette_admin_geospatial import GeospatialPlugin
from starlette_admin.contrib.sqla import Admin
admin = Admin(engine, plugins=[GeospatialPlugin(default_zoom=13)])
Plugin constructor options लेता है, और list सीधे Admin तक चली जाती है। Setup या register करने की कोई और ज़रूरत नहीं। Options constructor से Python backend, Jinja templates, और frontend JavaScript तक flow होते हैं।
प्लगइन बनाना
प्लगइन लिखने के लिए official cookiecutter template से शुरुआत करें। यह सही directory structure और configuration वाला publishable package generate करता है।
Prerequisites
cookiecutter को अपने package manager से install करें। विवरण के लिए official installation guide देखें:
Scaffolding
Cookiecutter template को किसी भी location से run करें:
Template आपसे plugin का नाम, package slug, version, और कुछ अन्य variables पूछता है। यह पूरा होने पर आपके पास एक self-contained package होता है, जिसमें शामिल हैं:
- आपकी plugin class और fields रखने वाली एक
src/directory। - सही ढंग से namespaced
templates/,static/, औरtranslations/folders। - एक complete test suite।
- Run करने योग्य एक example application।
Plugin API
हर प्लगइन के केंद्र में BasePlugin (starlette_admin.plugins.BasePlugin) का एक subclass होता है, जो Admin के initialize होते समय आपकी features register करने के hooks देता है।
name attribute एक unique kebab-case identifier है जो आपके templates और static assets के namespace का भी काम करता है। आपका plugin ship की गई हर template और static file plugins/<name>/ के अंतर्गत होनी चाहिए।
Asset folders
एक plugin अपने package की root पर ठीक तीन folders रख सकता है। Register करने की कुछ ज़रूरत नहीं, क्योंकि admin उन्हें convention से ढूँढ लेता है:
templates/: Jinja templates, जोtemplates/plugins/<name>/के अंतर्गत होने चाहिए।static/: CSS और JS files जैसे static assets, जोstatic/plugins/<name>/के अंतर्गत होने चाहिए।translations/: Babel translation catalogs।
plugins/<name>/ namespace के भीतर रहने से आपके assets core files या अन्य plugins से टकराते नहीं, साथ ही वे user की अपनी templates_dir या static_dir के ज़रिए override करने योग्य भी बने रहते हैं।
Declarative hooks
Assets inject करने, views register करने, या routes mount करने के लिए declarative hooks को ओवरराइड करें।
css_links(self, request: Request) -> Sequence[str]: हर admin page layout में stylesheets जोड़ता है।js_links(self, request: Request) -> Sequence[str]: हर admin page layout में scripts जोड़ता है।views(self) -> Sequence[BaseView]: Admin sidebar में register होने वाले views return करता है। उन्हें group करने के लिए एकDropDownreturn करें।routes(self) -> Sequence[Route | Mount]:/plugins/<name>/के अंतर्गत mounted headless endpoints return करता है, जो webhooks और proxy endpoints के लिए handy है।middlewares(self) -> Sequence[Middleware]: Starlette middlewares जोड़ता है।template_globals(self) -> dict[str, Any]: Jinja globals expose करता है, जो<name>_prefixed होते हैं ताकि टकराव न हो।template_filters(self) -> dict[str, Callable]: उसी तरह<name>_prefixed Jinja filters expose करता है।
Setup hook
setup(self, admin: BaseAdmin) -> None आपके plugin को core registries के साथ integrate करता है। इसका उपयोग model converters, filters, import और export formats, storage backends, तथा event subscribers register करने के लिए करें। यह declarative hooks apply होने के बाद run होता है।
Lifecycle hook
on_mount(self, admin: BaseAdmin) -> None ठीक एक बार run होता है, Starlette sub-application के build और mount होने के बाद। Built application admin.app के रूप में available होता है।
Templates और overrides
Plugin templates loader chain में अपने-आप शामिल हो जाते हैं। User कोई template override करने के लिए matching path पर अपनी templates_dir के अंदर फ़ाइल रखता है, जिसकी हमेशा priority रहती है। उदाहरण के लिए, plugins/geospatial/fields/form/point.html को override करने के लिए वह templates_dir/plugins/geospatial/fields/form/point.html बनाता है।
User override मूल template को safely extend कर सके, इसके लिए हर plugin को एक @<name> prefix mapping मिलती है, जो @core prefix की तरह काम करती है। Override {% extends "@geospatial/fields/form/point.html" %} से शुरू होता है और base plugin template को recursively include किए बिना उसे extend करता है।
Frontend JavaScript integration
Custom fields ship करने वाला plugin अपनी frontend scripts को field initializer contract के अनुसार package करे। इससे वे full page loads और dynamically insert किए गए fragments दोनों में काम करती रहती हैं।
- Locally target करें: Query हमेशा दिए गए
containerelement के अंदर करें, globaldocumentपर कभी नहीं। - Idempotent बनें: Core initializer को DOM ready पर चलाता है और जब भी inline rows या fragments insert करता है, दोबारा चलाता है।
- Data attributes का उपयोग करें: Field element पर render किए गए
data-*attributes से configuration पढ़ें।
(function () {
function initSlider(container) {
var input = container.querySelector('input[type="range"]');
var output = container.querySelector(".sa-slider-output");
var suffix = container.dataset.suffix || "";
input.addEventListener("input", function () {
output.textContent = input.value + suffix;
});
}
// Register the initializer so core runs it on the right lifecycle events
window.StarletteAdmin.registerFieldInitializer(function (element) {
element.querySelectorAll("[data-sa-slider]").forEach(initSlider);
});
})();
Setup hook के ज़रिए extension points
Plugins अपना अलग extension path बनाने के बजाय existing public registries का उपयोग करते हैं।
- Converters: ORM column types को अपनी field classes में map करने के लिए, जिस contrib backend को target कर रहे हैं उसका
register_convertercall करें। Field को खुद एक ordinaryStringFieldsubclass के रूप में define करें, जो geometries को WKT text के रूप में store और display करता है:
from dataclasses import dataclass
from typing import Any
from starlette_admin.contrib.sqla.converters import register_converter
from starlette_admin.fields import StringField
@dataclass
class MyGeoField(StringField):
...
@register_converter("Geometry")
def convert_geometry(*args: Any, **kwargs: Any) -> MyGeoField:
return MyGeoField(*args, **kwargs)
- Filters: किसी field type से filter classes attach करने के लिए
register_filterscall करें।
from starlette_admin.contrib.sqla.filters import register_filters
register_filters(MyGeoField, WithinBoundingBoxFilter)
- Storage: Azure या GCS जैसा नया backend expose करने के लिए
register_storagecall करें।
- Importers और Exporters:
register_import_formatऔरregister_export_formatका उपयोग करें।
from starlette_admin.export import register_export_format
register_export_format("pdf", PDFExporter())
एक plugin कई ORM backends को support कर सकता है, इसलिए उन्हें setup() के अंदर conditionally import करें। इससे plugin तब भी load होता रहता है जब user ने उनमें से केवल एक ही install किया हो:
def setup(self, admin: "BaseAdmin") -> None:
try:
from starlette_admin_geospatial.contrib.sqla import register_sqla_converters
register_sqla_converters()
except ImportError:
pass # geoalchemy2 or sqlalchemy not installed
आगे क्या
- कस्टम थीम: उसी cookiecutter workflow का उपयोग करके एक पूरा visual system package और share करें।
- इवेंट: Subscriber API जिसे plugin अपने
setup()hook से register करता है। - एक्सटेंशन पॉइंट्स: हर registry और base class जिसमें plugin hook कर सकता है।