Oruji.org
Oruji.orgPersian Tutorials
ورود
ویرایش: 1396/11/13 19:19

آموزش تولید محتوای غیر html ای در جنگو (Django)

معمولا هنگامی که درباره ی deploy کردن وب سایت ها صحبت می شود، موضوع صحبت درباره ی تولید HTML می باشد. البته که موارد بسیار دیگری نیز وجود دارد؛ ما از وب برای توزیع داده در تمام قابل بندی ها استفاده می کنیم: RSS، PDF، عکس ها و غیره ....

تاکنون، تمرکز بر روی تولید HTML بوده است، ولی در این آموزش از کتاب، از این مسیر منحرف شده و به استفاده ی جنگو برای تولید انواع دیگر محتویات به غیر از HTML خواهیم پرداخت.

جنگو دارای ابزار داخلی مناسبی می باشد که می توان برای تولید برخی محتوای به غیر از HTML از آن استفاده کرد:

هر کدام از ابزار فوق در این فصل بررسی خواهند شد، ولی ابتدا قواعد اولیه را پوشش خواهیم داد.

اصول اولیه: view ها و MIME-type ها

آموزش view و urlconf جنگو را بخاطر بیاورید که یک تابع view به سادگی یک تابپ پایتون می باشد که یک درخواست وب را دریافت کرده و یک پاسخ وب را بر می گرداند. این پاسخ می تواند محتویات HTML از صفحه ی وب یا یک تغییر مسیر، یا یک خطای 404، یا یک سند XML، یا حتی یک تصویر ... و یا هر چیز دیگری باشد.

به طور رسمی تر، یک تابع view جنگو باید

نکته ی کلیدی جهت برگرداندن محتوای غیر HTML ای از یک view درون کلاس HttpResponse قرار دارد، به ویژه آرگومان mimetype. با قرار دادن mimetype ، می توان به مرورگر نشان داد که یک پاسخ از قالب بندی متفاوت را بر مر گردانیم.

برای مثال، اجازه دهید به view زیر که یک تصویر با قالب بندی PNG را بر می گرداند را بررسی کنیم، تنها فایل را از حافظه خوانده ایم:

from django.http import HttpResponse def my_image(request): image_data = open("/path/to/my/image.png", "rb").read() return HttpResponse(image_data, mimetype="image/png")

همین! در صورتی که شما مسیر تصویر را در فراخوانی open() با یک مسیر برای یک تصویر واقعی جا به جا کنید، می توانید از این view به سادگی برای نمایش یک تصویر استفاده کنید، و مرورگر به درستی آن را نمایش خواهد داد.

نکته ی مهم دیگر که باید در نظر داشت این است که، شیء های HttpResponse با API استاندارد پایتون یعنی "file like object" کار می کنند. این بدین معناست که می توان، از یک نمونه ی HttpResponse را در هر جای پایتون (یا یک کتابخانه ی third-party) که انتظار یک فایل را دارد استفاده کنید.

برای مثالی از نحوه ی کارکرد آن، اجازه دهید نگاهی به تولید CSV با جنگو بیاندازیم.

تولید CSV

CSV یک قالب بندی ساده می باشد که معمولا توسط نرم افزار spreadsheet استفاده می شود. اساسا یک سری از ردیف های جدول با هر سلول در ردیف جدا شده توسط یک علامت کاما می باشد (CVS مخفف comma‑seperated values می باشد). برای مثال، در زیر برخی داده های "unruly" مسافران هوایی در قالب بندی CSV می باشد.

Year,Unruly Airline Passengers 1995,146 1996,184 1997,235 1998,200 1999,226 2000,251 2001,299 2002,273 2003,281 2004,304 2005,203 2006,134 2007,147

هر چند CSV ساده به نظر می رسد، قالب بندی جزئیات آن دارای توافق جهانی نمی باشد. قسمت های مختلف نرم افزار CVS های مختلفی را تولید و استفاده می کند. خوشبختانه، پایتون دارای یک کتابخانه ی استاندار CSV با نام cvs می باشد.

به دلیل آنکه ماژول csv به صورت file-like objects کار می کند، استفاده از آن ساده تر از HttpResponse می باشد:

import csv from django.http import HttpResponse # Number of unruly passengers each year 1995 - 2005. In a real application # this would likely come from a database or some other back-end data store. UNRULY_PASSENGERS = [146,184,235,200,226,251,299,273,281,304,203] def unruly_passengers_csv(request): # Create the HttpResponse object with the appropriate CSV header. response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = 'attachment; filename=unruly.csv' # Create the CSV writer using the HttpResponse as the "file." writer = csv.writer(response) writer.writerow(['Year', 'Unruly Airline Passengers']) for (year, num) in zip(range(1995, 2006), UNRULY_PASSENGERS): writer.writerow([year, num]) return response

کد فوق باید بسیار واضح باشد، ولی یک نکاتی ویژه برای ذکر کردن وجود دارد:

این الگوی کلی ای می باشد که شما در هر زمان که نیاز به برگرداندن محتوای غیر HTML ای دارید از آن استفاده خواهید کرد: ساختن یک شیء HttpResponse (با یک mimetype ویژه)، ارسال کردن آن به چیزی که انتظار یک فایل را دارد، و سپس برگرداند یک response.

اجازه دهید به نگاهی تعداد بیشتری از مثال بیاندازیم.

ساختن PDF

Portable Document Format (PDF) یک قالب بندی توسعه یافته توسط Adobe می باشد که برای نمایش اسناد قابل چاپ استفاده می شود، قالب بندی pixel-perfect کامل، فونت های جاسازی شده، و گرافیک دو بعدی. می توان یک PDF را معادل دیجیتال یک سند چاپ شده دانست؛ در واقع، PDF ها اغلب در توزیع اسناد به قصد چاپ آن ها استفاده می شود.

می توان به سادگی PDF ها را با پایتون و جنگو، با تشکر از کتابخانه ی عالی منبع باز ReportLab تولید کرد (htt://www.reportlab.org/rl_toolkit.html). مزیت تولید فایل های PDF به طور پویا این است که، می توانید PDF های سفارشی را برای اهداف مختلف ایجاد کنید.

در دست ترجمه/تالیف ...

نصب ReportLab

قبل از تولید PDF نیاز می باشد ReportLab را نصب کنید که معمولا خیلی ساده می باشد: تنها کافیست کتابخانه ی آن را از http://www.reportlab.org/downloads.html دانلود و نصب کنید.

راهنمای کاربر (به طور طبیعی تنها به صورت یک فایل PDF در دسترس می باشد) در http://www.reportlab.org/rsrc/userguide.pdf دارای دستور العمل اضافه می باشد.

می توان نصب بودن ReportLab را با import کردن آن در interactive interpreter پایتون آزمایش کرد:

>>> import reportlab

در صورتیکه دستور فوق هیچ خطایی را ایجاد نکند، نصب درست انجام شده است.

نوشتن view

همانند CSV، تولید PDF ها به صورت پویا با جنگو ساده می باشد، چرا که API مخصوص ReportLab به صورت file‑like object عمل می کند.

در زیر مثال "Hello World" را مشاهده می کنید:

from reportlab.pdfgen import canvas from django.http import HttpResponse def hello_pdf(request): # Create the HttpResponse object with the appropriate PDF headers. response = HttpResponse(mimetype='application/pdf') response['Content-Disposition'] = 'attachment; filename=hello.pdf' # Create the PDF object, using the response object as its "file." p = canvas.Canvas(response) # Draw things on the PDF. Here's where the PDF generation happens. # See the ReportLab documentation for the full list of functionality. p.drawString(100, 100, "Hello world.") # Close the PDF object cleanly, and we're done. p.showPage() p.save() return response

نکاتی در مورد کد فوق:

PDF های پیچیده

در صورتی که یک سند پیچیده ی PDF (یا هر قطعه داده ی بزرگ) را ایجاد می کنید، استفاده کردن از کتابخانه ی cStringIO به صورت یک محل نگهداری موقت برای فایل PDF خودتان را بررسی کنید. کتابخانه ی cStringIO یک رابط file-like object را تهیه می کند که برای حداکثر بهره وری در C نوشته شده است.

در زیر مثال "Hello World" قبلی با استفاده از cStringIO باز نویسی شده است:

from cStringIO import StringIO from reportlab.pdfgen import canvas from django.http import HttpResponse def hello_pdf(request): # Create the HttpResponse object with the appropriate PDF headers. response = HttpResponse(mimetype='application/pdf') response['Content-Disposition'] = 'attachment; filename=hello.pdf' temp = StringIO() # Create the PDF object, using the StringIO object as its "file." p = canvas.Canvas(temp) # Draw things on the PDF. Here's where the PDF generation happens. # See the ReportLab documentation for the full list of functionality. p.drawString(100, 100, "Hello world.") # Close the PDF object cleanly. p.showPage() p.save() # Get the value of the StringIO buffer and write it to the response. response.write(temp.getvalue()) return response

امکانات دیگر

مجموعه ی کاملی از انواع دیگر محتویاتی که می توان در پایتون تولید کرد وجود دارد. در دست ترجمه/تالیف ...:

به طور کلی، هر کتابخانه ی پایتون قابل ایجاد درون یک فایل می تواند درون جنگو استفاده شود. امکانات عظیم می باشند.

اکنون که با قواعد اولیهه ی تولید محتوای غیر HTML ای، آشنا شدیم، اجازه دهید تصورمان را یک درجه افزایش دهیم. جنگو تعداد ابزار بسیار جذاب برای تولید انواع رایج محتوای غیر HTML ای ارائه می دهد.

فریم ورک یا چارچوب Syndication Feed

جنگو یک فریم ورک یا چارچوب سطح بالا syndication-feed-generating را ارائه می کند که ایجاد RSS و Atom را ساده می کند.

برای ایجاد هر syndication feed، همه باید یک کلاس کوچک پایتون بنویسند. می توانید هر مقدار "feed" که می خواهید بسازید.

فریم ورک یا چارچوب سطح بالای feed-generating یک view می باشد که به طور قرارداد به /feeds/ وصل شده است. جنگو از باقی مانده ی URL (هر چیزی بعد از /feeds/) برای تعیین feed برای برگرداندن استفاده می کند.

برای ایجاد یک feed، شما یک Feed Class خواهید نوشت و در URLconf خود به آن اشاره می کنید.

مقدار دهی اولیه

برای فعال کردن syndication feed ها روی سایت جنگوی خود، URLconf زیر را اضافه کنید:

(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds} ),

این خط به جنگو می گوید؛ از فریم ورک RSS جهت کنترل تمام URL هایی که با "feeds/" شروع می شوند استفاده کند. (می توانید پیشوند "feeds/" را برای متناسب ساختن با نیازهای خودتان تغییر دهید.)

این خط URLconf دارای یک آرگومان اضافی می باشد: {'feed_dict': feeds}. از این آرگومان اضافه جهت ارسال feed هایی که باید تحت URL منتشر شده باشند استفاده کنید.

به طور خاص، feed_dict باید یک دیکشنری باشد که نام URL را به کلاس Feed مرتبط می کند. می توانید feed_dict را درون خود URLconf تعریف کنید. در زیر مثال کامل URLconf را ملاحظه می کنید:

from django.conf.urls.defaults import * from mysite.feeds import LatestEntries, LatestEntriesByCategory feeds = { 'latest': LatestEntries, 'categories': LatestEntriesByCategory, } urlpatterns = patterns('', # ... (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}), # ... )

مثال قبلی دو feed را در نظر گرفته است:

زمان راه اندازی، نیاز خواهید داشت خود کلاس های Feed را تعریف کنید.

یک کلاس Feed یک کلاس ساده ی پایتون می باشد که یک syndication feed را نشان می دهد. یک feed می تواند ساده باشد (مانند یک feed "سایت اخبار"، یا یک feed اولیه که آخرین ورودی های یک بلاگ را نمایش می دهد) یا بسیار پیچیده (مانند یک feed که تمام ورودی های بلاگ در یک طبقه بندی خاص جایی که طبقه بندی متغیر می باشد نمایش می دهد).

کلاس های Feed باید از کلاس django.contrib.syndication.feeds.Feed مشتق شوند. آن ها می توانند در هر جایی از درخت کد شما قرار بگیرند.

یک Feed ساده

مثال ساده ی زیر یک Feed از پنج ورودی آخر برای بلاگ داده شده را توضیح می دهد:

from django.contrib.syndication.feeds import Feed from mysite.blog.models import Entry class LatestEntries(Feed): title = "My Blog" link = "/archive/" description = "The latest news about stuff." def items(self): return Entry.objects.order_by('-pub_date')[:5]

نکات قابل توجه در کد فوق از این قرار می باشند:

تنها یک گام بیشتر وجود دارد. در یک RSS feed، هر <item> دارای یک <title>، <link> و <description> می باشد. نیاز است داده ای که قرار است برای درون آن المنت ها قرار گیرد، به فریم ورک گفته شود.

یک Feed پیچیده تر

فریم ورک همچنین feed های پیچیده تر را نیز از طریق پارامترها پشتیبانی می کند.

برای مثال، تصور کنید بلاگ شما یک RSS feed برای هر تگ مجزایی که شما برای طبقه بندی ورودی های خودتان استفاده کرده اید ارائه می کند. ساختن یک کلاس Feed جدا برای هر تگ احمقانه می باشد؛ نقض قانون "Don't Repeat Yourself" (DRY) می باشد.

در عوض، چارچوب syndication به شما اجازه می دهد feed های جنریکی ایجاد کنید که آیتم های متکی بر اطلاعات در آدرس feed ها را گردانند.

feed های تعیین تگ شما می تواند مانند زیر URL ها را استفاده کنند:

slug در اینجا "tags" می باشد. فریم ورک syndication، bit های URL اضافه ی بعد از slug را می بیند – 'python' و 'cats' – و به شما جهت گفتن معنی آن bit های URL و نحوه ی تاثیر آن ها در دست ترجمه/تالیف ...

یک مثال این موضوع را واضح تر می کند. در کد زیر feed های تگ تعیین را ملاحظه می کنید:

from django.core.exceptions import ObjectDoesNotExist from mysite.blog.models import Entry, Tag class TagFeed(Feed): def get_object(self, bits): # In case of "/feeds/tags/cats/dogs/mice/", or other such # clutter, check that bits has only one member. if len(bits) != 1: raise ObjectDoesNotExist return Tag.objects.get(tag=bits[0]) def title(self, obj): return "My Blog: Entries tagged with %s" % obj.tag def link(self, obj): return obj.get_absolute_url() def description(self, obj): return "Entries tagged with %s" % obj.tag def items(self, obj): entries = Entry.objects.filter(tags__id__exact=obj.id) return entries.order_by('-pub_date')[:30]

در کد فوق اصل اولیه ی الگوریتم فریم ورک RSS وجود دارد، به توجه به این کلاس و یک درخواست برای URL مورد نظر یعنی /feeds/tags/python/:

  1. فریم ورک آدرس /feeds/tags/python/ را دریافت می کند و ملاحظه می کند که یک تکه ی اضافی از URL بعد از slug وجود دارد. فریم ورک رشته ی باقی مانده را از توسط حرف ("/") جدا کرده و متد کلاس Feed یعنی get_object را فراخوانی کرده و bit ها را به آن ارسال می کند.

    در این مورد، bits مورد نظر ['python'] می باشد. برای یک درخواست به /feeds/tags/python/django/، bit ها ['python', 'django'] می باشند.

  2. get_object() مسئول بازیابی شیء Tag داده شده از bit های داده شده می باشد.

    در این مورد، get_object() برای بازیابی Tag از API پایگاده داده ی جنگو استفاده می کند. توجه داشته باشید که get_object() در صورتیکه پارامتر های غیر معتبر داده شود، باید خطای django.core.exceptions.ObjectDoesNotExist ایجاد کند. هیچ try/except ای در اطراف فراخوانی Tag.DoesNotExist وجود ندارد، زیرا این کار ضروری نمی باشد. آن تابع زمان شکست Tag.DoesNotExist ایجاد می کند، و Tag.DoesNotexist از OjbectDoesNotexist مشتق شده است. بروز objectDoesNotexist در get_object()تولید یک خطای 404 برای آن درخواست را به جنگو می گوید.

  3. برای تولید <title>، <link> و <description> مربوط به feed، جنگو متدهای title()، link() و Description() را مورد استفاده قرار می دهد. در مثال قبلی، آن ها attribute های ساده ی کلاس رشته بودند، ولی این مثال نشان می دهد که، آن ها می تواند هم رشته و هم متد باشند. برای هر title، link و description، جنگو الگوریتم زیر را دنبال می کند:
    1. 1. سعی می کند یک متد را فراخوانی کند، ارسال آرگومان obj، جایی که obj شیءی می باشد که توسط get_object() بر گردانده شده است.
    2. در صورت شکست، جنگو تلاش می کند یک متد با هیچ آرگومانی را فراخوانی کند.
    3. در صورت شکست، جنگو attribute کلاس را استفاده می کند.
  4. در پایان، توجه داشته باشید که items() در این مثال همچنین آرگومان obj را نیز دریافت می کند. الگوریتم برای items همانند الگوریتم توضیح داده شده در گام قبلی می باشد – ابتدا، سعی می کند items(obj)، سپس items() و در پایان یک attribute کلاس items (که باید یک لیست باشد).

مستندات کامل از تمام متدها و attribute ها از کلاس های Feed همواره از اسناد رسمی جنگو قابل دسترسی می باشد (http://docs.djangoproject.com/en/dev/ref/contrib/syndication)

تعیین نوع Feed

به طور پیشفرض، فریم ورک syndication، RSS 2.0 را تهیه می کند. برای تغییر آن، یک attribute، feed_type برای کلاس Feed خودتان اضافه کنید:

from django.utils.feedgenerator import Atom1Feed class MyFeed(Feed): feed_type = Atom1Feed

توجه داشته باشید که feed_type را برای یک شیء کلاس در نظر گرفته اید، نه یک نمونه، در حال حاضر انواع feed های در دسترس در جدول 1-11 نشان داده شده اند.

جدول

جدول ۱-۱۳

کلاس Feed Format
Django.utils.feedgenerator.Rss201rev2Feed RSS 2.01 (default)
Django.utils.feedgenerator.RssUserland091Feed RSS 0.91
Django.utils.feedgenerator.Atom1Feed Atom 1.0

Enclosures

برای تعیین enclosure ها (مانند منابع media مرتبط با یک آیتم feed مانند feed های MP3 podcast)، item_enclosure_url، item_enclosure_length و item_enclosure_mime_type را استفاده کنید، به عنوان مثال:

from myproject.models import Song class MyFeedWithEnclosures(Feed): title = "Example feed with enclosures" link = "/feeds/example-with-enclosures/" def items(self): return Song.objects.all()[:30] def item_enclosure_url(self, item): return item.song_url def item_enclosure_length(self, item): return item.song_length item_enclosure_mime_type = "audio/mpeg"

البته که شما یک شیء Song با فیلدهای song_url و song_length (مانند اندازه ی بایت ها) ساخته اید.

Language

Feed های ساخته شده توسط فریم ورک syndication به طور خودکار شامل تگ مناسب <language> (RSS 2.0) یا attribute، xml:lang (Atom) می باشند. این به طور مستقیم از تنظیم LANGUAGE_CODE آمده است.

URLs

لینک متد/attribute می تواند هم یک URL مستقل (مانند "/blog/") یا یک URL با آدرس کامل دامنه و پروتکل (مانند "http://www.example.com/blog/") باشد. در صورتی که link دامنه را بر نگرداند، فریم ورک syndication دامنه ی سایت فعلی را به همراه تنظیم SITE_ID درج خواهد کرد. (برای اطلاعات بیشتر در مورد SITE_ID و چارچوب سایت ها به پکیج django.contrib مراجعه کنید.)

feed های Atom نیازمند یک <link rel="self"> می باشند که مکان فعلی feed را تعریف کند. فریم ورک syndication به طور خودکار این را قرار می دهد.

انتشار feed های Atom و RSS پشت سر هم

برخی از توسعه دهندگان تمایل دارند، فیلد های هر دو نسخه ی Atom و RSS در دسترس قرار دهند. انجام این کار با جنگو بسیار آسان می باشد: تنها کافیست یک کلاس فرزند از کلاس feed خود ایجاد کرده و feed_type را برای چیزی متفاوت قرار دهید. سپس URLconf خود را جهت اضافه کردن نسخه های اضافه به روز رسانی کنید. در زیر یک مثال کامل را ملاحظه می کنید:

from django.contrib.syndication.feeds import Feed from django.utils.feedgenerator import Atom1Feed from mysite.blog.models import Entry class RssLatestEntries(Feed): title = "My Blog" link = "/archive/" description = "The latest news about stuff." def items(self): return Entry.objects.order_by('-pub_date')[:5] class AtomLatestEntries(RssLatestEntries): feed_type = Atom1Feed

و در زیر URL همراه:

from django.conf.urls.defaults import * from myproject.feeds import RssLatestEntries, AtomLatestEntries feeds = { 'rss': RssLatestEntries, 'atom': AtomLatestEntries, } urlpatterns = patterns('', # ... (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}), # ... )

فریم ورک یا چارچوب نقشه ی سایت

نقشه ی سایت یک فایل XML در وب سایت شما می باشد که به indexer های موتور جستجو نحوه ی تغییر مکرر و نحوه ی ارتباط برخی صفحات مهم با دیگر صفحات سایت شما را می گوید. این اطلاعات به موتورهای جستجوی فهرست سایت شما کمک می کند.

به عنوان مثال، در زیر یک تکه از نقشه ی سایت برای وب سایت جنگو وجود دارد (http://www.djangoproject.com/sitemap.xml):

<?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>http://www.djangoproject.com/documentation/</loc> <changefreq>weekly</changefreq> <priority>0.5</priority> </url> <url> <loc>http://www.djangoproject.com/documentation/0_90/</loc> <changefreq>never</changefreq> <priority>0.1</priority> </url> ... </urlset>

برای مشاهده ی نقشه ی سایت های بیشتر به http://www.sitemaps.org/ مراجعه کنید.

فریم ورک نقشه ی سایت جنگو، ساختن این فایل XML را با اجازه دادن به شما جهت بیان این اطلاعات در کد پایتون خودکار می کند. جهت ساختن یک نقشه ی سایت، تنها نیاز به نوشتن یک کلاس Sitemap و اشاره ی به آن درون URLconf می باشد.

نصب

جهت نصب برنامه ی نقشه ی سایت، مراحل زیر را دنبال کنید:

  1. 'django.contrib.sitemaps' را به تنظیم INSTALLED_APPS اضافه کنید.
  2. 'django.template.loaders.app_directories.load_template_source'باید در تنظیم TEMPLATE_LOADERS وجود داشته باشد. این حالت به طور پیشفرض وجود دارد، بنابراین در صورتی که این تنظیم را تغییر داده اید، تنها کافیست آن را به حالت اول خود بر گردانید.
  3. اطمینان حاصل کنید که سایت های چارچوب را نصب کرده اید (به پکیج django.contrib مراجعه کنید).

مقدار دهی اولیه

جهت فعال کردن تولید نقشه ی سایت در سایت جنگو، خط زیر را درون URLconf اضافه کنید:

(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})

خط فوق برای ساختن یک نقشه ی سایت هنگامی که یک کلاینت به /sitemap.xml دسترسی پیدا می کند در نظر گرفته شده است. توجه داشته باشید که حرف نقطه در sitemap.xml با یک علامت ("\") میسر شده است، زیرا نقطه ها معنی خاصی در regular expression ها دارند.

نام فایل نقشه ی سایت اهمیتی ندارد، ولی مکان آن مهم می باشد. موتورهای جستجو تنها لینک ها را در نقشه ی سایت شما برای سطح URL فعلی و پایین فهرست می کنند. برای مثال، در صورتی که sitemap.xml در دایرکتوری ریشه ی شما می باشد، ممکن است به هر URL ای در سایت شما رجوع کند. در صورتی که نقشه ی سایت در /content/sitemap.xml باشد، ممکن است تنها به URL هایی که با /content/ شروع می شوند رجوع کند.

view نقشه ی سایت یک آرگومان اضافه ی الزامی دریافت می کند: {'sitemaps': sitemaps}. نقشه های سایت باید یک دیکشنری باشند که بخش کوتاه لیبلی (مانند blog یا news) را به کلاس Sitemap آن (مانند BlogSitemap یا NewsSitemap) مرتبط می سازد. همچنین ممکن است به یک instance از یک کلاس Sitemap (مانند BlogSitemap(some_var)) مرتبط سازد.

کلاس های Sitemap

یک کلاس Sitemap یک کلاس ساده ی پایتون می باشد که یک بخش از ورودی های نقشه ی سایت شما را نشان می دهد. برای مثال، یک کلاس Sitemap هنگامی که دیگری می تواند تمام رخدادها در در رخدادهای تقویم نشان دهد تمام ورودی های وبلاگ شما را نشان دهد.

در ساده ترین مورد، تمام این بخش ها با یکدیگر داخل یک sitemap.xml بدست می آیند، ولی استفاده از فریم ورک برای تولید یک فهرست نقشه ی سایت که به فایل های نقشه ی سایت منحصر به فرد نیز ممکن است، یکی برا هر بخش.

کلاس های Sitemap باید از کلاس django.contrib.sitemaps.Sitemap مشتق شوند. آن ها می توانند هر جایی در درخت کد پایتون شما قرار بگیرند.

برای مثال، فرض می کنیم شما دارای یک سیستم بلاگ می باشید، با یک مدل Entry، و می خواهید نقشه ی سایت تمام لینک ها به ورودی منحصر به فرد بلاگ را شامل شود. در زیر کلاس Sitemap مورد نظر وجود دارد:

from django.contrib.sitemaps import Sitemap from mysite.blog.models import Entry class BlogSitemap(Sitemap): changefreq = "never" priority = 0.5 def items(self): return Entry.objects.filter(is_draft=False) def lastmod(self, obj): return obj.pub_date

declare کردن نقشه ی سایت باید بسیار شبیه به یک Feed باشد. در دست ترجمه/تالیف ...

همانند کلاس های Feed، اعضای Sitemap می توانند متد یا attribute ها باشند. به بخش کمی قبل در این آموزش از کتاب، "یک مثال پیچیده" برای نحوه ی انجام این اعمال مراجعه کنید.

یک کلاس نقشه ی سایت می تواند متد/attribute های زیر را تعریف کند:

میانبرها

فریم ورک نقشه ی سایت کلاس های مناسبی برای موارد مشترک تهیه کرده است. این کلاس ها در بخش های زیر توضیح داده شده اند.

FlatPageSitemap

کلاس django.contrib.sitemaps.FlatPageSitemap به تمام صفحات مسطح تعریف شده برای سایت فعلی نگاه می کند و یک ورودی در نقشه ی سایت ایجاد می کند. این ورودی ها تنها شامل attribute مورد نظر یعنی location می شوند – نه lastmod، changefreq یا priority.

برای اطلاعات بیشتر در مورد صفحات مسطخ به پکیج django.contrib مراجعه کنید.

GenericSitemap

کلاس GenericSitemap با هر view جنریکی کار می کند (به view های generic مراجعه کنید) که شما آن ها را فرا گرفته اید.

برای استفاده از آن، یک نمونه بسازید، ارسال در info_dict یکسان که شما به view های جنریک ارسال می کنید. تنها نیازمندی این است که دیکشنری یک ورودی queryset داشته باشد. ممکن است همچنین یک ورودی date_field داشته باشد که یک فیلد تاریخ برای شیء های بازیابی شده از queryset را تعیین می کند. این برای attribute، lastmode در نقشه ی سایت تولید شده مورد استفاده قرار خواهد گرفت. شما ممکن است آرگومان های کیورد priority و changefreq را برای سازنده ی GenericSitemap جهت تعیین این attribute ها برای همه ی URL ها ارسال کنید.

در زیر مثالی از یک URLconf که از هر دوی FlatPageSitemap و GenericSiteMap (با شیء فرضی Entry از پیش) استفاده می کند وجود دارد:

from django.conf.urls.defaults import * from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap from mysite.blog.models import Entry info_dict = { 'queryset': Entry.objects.all(), 'date_field': 'pub_date', } sitemaps = { 'flatpages': FlatPageSitemap, 'blog': GenericSitemap(info_dict, priority=0.6), } urlpatterns = patterns('', # some generic view using info_dict # ... # the sitemap (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) )

ساخت فهرست نقشه ی سایت

فریم ورک نقشه ی سایت همچنین دارای توانایی برای ساختن یک فهرست نقشه ی سایت می باشد که به فایل های منحصر به فرد نقشه ی سایت رجوع می کند، یکی برای هر بخش تعریف شده در دیکشنری sitemaps. تنها تفاوت ها در کاربرد هستند:

در زیر خطوط URLconf مربوط برای مثال قبلی وجود دارد:

(r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}), (r'^sitemap-(?P<section>. ).xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})

کد فوق به طور اتوماتیک یک فایل sitemap.xml تولید می کند که به هر دوی sitemap-flatpages.cml و sitemap-blog.xml رجوع می کند. کلاس های Sitemap و دیکشنری sitemaps هیچگاه تغییر نمی کنند.

پینگ کردن گوگل

ممکن است بخواهید گوگل را هنگامی که نقشه ی سایت شما تغییر می کند پینگ کنید، تا به آن اجازه دهید دوباره فهرست گذاری سایت شما را بداند. چارچوب یک تابع تنها برای فقط برای این کار تهیه کرده است: django.contrib.sitemaps.ping_google().

ping_google() یک آرگومان اختیاری دریافت می کند، sitemap_url، که باید URL مستقل از نقشه ی سایت سایت شما باشد (مانند '/sitemap.xml'). در صورتی که آرگومان تهیه نشده باشد، ping_google() تلاش می کند نقشه ی سایت شما را توسط انجام یک جستجوی بر عکس در URLconf بسنجد.

ping_google() در صورتی که نتواند URL نقشه ی سایت را تعیین کند، خطای django.contrib.sitemaps.SitemapNotFound را ایجاد خواهد کرد.

روش مفید برای فراخوانی ping_google به شکل یک متد save() مدل می باشد:

from django.contrib.sitemaps import ping_google class Entry(models.Model): # ... def save(self, *args, **kwargs): super(Entry, self).save(*args, **kwargs) try: ping_google() except Exception: # Bare 'except' because we could get a variety # of HTTP-related exceptions. pass

راهکار موثر تر، فراخوانی ping_google() از یک اسکریپت cron یا برخی وظایف برنامه ریزی شده ی دیگر می باشد. تابع یک HTTP request برای سرور های گوگل ایجاد می کند، بنابراین شما ممکن نیست بخواهید برای معرفی در هر بار فراخوانی save() بار اضافه ی شبکه را داشته باشید.

در پایان، در صورتی که 'django.contrib.sitemaps' درون تنظیم INSTALLED_APPS می باشد، manage.py شما شامل یک دستور جدید، ping_google خواهد بود. این برای دسترسی به پینگ کردن درون خط فرمان مفید می باشد. برای مثال:

python manage.py ping_google /sitemap.xml