oruji.github.io
oruji.github.ioPersian Tutorials
ویرایش: 1396/11/13 19:20
A A

آموزش پکیج django.contrib در جنگو (Django)

یکی از نقاط قدرت پایتون فلسفه ی "batteries included" پایتون می باشد: هنگامی که پایتون را نصب می کنید، پایتون درون خود دارای یک کتابخانه بزرگ از پکیج هایی می باشد که می توان بلافاصله از آن ها استفاده کرد می باشد، بدون نیاز به دانلود هیچ چیز دیگری. جنگو سعی می کند این فلسفه را دنبال کند، و حاوی کتابخانه ی استاندارد خودش می باشد از add-on های مفید برای وظایف مشترک توسعه ی وب می باشد. این آموزش از کتاب، مجموعه ای از این add-on ها را پوشش می دهد.

کتابخانه ی استاندارد جنگو

کتابخانه ی استاندارد جنگو، درون پکیج django.contrib قرار گرفته است. درون هر ساب پکیج یک قسمت جدا از عملکرد add-on می باشد. این قسمت ها لزوما وابسته نمی باشند، ولی برخی ساب پکیج های django.contrib نیازمند دیگر پکیج ها می باشند.

هیچ نیازمندی سختی برای انواع عمکردها در django.contrib وجود ندارد. برخی از پکیج ها شامل ماژول هایی می باشند (و از این رو نیازمند نصب جداول پایگاه داده ی آن ها درون پایگاه داده ی شما می باشد.)، ولی بقیه تنها عبارتند از middleware یا تگ های template.

تنها مشخصه ی مشترکی بین پکیج های django.contrib وجود دارد این است: در صورتی که پکیج django.contrib را به کلی حذف کنید، شما همچنان می توانید از خصوصیات اساسی جنگو بدون هیچ مشکلی استفاده کنید. هنگامی که توسعه دهندگان جنگو عملکرد جدیدی را به فریم ورک یا چارچوب اضافه می کنند، آن ها از این قانون تجربی در تصمیم اینکه آیا عمکرد جدید باید درون django.contrib باشد یا جای دیگری استفاده می کند.

django.contrib عبارت است از این پکیج ها:

باقی مانده ی این آموزش از کتاب، به جزئیات تعدادی از پکیج های django.contrib خواهد پرداخت که تاکنون درباره ی آن ها در این کتاب بحث نشده است.

Sites

سیستم sites جنگو یک فریم ورک یا چارچوب جنریک می باشد که به شما اجازه می دهد چندین وب سایت را با پایگاه داده و پروژه ی جنگوی همسان اداره کنید. این یک مفهوم تصوری می باشد، و (در دست ترجمه ...)، بنابراین با چند سناریو شروع می کنیم که این مفهوم می تواند در آنجا مفید باشد.

سناریو 1: استفاده ی دوباره از داده در سایت های چندگانه

همانطور که در مقدمه توضیح داده شد، سایت های LJWorld.com و Lawrence.com ساخته شده با جنگو توسط سازمان اخبار یکسان اداره شده است: روزنامه ی Lawrence Journal-World در Lawrence، Kansas. LJWorld.com بر روی اخبار تمرکز می کند، در حالی که Lawrence.com بر روی سرگرمی های محلی. ولی اغلب مقاله نویسان می خواهند یک مقاله را بر روی هر دو سایت منتشر کنند.

روش احمقانه برای حل مشکل، استفاده از پایگاه داده ی جدا برای هر سایت و نیاز داشتن تولید کنندگان سایت جهت دو مرتبه انتشار یک داستان همسان: یک مرتبه برای LJWorld.com و دوباره یک بار دیگر برای Lawrence.com. ولی این حرکت برای تولید کنندگان سایت نا کارآمد می باشد، و ذخیره ی چندین کپی از یک داستان در پایگاه داده کاری زائد و افزونه می باشد.

راهکار بهتر؟ هر دو سایت از یک پایگاه داده ی استفاده کنند، و یک مقاله از طریق یک رابطه ی چند به چند با یک یا چند سایت مشترک باشد. فریم ورک یا چارچوب sites جنگو جدول پایگاه داده ای برای آن دسته از مقالاتی که می توانند مرتبط باشند ارائه می کند. این یک قلاب برای پیوستن داده با یک یا بیشتر سایت ها می باشد.

سناریو 2: ذخیره ی نام/دامنه ی سایت شما در یک مکان

LJWorld.com و Lawrence.com هر دو دارای قابلیت هشدار پست الکترونیک می باشند، که به خوانندگان اجازه می دهد جهت دست یابی به اطلاعات در هنگام بروز اخبار عضو شوند. این بسیار اساسی است: یک خواننده در یک وب عضو می شود، و بلا فاصله یک پست الکترونیک با پیام "Thanks for you subscription" در یافت می کند.

اجرا شدن این پروسه ی عضویت به صورت دو مرتبه کد زدن یکسان نا کارآمد و زائد می باشد، بنابراین سایت ها از در پشت صحنه از یک کد همسان استفاده می کنند. ولی پیام "Thanks you for your subscription" برای هر سایت باید متفاوت باشد. با استفاده از شیء های Site، می توان پیام thank-you را با استفاده از مقادیر نام سایت فعلی (مانند 'LJWorld.com') و نام دامنه (مانند 'www.ljworld.com') جدا کرد.

فریم ورک sites جنگو مکانی برای شما جهت ذخیره name و domain برای هر سایت در پروژه ی جنگو ارائه می کند، که بدین معنی است که می توانید از مقدایر در یک روش جنریک دوباره استفاده کرد.

نحوه ی استفاده از فریم ورک یا چارچوب Sites

فریم ورک sites بیشتر یک سری از قرارداد ها می باشد تا یک چارچوب. همه چیز بر اساس دو مفهوم ساده می باشد:

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

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

  1. 'django.contrib.sites' را به تنظیم INSTALLD_APPS اضافه کنید.
  2. دستور manage.py syncdb را جهت نصب جدول django_site داخل پایگاه داده ی خود اجرا کنید. همچنین این یک شیء site پیشفرض، با دامنه ی example.com ایجاد می کند.
  3. سایت example.com را به دامنه ی خودتان تغییر داده، و هر شیء Site دیگری را اضافه کنید، هم از طریق سایت مدیر جنگو یا از طریق API پایتون. یک شیء Site برای هر سایت/دامنه ای که این پروژه ی جنگو ایجاد کرده بسازید.
  4. تنظیم SITE_ID در هر یک از فایل های تنظیم خودتان تعریف کنید. این مقدار باید ID پایگاه داده برای شیء Site، جهت سایت ایجاد شده توسط آن فایل تنظیمات باشد.

قابلیت های فریم ورک یا چارچوب Sites

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

استفاده ی دوباره از داده در چندین سایت

جهت استفاده ی دوباره از داده در چندین سایت، همانطور که در سناریو 1 توضیح داده شد، تنها کافیست یک ManyToManyField برای Site در مدل های خود ایجاد کنید، برای مثال:

from django.db import models from django.contrib.sites.models import Site class Article(models.Model): headline = models.CharField(max_length=200) # ... sites = models.ManyToManyField(Site)

این زیر ساختی است که برای مربوط ساختن مقالات با چندین سایت در پایگاه داده نیاز می باشد. با قرار گرفتن آن، می توان از کد view جنگوی همسان برای چندین سایت دوباره استفاده کرد. مثال مدل Article زیر، view مورد نظر یعنی article_detail به شکل زیر خواهد بود:

from django.conf import settings from django.shortcuts import get_object_or_404 from mysite.articles.models import Article def article_detail(request, article_id): a = get_object_or_404(Article, id=article_id, sites__id=settings.SITE_ID) # ...

تابع view فوق قابل استفاده ی دوباره می باشد چرا که سایت مقاله را به صورت پویا بررسی می کند، بر حسب مقدار تنظیم SITE_ID.

برای مثال، تصور کنید فایل تنظیمات LJWorld.com دارای یک تنظیم SITE_ID با مقدار 1 می باشد، و فایل تنظیمات Lawrence.com دارای یک SITE_ID با مقدار 2 می باشد. در صورتی که این view زمانی که فایل تنظیمات LJWorld.com فعال است فراخوانی شده است، سپس (در دست ترجمه ...).

مربوط ساختن محتوی با یک سایت تنها

به طور همسان، می توان یک مدل را در یک رابطه ی چند به یک با استفاده از ForeignKey به مدل Site مرتبط کرد.

برای مثال، در صورتی که هر مقاله تنها با یک سایت تنها مرتبط باشد، می توانید از مدلی شبیه به مدل زیر استفاده کنید:

from django.db import models from django.contrib.sites.models import Site class Article(models.Model): headline = models.CharField(max_length=200) # ... site = models.ForeignKey(Site)

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

Hooking Into the Current Site from Views

در یک سطح پایین، می توان کارهای خاصی را بر اساس سایت با استفاده از فریم ورک sites در view های جنگو در view ای که فراخوانی شده است انجام داد، برای مثال:

from django.conf import settings def my_view(request): if settings.SITE_ID == 3: # Do something. else: # Do something else.

البته، قرار دادن ID های سایت مانند کد فوق کاری شلخته می باشد. روشی تمیزتر از انجام کاری یکسان برای بررسی دامنه ی سایت:

from django.conf import settings from django.contrib.sites.models import Site def my_view(request): current_site = Site.objects.get(id=settings.SITE_ID) if current_site.domain == 'foo.com': # Do something else: # Do something else.

روش بازیابی شیء Site برای مقدار settings.SITE_ID بسیار رایج می باشد، بنابراین مدیر مدل Site (Site.objects) دارای یک متد get_current() می باشد. مثال زیر برابر با مثال قبلی می باشد:

from django.contrib.sites.models import Site def my_view(request): current_site = Site.objects.get_current() if current_site.domain == 'foo.com': # Do something else: # Do something else.

بدست آوردن دامنه ی فعلی برای نمایش

برای یک رویکرد DRY (Don't Repeat Yourself)، حذف کد های تکراری، جهت ذخیره ی نام سایت و دامنه، همانطور که کمی قبل تر در "سناریو 2: ذخیره نام/دامنه سایت در یک مکان" توضیح داده شد، تنها کافیست به name و domain شیء Site فعلی مراجعه کنید. برای مثال:

from django.contrib.sites.models import Site from django.core.mail import send_mail def register_for_newsletter(request): # Check form values, etc., and subscribe the user. # ... current_site = Site.objects.get_current() send_mail('Thanks for subscribing to %s alerts' % current_site.name, 'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name, 'editor@%s' % current_site.domain, [user_email]) # ...

در ادامه مثال در حال پیشرفت LJWorld.com و Lawrence.com در Lawrence.com این آدرس پست الکترونیک دارای خط موضوع "Thanks for subscribing to Lawrence.com alerts" می باشد. در LJWorld.com، آدرس پست الکترونیکی دارای خط موضوع "Thanks … to LJworld.com alerts" می باشد. این رفتار همسان مختص سایت برای بدنه ی پیام آدرس پست الکترونیک بکار برده می شود.

یک روش حتی بیشتر انعطاف پذیر (ولی سنگین تر) برای انجام این استفاده از سیستم template جنگو می باشد. با فرض اینکه Lawrence.com و LJWorld.com دارای دایرکتوری های template متفاوت (TEMPLATE_DIRS)، می توان به سادگی به سیستم template محول کرد، مانند زیر:

from django.core.mail import send_mail from django.template import loader, Context def register_for_newsletter(request): # Check form values, etc., and subscribe the user. # ... subject = loader.get_template('alerts/subject.txt').render(Context({})) message = loader.get_template('alerts/message.txt').render(Context({})) send_mail(subject, message, 'do-not-reply@example.com', [user_email]) # ...

در این مورد، شما ملزم به ساخت template های subject.txt و message.txt در هر دو دایرکتوری template برای LJWorld.com و Lawrence.com می باشد. همانطور که قبلا ذکر شد، این روش منعطف تر از روش قبلی، ولی پیچیده تر نیز می باشد.

این ایده ی خوبی برای بکار بردن شیء های Site تا آنجا که ممکن است برای حذف پیچیدگی زائد و اضافه می باشد.

CurrentSiteManager

در صورتی که شیء ها نقش کلیدی را در برنامه ی شما ایفا می کنند، استفاده از CurrentSiteManager را در مدل های خود مورد ملاحظه قرار دهید. CurrentSiteMannager یک مدیر مدل (به آموزش مدل پیشرفته مراجعه کنید) است که به طور خودکار کوئری های خود را جهت بر داشتن تنها شیء های مرتبط شده با Site فعلی فیلتر می کند.

با اضافه کردن CurrentSiteManager به مدل خود از آن استفاده کنید. برای مثال:

from django.db import models from django.contrib.sites.models import Site from django.contrib.sites.managers import CurrentSiteManager class Photo(models.Model): photo = models.FileField(upload_to='/home/photos') photographer_name = models.CharField(max_length=100) pub_date = models.DateField() site = models.ForeignKey(Site) objects = models.Manager() on_site = CurrentSiteManager()

با مدل فوق، Photo.objects.all() تمام شیء های Photo را در پایگاه داده بر می گرداند. ولی Photo.on_site.all() تنها شیء های Photo مرتبط شده با سایت فعلی را بر می گرداند، بر حسب تنظیم SITE_ID.

به عبارت دیگر، دو عبارت زیر با یکدیگر برابر می باشند:

Photo.objects.filter(site=settings.SITE_ID) Photo.on_site.all()

چطور CurrentSiteManager می داند کدام فیلد از Photo، Site بوده است؟ به طور پیشفرض CurrentSiteMananger به دنبال یک فیلد با نام site می گردد. در صورتی که مدل شما دارای یک ForeignKey یا ManyToManyField فراخوانی شده ی چیزی به غیر از site باشد، نیاز خواهید داشت آن را به صورت پارامتر به CurrentSiteManager ارسال کنید. مدل زیر، که دارای یک فیلد با نام publish_on می باشد، این را توضیح می دهد:

from django.db import models from django.contrib.sites.models import Site from django.contrib.sites.managers import CurrentSiteManager class Photo(models.Model): photo = models.FileField(upload_to='/home/photos') photographer_name = models.CharField(max_length=100) pub_date = models.DateField() publish_on = models.ForeignKey(Site) objects = models.Manager() on_site = CurrentSiteManager('publish_on')

در صورتی که در تلاش برای استفاده از CurrentSiteManager و ارسال یک نام فیلدی که وجود ندارد می باشد، جنگو یک خطای ValueError ایجاد خواهد کرد.

طریقه ی استفاده ی جنگو از فریم ورک Sites

اگر چه استفاده از فریم ورک sites الزامی نمی باشد، استفاده از آن تشویق شده است، چرا که جنگو از آن در چند جا سود می برد. حتی اگر نصب جنگو شما تنها یک سایت را پشتیبانی کند، شما باید چند ثانیه برای ساختن شیء site با domain و name خودتان و اشاره به ID آن در تنظیم SITE_ID وقت صرف کنید.

در زیر نحوه ی استفاده ی جنگو از فریم ورک sites وجود دارد:

Flatpages

اغلب شما یک برنامه ی وب پایگاه داده محور خواهید داشت، ولی به تعدادی از صفحات استاتیک نیز نیاز خواهید داشت، از قبیل یک صفحه ی About یا یک صفحه ی Privacy Policy. این امکان وجود دارد که برای این نوع صفحات از وب سرور های استانداردی مانند Apache به صورت فایل های flat HTML استفاده کرد، اما این سطح اضافه ای از پیچیدگی درون برنامه ی شما ایجاد می کند، چرا که شما باید نسبت به تنظیم Apache نیز نگرانی هایی داشته باشید. باید برای تیم خود جهت ویرایش آن فایل ها دسترسی بر پا کنید، و همچنین نمی توانید از سیستم template جنگو برای طراحی این صفحات استفاده کنید.

راهکار برای این مشکل، برنامه ی flatpages جنگو می باشد، که در پکیج django.contrib.flatpages وجود دارد. این برنامه به شما اجازه می دهد صفحات استاتیک را از طریق سایت مدیر جنگو مدیریت کنید، همچنین این برنامه به شما اجازه می دهد template هایی برای آن ها با استفاده از سیستم template جنگو تعیین کنید، درست مثل بقیه ی داده های شما، و شما می توانید با API استاندارد پایگاه داده ی جنگو به flatpages دسترسی پیدا کنید.

(در دست ترجمه ...).

استفاده از Flatpages

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

  1. 'django.contrib.flatpages' را به تنظیم INSTALLED_APPS اضافه کنید. django.contrib.flatpages به django.contrib.sites وابسته است، بنابراین اطمینان حاصل کنید که هر دو پکیج درون INSTALLED_APPS وجود دارند.
  2. 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' را به تنظیم MIDDLEWARE_CLASSES اضافه کنید.
  3. جهت نصب دو جدول الزامی درون پایگاه داده ی خود دستور manage.py sycndb را اجرا کنید.

برنامه ی flatpages دو جدول درون پایگاه داده ی شما ایجاد می کند: django_flatpage و django_flatpage_sites. django_flatpage به سادگی یک URL را به عنوان و دسته ای از متن محتوا مرتبط می کند. django_flatpage_sites یک جدول چند به چند می باشد که یک flatpage را با یک یا بیشتر سایت ها مرتبط می سازد.

برنامه دارای یک تنها یک مدل FlatPage می باشد، که در django/contrib./flatpages/models.py تعریف شده است. که چیزی شبیه به کد زیر می باشد:

from django.db import models from django.contrib.sites.models import Site class FlatPage(models.Model): url = models.CharField(max_length=100, db_index=True) title = models.CharField(max_length=200) content = models.TextField(blank=True) enable_comments = models.BooleanField() template_name = models.CharField(max_length=70, blank=True) registration_required = models.BooleanField() sites = models.ManyToManyField(Site)

اجازه دهید فیلدهای فوق را مورد بررسی قرار دهیم:

می توان flatpages را از طریق رابط مدیر جنگو یا API پایگاه داده ی جنگو نیز ایجاد نمود. برای اطلاعات بیشتر در این مورد، بخش "اضافه کردن، تغییر دادن و حذف Flatpages" مشاهده کنید.

هنگامی که flatpages ساخته شد، FlatpageFallbackMiddleware تمام کار را انجام می دهد. هر بار که هر برنامه ی جنگو یک خطای 404 را ایجاد می کند، این middleware برای URL درخواست شده به صورت آخرین چاره middleware را بررسی می کند. به طور خاص، برای یک flatpage با URL داده شده یا یک ID سایت که با تنظیم SITE_ID مطابقت دارد بررسی می کند.

در صورتی که یک مطابق پدا کند، template مربوط به flatpage و یا در صورتی که flatpage دارای یک template سفارشی نباشد flatpages/default.html را بار گذاری می کند. این middleware آن template را تنها به یک متغیر context با نام flatpage ارسال می کند که شیء FlatPage می باشد، و در render کردن template از RequestContext استفاده می کند.

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

اضافه کردن، تغییر دادن و حذف Flatpages

می توان flatpages را به دو روش اضافه کرده، تغییر داده و یا حذف کرد:

از طریق رابط مدیر

در صورتی که رابط خودکار مدیر جنگو فعال کرده اید، باید به قسمت "Flatpages" در صفحه ی index مدیر مشاهده کنید. flatpages را به همانطور که هر شیء دیگری را در سیستم ویرایش می کند ویرایش کنید.

از طریق API پایتون

همانطور که قبلا ذکر شد، flatpages توسط یک مدل استاندارد جنگو که درون django/contrib./flatpages/models.py وجود دارد نشان داده می شود. از این رو، می توان به شیء های flatpage از طریق API پایگاه داده ی جنگو دسترسی پیدا کرد، برای مثال:

>>> from django.contrib.flatpages.models import FlatPage >>> from django.contrib.sites.models import Site >>> fp = FlatPage.objects.create( ... url='/about/', ... title='About', ... content='<p>About this site...</p>', ... enable_comments=False, ... template_name='', ... registration_required=False, ... ) >>> fp.sites.add(Site.objects.get(id=1)) >>> FlatPage.objects.get(url='/about/') <FlatPage: /about/ -- About>

استفاده از Template های Flatpage

به طور پیشفرض، flatpages توسط template، flatpages/default.html، render می شود، ولی می توان آن را برای یک flatpage خاص، با فیلد template_name در شیء FlatPage، override کرد.

ساختن flatpages/default.html به عهده ی شما می باشد. درون دایرکتوری template خودتان، تنها کافیست یک دایرکتوری flatpages حاوی فایل default.html بسازید.

template های flatpage یک متغیر تنهای context با نام flatpage ارسال می کنند که شیء flatpage می باشد.

در زیر یک نمونه template، flatpages/default.html وجود دارد:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html> <head> <title>{{ flatpage.title }}</title> </head> <body> {{ flatpage.content|safe }} </body> </html>

توجه داشته باشید که در کد فوق از فیلتر template، safe برای اجازه به flatpage.content جهت (در دست ترجمه ...) استفاده شده است.

Redirects

فریم ورک redirects جنگو به شما اجازه می دهد تغییر مسیرها را به سادگی توسط ذخیره ی آن ها در یک پایگاه داده و رفتار کردن با آن ها همانند هر شیء مدل دیگری کنترل کنید. برای مثال، می توان از فریم ورک redirects جنگو برای گفتن "هر درخواست به /music/ را به /sections/arts/music/ تغییر مسیر بده" استفاده کرد. هنگامی که نیاز به حرکت دادن برخی لینک در سایت خود داشته باشید این فریم ورک بسیار سودمند می باشد؛ توسعه دهندگان وب باید جهت اجناب از لینک های شکسته شده در صورت لزوم هرکاری انجام دهند.

استفاده از فریم ورک چارچوب Redirects

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

  1. 'django.contrib.redirects' را به تنظیم INSTALLED_APPS اضافه کنید.
  2. 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' به تنظیم MIDDLEWARE_CLASSES اضافه کنید.
  3. دستور manage.py sycdb را به نصب تنها جدول الزامی درون پایگاه داده اجرا کنید.

manage.py syncdb یک جدول django_redirect در پایگاه داده ی شما ایجاد می کند. این یک جدول جستجو با فیلدهای site_id، old_path و new_path می باشد.

می توان redirects را هم از طریق رابط مدیر جنگو و یا از API پایگاه داده ی جنگو ایجاد نمود. برای اطلاعات بیشتر بخش "اضافه کردن، تغییر دادن و حذف Redirects" مراجعه کنید.

هنگامی که redirects ایجاد شد، کلاس RedirectFallbackMiddleware تمام کار را انجام می دهد. هر زمان که هر برنامه ی جنگو یک خطای 404 ایجاد می کند، این middleware پایگاه داده ی redirects را برای URL درخواست شده به عنوان آخرین چاره بررسی می کند. به طور خاص، این middleware برای یک تغییر مسیر با old_path داده شده با یک ID سایت که مطابق با تنظیم SITE_ID می باشد بررسی می کند. (برای اطلاعات بیشتر در مورد SITE_ID و فریم ورک sites به بخش "Sites" در همین فصل مراجعه کنید.) سپس middleware مذکور مراحل زیر را دنبال می کند:

middleware تنها برای خطاهای 404 فعال شده است – نه برای خطاها یا پاسخ های 500 از هر کد وضعیت دیگر.

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

اضافه کردن، تغییر دادن و حذف Redirects

می توان redirects را به دو روش اضافه کرده، تغییر داده و حذف کرد:

از طریق رابط مدیر

در صورتی که رابط مدیر جنگو را فعال کرده باشید، می بایست یک بخش "Redirects" در صفحه ی index مدیر مشاهده کنید. همانطور که هر شیء دیگری را در این سیستم ویرایش می کنید، redirects را نیز ویرایش کنید.

از طریق API پایتون

redirects توسط یک مدل استاندارد جنگو که درون django/contrib./redirects/models.py قرار دارد نشان داده شده است. از این رو، می توان از طریق API پایگاه داده ی جنگو به شیء های redirect دسترسی پیدا کرد، برای مثال:

>>> from django.contrib.redirects.models import Redirect >>> from django.contrib.sites.models import Site >>> red = Redirect.objects.create( ... site=Site.objects.get(id=1), ... old_path='/music/', ... new_path='/sections/arts/music/', ... ) >>> Redirect.objects.get(old_path='/music/') <Redirect: /music/ ---> /sections/arts/music/>

محافظت CSRF

پکیج django.contrib.csrf در مقابل Cross-Site Request Forgery (CSRF) حفاظت می کند.

CSRF، همچنین به صورت "session riding" نیز شناخته می شود، که یک سایت امنیت بهره برداری می باشد. CSRF زمانیکه یک وب سایت مخرب (در دست ترجمه ...).

یک مثال ساده ی CSRF

فرض کنید درون یک حساب webmail در example.com وارد شده اید. این سایت webmail دارای یک دکمه ی log out می باشد که به آدرس example.com/logout اشاره می کند – این بدین معناست که، تنها عملی که برای خروج لازم است رفتن به آدرس example.com/logout می باشد.

یک می سایت مخرب می تواند توسط آن آدرس به صورت یک <iframe> پنهان در ون صفحه ی خود شما را ناگذیر به بازدید از آدرس example.com/logout کند. در نتیجه، در صورتی که درون حساب webmail در example.com باشید و از صفحه ی مخربی که دارای <iframe> به example.com/logout بازدید کنید، عمل بازدید از صفحه ی مخرب شما را از example.com خارج می کند.

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

یک مثال پیچیده در از CSRF

در مثال قبلی، example.com تا حدی مقصر می باشد، زیرا به یک تغییر وضعیت (مانند خرج کاربر) اجازه داده است تا از طریق روش GET درخواست شود. خیلی بهتر است برای هر درخواست از روش POST استفاده شود که وضعیت را در سرور تغییر می دهد. ولی حتی وب سایت هایی که روش POST را برای تغییر وضعیت لازم می دانند نیز برای CSRF آسیب پذیر می باشند.

فرض کنید example.com دارای عملکرد ارتقا پیدا کرده ی خروج می باشد، به طوری که یک دکمه ی <form> از طریق روش POST به آدرس example.com/logout ارسال می کند. بعلاوه، خروج <form> حاوی این فیلد hidden می باشد:

<input type="hidden" name="confirm" value="true">

این موضوع مطمئن می سازد که یک POST ساده به آدرس example.com/logout یک کاربر را خارج نمی سازد؛ به منظور خروج یک کاربر، کاربر باید example.com/logout را از طریق POST در خواست کرده و متغیر POST به نام confirm را با یک مقدار 'true' ارسال کند.

خوب، با وجود امنیت اضافه، این تنظیم می تواند همچنان توسط CSRF مورد سو استفاده قرار گیرد – صفحه ی مخرب تنها نیاز به یک مقدار کار بیشتر دارد. مهاجمان می توانند یک فرم کامل را به هدف سایت شما ساخته، آن را در یک <iframe> غیر قابل مشاهده مخفی کرده، سپس با استفاده از جاوا اسکریپت آن فرم را به طور خود کار ارسال کنند.

جلوگیری از CSRF

بنابراین، چطور یک سایت می تواند خود را از این سو استفاده حفاظت کند؟ (در دست ترجمه ...).

این موضوع درخواست های POST را کنار می گذارد. دومین قدم دادن یک فیلد hidden به هر <form> از نوع POST می باشد که مقدار این فیلد باید محرمانه بوده و از session ID کاربر تولید شده باشد. سپس، هنگام پردازش فرم در سمت سرور، برای آن فیلد محرمانه بررسی به عمل آمده و در صورت معتبر نبودن یک خطا ایجاد می شود.

این دقیقا آن چیزی است که لایه ی جلوگیری CSRF جنگو انجام می دهد، همانطور که در بخش های زیر توضیح داده شده است.

استفاده از CSRF Middleware

پکیج django.contrib.csrf حاوی تنها یک ماژول با نام middleware.py می باشد. این ماژول حاوی یک کلاس middleware جنگو با نام CSRFMiddleware می باشد که حفاظت CSRF را انجام می دهد.

جهت فعال کردن حفاظت CSRF، 'django.contrib.csrf.middleware.CsrfMiddleware'به تنظیم MIDDLEWARE_CLASSES درون فایل تنظیمات خود اضافه کنید. این middleware نیاز است که بعد از SessionMiddleware پاسخ را پردازش کند، بنابراین CSRFMiddleware باید قبل از SessionMiddleware در لیست قرار گرفته باشد (زیرا middleware پاسخ از آخر به اول پردازش شده است). همچنین این middleware باید پاسخ را قبل از آن که پاسخ فشرده شده باشد یا مسائل دیگر پردازش شود، بنابراین CSRFMiddleware باید بعد از GZipMiddleware بیاید. هنگامی که آن را به تنظیم MIDDLEWARE_CLASSES خود اضافه کنید، کار را انجام داده اید. بخش "ترتیب MIDDLEWARE_CLASSES" در آموزش مدل جنگو را برای توضیحات بیشتر مشاهده کنید.

در صورتی که علاقمند می باشید، در زیر نحوه ی عملکرد CsrfMiddleware وجود دارد. دو کار زیر انجام می شود:

  1. درخواست های خروجی را توسط اضافه کردن یک فیلد hidden به تمام فرم های POST، با نام csrfmiddlewaretoken و یک مقدار هش session ID به اضافه ی یک کلید امنیت می باشد، ویرایش می کند. middleware در صورتی که هیچ session ID ای وجود نداشته باشد هیچ ویرایشی انجام نمی دهد، بنابراین کاهش کارایی برای درخواست هایی که از session ها استفاده نمی کنند قابل اغماض است.
  2. در تمام درخواست های ورودی POST که دارای کوکی session نیستند، بررسی می کند که csrfmiddlewaretoken حاضر و درست باشد. در صورتی که نباشد، کاربر یک خطای 403 HTTP دریافت می کند. محتوای صفحه ای خطای 403 در آن نشان داده می شود پیام "Cross Site Request Forgery detected. Request aborted." می باشد.

این اطمینان حاصل می کند که تنها فرم هایی که از سایت شما سرچشمه گرفته اند می توانند از داده ها در برگشت استفاده کنند.

این middleware به طور عمد، تنها درخواست های HTTP POST را هدف گیری می کند (و فرم های POST متناظر). همانطور که توضیح داده شد، درخواست های GET هرگز نباید دارای تاثیرات غیر قابل انتظار باشند؛ این بر عهده ی شما می باشد که از این موضوع مطمئن شوید.

درخواست های POST با یک کوکی session محافظت نشده همراه نمی باشند، ولی آن ها نیاز به محافظت ندارند، زیرا یک وب سایت مخرب در هر صورت می تواند این نوع درخواست ها را بسازد.

جهت اجتناب از تغییر درخواست های غیر HTML ای، middleware نوع header محتویات پاسخ را قبل از ویرایش آن بررسی می کند. تنها صفحاتی که به صورت text/html یا application/xml xhtml باشند ویرایش می شوند.

محدودیت های CSRF Middleware

CsrfMiddleware نیازمند عملکرد فریم ورک session جنگو می باشد. (برای اطلاعات بیشتر به بخش کاربران عضویت و session مراجعه کنید.) در صورتی که از یک session سفارشی یا فریم ورک authentication ای استفاده می کنید که به صورت دستی کوکی های session را مدیریت می کند، این middleware به شما کمکی نخواهد کرد.

در صورتی که برنامه ی شما صفحات HTML و فرم ها را در برخی روش های غیر معمول ایجاد می کند (مثلا، در صورتی که قطعات HTML در عبارت های document.write جاوا اسکریپت ارسال می شوند)، ممکن است فیلتری که فیلد hidden به فرم اضافه می کند دور بزنید. در این مورد، ارسال فرم همواره شکست خواهد خورد. (این به این دلیل اتفاق می افتد که CsrfMiddleware برای اضافه کردن فیلد csrfmiddlewaretoken به HTML شما قبل از آن که صفحه به کلاینت ارسال شود از یک regular expression استفاده می کند. و regular expression گاهی اوقات این نوع HTML ها را نمی تواند کنترل کند.) در صورتی که شک دارید که این موضوع اتفاق می افتد یا خیر، تنها کافیست source را در مرورگر خود تماشا کنید که آیا csrfmiddlewaretoken درون <form> قرار گرفته است یا خیر.

برای اطلاعات و مثال های بیشتر درباره ی CSRF به http://en.wikipedia.org/wiki/csrf مراجعه کنید.

Humanizing Data

پکیج django.contrib.humanize مجموعه ای از فیلترهای مفید template جنگو را برای اضافه کردن یک "human touch" به داده نگه می دارد. جهت فعال کردن این فیلترها، 'django.contrib.humanize' به تنظیم INSTALLED_APPS اضافه کنید. هنگامی که این کار را انجام داده شد، در یک template از {% load humanize %} استفاده کنید، تا به فیلترهای توضیح داده شده در بخش های بعدی دسترسی پیدا کنید.

apnumber

برای شماره های 1 تا 9، این فیلتر شماره به حروف را بر می گرداند. در غیر اینصورت، عدد را بر می گرداند.

Examples:

می توان نمایش یک integer را در یک integer یا رشته ارسال کرد.

intcomma

این فیلتر یک integer را به یک رشته ی حاوی کاما برای هر سه رفم تبدیل می کند.

مثال ها:

می توان نمایش یک integer را در یک integer یا رشته ارسال کرد.

intword

این فیلتر یک large integer را به یک نمایش متن مناسب تبدیل می کند.

مثال ها:

مقادیر تا یک کادریلیون (عدد 1 با پانزده عدد صفر 1000000000000000) پشتیبانی می شوند.

می توان نمایش یک integer را در یک integer یا رشته ارسال کرد.

ordinal

این فیلتر یک integer را به ordinal آن به صورت رشته تبدیل می کند.

مثال ها:

می توان نمایش یک integer را در یک integer یا رشته ارسال کرد.

فیلترهای Markup

پکیج django.contrib.markup شامل چند فیلتر template جنگو می باشند که هرکدام یک زبان markup رایج را اجرا می کنند.

در هر مورد، فیلتر انتظار قالب بندی markup را به صورت یک رشته را داشته و یک نمایش متن markup شده را بر می گرداند. برای مثال، فیلتر textile متنی را که در قالب بندی Textile، mark up شده است را به HTML تبدیل می کند:

{% load markup %} {{ object.content|textile }}

جهت فعال کردن این فیلترها، 'django.contrib.markup'را به تنظیم INSTALLED_APPS اضافه کنید. هنگامی که این کار را انجام داده شد، از {% load markup %} در یک template استفاده کنید تا به این فیلترها دسترسی پیدا کنید. برای مستندات بیشتر، کد منبع