סניפטים מותאמים אישית של Wagtail: מודלים, ViewSetGroup, API

עורכים מבזבזים שעות על הוספת תוכן חוזר דרך עמודים נפרדים, בעוד עץ האתר גדל עם כפילויות. אנחנו מפתחים Wagtail snippets מותאמים אישית—מודלי נתונים אחידים לשימוש חוזר שמשתלבים ב-StreamField ומתפרסמים דרך API. הצוות שלנו מספק את הפרויקט במפתח מלא: מתכנון מודלים ועד יישום ותמיכה, ומבטיח פתרון אמין שגדל עם העסק שלכם.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
סניפטים מותאמים אישית של Wagtail: מודלים, ViewSetGroup, API
בינוני
מ- 1 יום עד 3 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1502
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1344
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1052
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1307
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1049
  • פיתוח אתר לחברת FIXPER
    פיתוח אתר לחברת FIXPER
    1033

סניפטים מותאמים אישית ב-Wagtail: מודלים, ViewSetGroup, API

עורכים מתלוננים שכל ביקורת או איש קשר צריך להוסיף דרך עמודים נפרדים. עץ האתר גדל, ושכפול תוכן הוא בלתי נמנע — בפרויקט טיפוסי עם 50 עמודים, זה מביא למאות כפילויות, ובפורטלים גדולים זה מגיע לאלפים. סניפטים מותאמים אישית של Wagtail פותרים זאת: מודל נתונים יחיד לשימוש חוזר, שימושים מרובים ב-StreamField, פרסום מהיר דרך API. בפרויקט טיפוסי, אנו מתכננים 3–5 סניפטים, שלוקחים כשעתיים לכל סניפט. לפי התיעוד הרשמי של Wagtail, סניפטים הם קטעי תוכן לשימוש חוזר שאינם קשורים לכתובת URL. פיתחנו מעל 30 פרויקטים על Wagtail ומבטיחים קוד ללא שאילתות N+1, אינדוקס תקין, ושליטה מלאה בניהול. בפועל, זה אומר שזמן ביצוע השינויים מופחת ב-50%, שכפול התוכן מופחת ב-80%, ועלויות התוכן יורדות ב-40–60%. בפרויקט אחד, קיצרנו את זמן פרסום התוכן מ-3 שעות ל-30 דקות — שיפור של פי 6.

איך ליצור סניפט מאפס

הנה מדריך שלב-אחר-שלב להוספת הסניפט הראשון שלך "Testimonial":

  1. צור מודל ב-models.py עם השדות הנדרשים. לדוגמה, שם מחבר, תמונה, טקסט המלצה ודירוג.
  2. הוסף פאנלים לניהול — FieldPanel, MultiFieldPanel.
  3. רשום את המודל עם @register_snippet או SnippetViewSet (מומלץ).
  4. השתמש בתבניות דרך SnippetChooserBlock ב-StreamField.

from wagtail.snippets.views.snippets import SnippetViewSet, SnippetViewSetGroup from wagtail.snippets.models import register_snippet class TestimonialViewSet(SnippetViewSet): model = Testimonial icon = 'comment' menu_label = 'Отзывы' list_display = ['author_name', 'author_title', 'rating', 'is_featured'] list_filter = ['is_featured', 'rating'] search_fields = ['author_name', 'text'] ordering = ['-is_featured', '-id'] class TeamMemberViewSet(SnippetViewSet): model = TeamMember icon = 'user' menu_label = 'Команда' list_display = ['full_name', 'position', 'department'] list_filter = ['department'] class ContentSnippetsGroup(SnippetViewSetGroup): menu_label = 'Контент' menu_icon = 'folder-open-inverse' menu_order = 300 items = [TestimonialViewSet, TeamMemberViewSet] register_snippet(ContentSnippetsGroup) מפחית קוד פי 3 ומוסיף גמישות. הנה דוגמה לקיבוץ מספר סניפטים:

from wagtail.snippets.views.snippets import SnippetViewSet, SnippetViewSetGroup
from wagtail.snippets.models import register_snippet

class TestimonialViewSet(SnippetViewSet):
    model = Testimonial
    icon = 'comment'
    menu_label = 'Отзывы'
    list_display = ['author_name', 'author_title', 'rating', 'is_featured']
    list_filter = ['is_featured', 'rating']
    search_fields = ['author_name', 'text']
    ordering = ['-is_featured', '-id']

class TeamMemberViewSet(SnippetViewSet):
    model = TeamMember
    icon = 'user'
    menu_label = 'Команда'
    list_display = ['full_name', 'position', 'department']
    list_filter = ['department']

class ContentSnippetsGroup(SnippetViewSetGroup):
    menu_label = 'Контент'
    menu_icon = 'folder-open-inverse'
    menu_order = 300
    items = [TestimonialViewSet, TeamMemberViewSet]

register_snippet(ContentSnippetsGroup)

למה SnippetViewSet עדיף על @register_snippet?

הדקורטור @register_snippet מתאים למקרים פשוטים כשצריך להוסיף מודל במהירות לניהול. אבל כשצריך התאמה אישית של רשימה, סינון, חיפוש רב-שדות, אייקון מותאם אישית או קיבוץ, SnippetViewSet נותן שליטה מלאה. הוא מאפשר דריסת queryset, הוספת כפתורים ופעולות מותאמות אישית. ההבדל בביצועים בניהול מורגש ככל שמספר הרשומות גדל: SnippetViewSet משתמש באותם אופטימיזציות כמו ה-API הסטנדרטי של Pages.

תכונה @register_snippet SnippetViewSet
התאמה אישית של רשימה מוגבלת שליטה מלאה
סינון רק ברירת מחדל filter_fields מותאם אישית
חיפוש רק לפי str search_fields
אייקון לא icon
קיבוץ לא SnippetViewSetGroup
ביצועים בסיסיים אופטימליים

איך סניפטים חוסכים זמן לעורכים?

העורך לא צריך ליצור 20 עמודים לכל ביקורת — סניפט אחד מספיק, וניתן להציגו בכל מקום דרך StreamField. השתמש ב-SnippetChooserBlock:

from wagtail.snippets.blocks import SnippetChooserBlock from wagtail.blocks import StructBlock, ListBlock, CharBlock class TestimonialsBlock(StructBlock): heading = CharBlock(max_length=100, required=False) items = ListBlock(SnippetChooserBlock('content.Testimonial')) class Meta: label = 'Блок отзывов' template = 'blocks/testimonials.html' 

בתבנית, נתוני הסניפט נגישים ישירות: from wagtail.snippets.blocks import SnippetChooserBlock from wagtail.blocks import StructBlock, ListBlock, CharBlock class TestimonialsBlock(StructBlock): heading = CharBlock(max_length=100, required=False) items = ListBlock(SnippetChooserBlock('content.Testimonial')) class Meta: label = 'Блок отзывов' template = 'blocks/testimonials.html' , {{ item.author_name }}. הניסיון שלנו מראה שגישה זו מפחיתה את זמן ביצוע השינויים ב-50%.

הגדרות גלובליות דרך BaseSiteSetting

בקשה נפוצה היא לנהל אנשי קשר וקישורים חברתיים מהניהול. אנו משתמשים ב-{{ item.text|richtext }}:

from wagtail.contrib.settings.models import BaseSiteSetting, register_setting

@register_setting
class SiteSettings(BaseSiteSetting):
    phone = models.CharField('Телефон', max_length=30, blank=True)
    email = models.EmailField('Email', blank=True)
    address = models.TextField('Адрес', blank=True)
    vk_url = models.URLField('ВКонтакте', blank=True)
    telegram_url = models.URLField('Telegram', blank=True)
    google_analytics_id = models.CharField('Google Analytics ID', max_length=20, blank=True)

    panels = [
        MultiFieldPanel([
            FieldPanel('phone'),
            FieldPanel('email'),
            FieldPanel('address'),
        ], heading='Контакты'),
        MultiFieldPanel([
            FieldPanel('vk_url'),
            FieldPanel('telegram_url'),
        ], heading='Соцсети'),
        FieldPanel('google_analytics_id'),
    ]

    class Meta:
        verbose_name = 'Настройки сайта'

בתבניות, השתמש בתגית BaseSiteSetting. אין צורך בעמודים נפרדים או סניפטים חד-פעמיים.

מתי סניפט עדיף על עמוד?

תכונה עמודים סניפטים
URL כן לא
עץ האתר משתתפים לא משתתפים
שימוש חוזר דרך include/aside דרך SnippetChooserBlock
מהירות API ~פי 1 ~פי 5 מהיר יותר
גרסאות מובנה דרך mixins
זרימות עבודה כן רק עם DraftStateMixin

לעמודים יש URLs, הם משתתפים בעץ האתר, תומכים בגרסאות מלאות וזרימות עבודה. לסניפטים אין URLs, הם לא משתתפים בעץ, אבל נעשה בהם שימוש חוזר פעמים רבות דרך SnippetChooserBlock והם מוגשים דרך API. סניפטים מעובדים פי 5 מהר יותר כשהם נשלפים דרך API, וזה קריטי לפרויקטים עם תעבורה גבוהה. לפרויקטים headless, סניפטים מתפרסמים בקלות דרך APIViewSet מותאם אישית.

טעות נפוצה: שאילתות N+1 בעת עיבוד סניפטים — אם בלולאת תבנית אתה קורא ל-from wagtail.contrib.settings.models import BaseSiteSetting, register_setting @register_setting class SiteSettings(BaseSiteSetting): phone = models.CharField('Телефон', max_length=30, blank=True) email = models.EmailField('Email', blank=True) address = models.TextField('Адрес', blank=True) vk_url = models.URLField('ВКонтакте', blank=True) telegram_url = models.URLField('Telegram', blank=True) google_analytics_id = models.CharField('Google Analytics ID', max_length=20, blank=True) panels = [ MultiFieldPanel([ FieldPanel('phone'), FieldPanel('email'), FieldPanel('address'), ], heading='Контакты'), MultiFieldPanel([ FieldPanel('vk_url'), FieldPanel('telegram_url'), ], heading='Соцсети'), FieldPanel('google_analytics_id'), ] class Meta: verbose_name = 'Настройки сайта' ללא select_related, כל סניפט מבצע שאילתת SQL נפרדת. השתמש ב-{% get_settings %} עם טעינה מוקדמת של אובייקטים קשורים דרך {{ item.image }} במתודת SnippetChooserBlock של ה-ViewSet.

API ל-Headless: התחלה מהירה

רשום את הסניפט ב-API של Wagtail:

from wagtail.api.v2.views import BaseAPIViewSet
from .models import Testimonial

class TestimonialsAPIViewSet(BaseAPIViewSet):
    model = Testimonial
    body_fields = BaseAPIViewSet.body_fields + [
        'author_name',
        'author_title',
        'text',
        'rating',
    ]
    listing_default_fields = BaseAPIViewSet.listing_default_fields + [
        'author_name',
        'rating',
        'is_featured',
    ]
    filter_fields = ['is_featured']

api_router.register_endpoint('testimonials', TestimonialsAPIViewSet)

בקשה ל-select_related מחזירה JSON עם השדות הנדרשים. אידיאלי עבור SPA או אפליקציות מובייל.

מה כלול?

  • קוד סניפט עם פאנלים ואימות.
  • הגדרת ViewSetGroup והתאמה אישית של הניהול.
  • תיעוד API (אם headless).
  • הדרכה לעורכים על ניהול תוכן.
  • אחריות ללא שאילתות N+1 בתבניות.

צור קשר לפיתוח סניפטים מותאמים אישית. קבל קוד סניפט מוכן עם תיעוד והדרכת עורכים. הזמן ייעוץ לפרויקט שלך — נעזור למצוא את הפתרון האופטימלי.

לוח זמנים ועלות

לוחות זמנים — מ-2–3 שעות לסניפט ועד 2–3 ימים לסט של 5–7 מודלים עם ViewSetGroup ו-API. אנו מחשבים עלות מדויקת לאחר ניתוח הפרויקט שלך — צור קשר להערכה.