این سایت از کوکی استفاده می کند. ادامه مرور در این سایت به منزله این است که با استفاده کوکی ها توسط ما موافقت کرده اید.

 

خوش آمدید به انجمن تخصصی پایتون و جنگو (پایتونی ها)

لطفاً برای دسترسی به تمامی بخش های سایت مراحل ثبت نام و ایجاد حساب کاربری را طی نمایید.

جستجو در تالار: در حال نمایش نتایج برای برچسب های 'آموزش تصویری جنگو'.



تنظیمات بیشتر جستجو

  • جستجو بر اساس برچسب

    برچسب ها را با , از یکدیگر جدا نمایید.
  • جستجو بر اساس نویسنده

نوع محتوا


تالار ها

  • پایتون ( Python )
    • تالار پایتون مقدماتی
    • تالار پایتون پیشرفته
    • تالار تفاوت زبان پایتون ورژن ۲ و ۳
  • جنگو ( django )
    • تالار جنگو مقدماتی
    • تالار جنگو پیشرفته
    • تالار کتاب جنگو ( جنگو بوک )
    • تالار آموزش پروژه محور جنگو
  • آموزش تکه کدهای کاربردی پایتون ( Python Code Snippet )
  • دریافت نسخه های پایتون
    • نرم افزار زبان برنامه نویسی پایتون
  • دریافت افزونه های پایتون
    • اجرای اسکریپتهای پایتون در اندروید
  • رفع مشكلات برنامه های پايتون
  • معرفی برنامه های تحت پايتون
  • بخش بایگانی

وبلاگ‌ها

  • مقایسه Python با هشت زبان برنامه نویسی مطرح جهان

دسته ها

  • مقاله های سایت

دسته ها

  • دانلود نرم افزار زبان برنامه نویسی پایتون
  • دریافت افزونه های پایتون
    • اجرای اسکریپتهای پایتون در اندروید
  • کتاب های آموزشی پایتون ( Python )
  • کتاب های آموزش فریم ورک جنگو ( Django )

دسته ها

  • آموزش پایتون
    • آموزش پایتون مقدماتی
    • آموزش پایتون پیشرفته
    • تفاوت های پایتون ۲ و پایتون ۳
  • آموزش جنگو
    • آموزش جنگو مقدماتی
    • آموزش جنگو پیشرفته
    • آموزش پروژه محور جنگو
  • تکه کدهای کاربردی پایتون ( Python Code Snippet )
  • آموزش گیت
    • گیت لب ( GitLab )
    • گیت هاب ( GitHub )

7 نتیجه پیدا شد

  1. با عرض سلام خدمت پایتونی های عزیز . امیدوارم موفق و پیروز باشید . در قسمت چهارم از سری آموزش پروژه محور طراحی وبلاگ ساده با جنگو در خدمت شما هستیم . اگر مایل به دیدن آموزش های پروژه محور جنگو هستید به این لینک مراجعه کنید . در قسمت چهارم به نحوه ایجاد دیتابیس و اتصال اون به پنل مدیریت جنگو می پردازیم . ساخت یک وبلاگ ساده با جنگو پایگاه داده ( دیتابیس ) پایه و اساس بسیاری از برنامه های وب است و برنامه جانگو نیز جزو همین خانواده حساب می شود . در این قسمت از آموزش، تنظیمات پایگاه داده را پیکربندی کرده و بعد از اون از پنل مدیریت Django برای همگام سازی پایگاه داده با مدلی که در جلسه قبل ساختیم ، استفاده می کنیم . همانطور که در آموزش فایل settings.py در جنگو گفتیم ، تنظیمات مربوط به دیتابیس های ما در این فایل انجام خواهد گرفت . فراموش نکنید که قرار شد ما خیلی بحث رو سخت نکنیم و فعلا ابتدایی ترین آموزش هارو برای شما دوستان فراهم کنیم . خب فایل settings.py رو با ویراشگرتون باز کنید . در این فایل باید به سراغ دیکشنری DATABASE بریم : خب همانطور که می بینید ما در اینجا از دیتابیس sqlite استفاده کردیم و در خط NAME بهش دیتابیس پروژه رو معرفی کردیم . شما می توانید از نام دیگری استفاده کنید . ولی به صورت پیش فرض می تونید بهش دست نزنید . همین برای شناسوندن دیتابیس به پروژه کافیست . البته از دیتابیس sqlite بیشتر برای آموزش استفاده می شه . بعدها که پروژه های بزرگتر و تجاری انجام دادیم ، خواهید دید که به سراغ دیتابیس Mysql یا PostgreSQL خواهیم رفت . حالا که تنظیمات پایگاه داده پیکربندی شده است می تونید پایگاه داده خودتون رو ایجاد کنید. از اونجایی که شما برای اولین بار این کار را انجام می دید، از شما خواسته می شه که یک حساب کاربری مدیریت که در بخش بعدی مورد استفاده قرار می گیره ، ایجاد کنید. به ترمینال برید و کد زیر رو بزنید : python manage.py syncdb حالا بعد از زدن این دستور به روت پروژه تون مراجعه کنید ، می بینید که فایلی با نام db.sqlite3 ایجاد شده که این فایل دیتا بیس پروژه شماست و اطلاعات شما از قبیل : صفحات و پست ها و کاربران و ... بر روی این فایل ذخیره خواهد شد . پس خیلی مواظب این فایل باشید ! ساخت اکانت مدیر برای پنل مدیریت جنگو جنگو به صورت پیش فرض صفحه مدیریت دارد . اگر به جلسه قبلی رجوع کنید خواهید دید زمانی که ما مدل App بلاگ خودمون رو ایجاد کردیم ... هنگام ایجاد چندتا App‌ دیگه هم به صورت پیش فرض ایجاد شدن که یکی از اونها Admin بود ... برای دسترسی به این صفحه به مرورگر خودتون مراجعه کنید و آدرس زیر رو بزنید تا صفحه ورود به مدیریت رو مشاهده کنید : localhost:8000/admin خب باید با صحنه زیر مواجه بشید : خب برای ورود شما احتیاج به یک اکانت مدیریتی دارید . ترمینال خودتون رو باز کنید و دستور زیر رو وارد کنید . بعد از دستور زیر از شما ایمیل و پسورد میخواد . هر چیزی که دوست دارید وارد کنید ولی فراموشش نکنید . این اکانت مدیریت پروژه شماست . python manage.py createsuperuser طبق مراحل زیر عمل کنید : خب شما موفق شدید اکانت مدیریت برای پروژه خودتون ایجاد کنید . حالا با یوزر نیم admin و پسوردی که ایجاد کردید وارد پنل مدیریت پروژه خودتون بشید . من زیاد موارد داخل پنل مدیریت رو توضیح نمیدم . میتونید از لینک های زیر برای آموزش های بیشتر استفاده کنید : آموزش ایجاد پنل مدیریت در جنگو ( جلسه ششم ) - بخش اول آموزش ایجاد پنل مدیریت در جنگو ( جلسه ششم ) - بخش دوم خب همانطور که می بینید تونستیم دیتابیس پروژه مون رو ایجاد کنیم و بعد به پنل مدیریت پیش فرض جنگو هم دسترسی پیدا کنیم . خیلی خب . شما تا اینجا رو کمی تمرین کنید و کمی با پنل مدیریت جنگو دست و پنجه نرم کنید و بعد به سراغ قسمت بعدی آموزش برید . اگر سوالی یا مشکلی درباره این آموزش داشتید در بخش تاپیک پشتیبانی این آموزش مطرح کنید تا دوستان شما به شما پاسخ بدن . خسته نباشید . جلسه پنجم از سری آموزش پروژه محور ساخت یک وبلاگ ساده با جنگو به پایان رسید . موفق و پیروز باشید پایتونی ها
  2. این تاپیک پشتیبانی برای آموزش است ساخت یک وبلاگ ساده با جنگو ( قسمت پنجم ) 02/07/96 16:10 02/07/96 16:10 لطفا اگرهر سوال یا بازخوردی دارید اینجا ارسال کنید.
  3. نگارش 1.0.0

    132 دریافت

    دانلود کتاب آموزش ساخت فروشگاه آنلاین با پایتون و جنگو ( Beginning Django E-Commerce ) با سلام امروز براتون کتاب بسیار مفید و جالب Beginning Django E-Commerce Jim McGaw-2009 رو براتون آماده کردیم . امیدواریم که این از دانلود و مطالعه این کتاب لذت ببرید . این کتاب در زمینه آموزش پایتون و آموزش فریم ورک جنگو و آموزش ساخت فروشگاه با پایتون و آموزش ساخت فروشگاه آنلاین با جنگو ... کمک بسیار شایانی به شما خواهد کرد . در اینجا سرفصل های این کتاب رو برای شما به نمایش میزاریم : ■About the Author .................................................................................................... xi ■About the Technical Reviewer ............................................................................... xii ■Acknowledgments ................................................................................................ xiii ■Introduction .......................................................................................................... xiv ■Chapter 1: Best Laid Plans.......................................................................................1 ■Chapter 2: Creating a Django Site..........................................................................17 ■Chapter 3: Models for Sale ....................................................................................39 ■Chapter 4: The Shopping Cart................................................................................79 ■Chapter 5: Site Checkout & Orders ......................................................................109 ■Chapter 6: Creating User Accounts......................................................................153 ■Chapter 7: Product Images..................................................................................173 ■Chapter 8: Implementing Product Search ...........................................................179 ■Chapter 9: Intelligent Cross-Selling.....................................................................193 ■Chapter 10: Adding in Ajax ..................................................................................205 ■Chapter 11: Search Engine Optimization .............................................................231 ■Chapter 12: Web Security Overview ....................................................................255 ■Chapter 13: Improving Performance ...................................................................279 ■Chapter 14: Django Testing .................................................................................299 ■Chapter 15: Deployment ......................................................................................323 ■Chapter 16: Django on Google App Engine ..........................................................341 ■Index....................................................................................................................365 لطفا بعد از دانلود و مطالعه این کتاب با نظرات خود در این بخش دیگران را در مطالعه این کتاب راهنمایی کنید . این کتاب برای کسانی که در مسیر یادگیری زبان برنامه نویسی پایتون و جنگو هستند بسیار مناسب است . اگر قصد ساخت سایت فروشگاهی با جنگو و یا آموزش ساخت وب سایت آنلاین با پایتون رو دارید این کتاب رو مطالعه کنید . امیدوارم که از این کتاب استفاده کامل رو برده باشید . پایتونی ها

    رایگان

  4. این تاپیک پشتیبانی برای آموزش است فریم ورک جنگو ( Django ) چیست ؟ 31/04/96 16:19 31/04/96 16:19 لطفا اگرهر سوال یا بازخوردی دارید اینجا ارسال کنید.
  5. با عرض سلام خدمت تمام پایتونی های عزیز . امیدوارم هرجا هستید موفق و پیروز باشید . در خدمت شما هستیم با مقاله جنگو چیست ؟ با ما همراه باشید . فریم ورک جنگو ( Django ) چیست ؟ در کل یک توضیح کلی درباره فریم ورک جنگو وجود دارد : جنگو ( Django ) یک چارچوب نرم‌افزاری تحت وب آزاد و متن‌باز است که به زبان پایتون نوشته شده است و از معماری MVC ( Model–view–controller) پیروی می‌کند. هدف اصلی جنگو ساخت آسان سایت‌های پیچیده و وابسته به دیتابیس است و بر پایهٔ قابلیت استفادهٔ مجدد و قابل اتصال بودن اجزای مختلف، توسعهٔ سریع و اصل خودت را تکرار نکن (DRY) طراحی شده است. جنگو سراسر از پایتون استفاده می‌کند، حتی برای تنظیمات، فایل‌ها و مدل‌های اطلاعات . تاثیر پایتون بر این فریم ورک کل این فریم ورک با استفاده از زبان پایتون پیاده سازی شده است . پس بسیاری از ویژگی های خود را از زبان پایتون به ارث برده است . با استفاده از این فریم ورک امکان ایجاد وب سایت هایی حرفه ای و پیچیده در کمترین زمان ممکنه و همچنین با در نظر گرفتن مورادی چون امنیت و سرعت و … فراهم می باشد . در ادامه برخی از ویژگی های قابل تاکید زبان پایتون که تاثیر مهمی بر این فریم ورک دارند مطرح می گردد . *** پایتون زبانی تفسیری بوده و برای اجرا نیازی به کامپایل ندارد . در برنامه نویسی وب با استفاده از این ویژگی بعد از تغییر کد یا ایجاد آن نتایج کار بلافاصله قابل مشاهده می باشد . *** انواع داده در پایتون داینامیک می باشد . پس شما نگرانی از تعریف نوع متغییر ندارید . *** سینتکس زبان پایتون کوتاه و در عین حال واضح و قابل فهم می باشد . این بدین معنی هست که برای انجام کار های مشابه کدی بسیار کمتر لازم می باشد . برای مثال معمولا هر خط پایتون معادل ۱۰ خط در جاوا (Java) می باشد !! *** پایتون روشهایی قدرتمند برای meta-programming در اختیار قرار می دهد . این ویژگی امکان ویرایش با اضافه کردن رفتار ها و توابع را با اشیا در زمان اجرای برنامه فراهم می کند . جدایی از ویژگی های فوق جنگو خود روشهایی برای افزایش سرعت و سهولت برنامه نویسی همزمان با رعایت کامل موارد امنیتی و کارایی را دارا می باشد . که در ادامه با برخی از این ویژگی ها بیشتر آشنا خواهیم شد . چرا شما به فریم ورک نیاز دارید؟ برای اینکه واقعا بفهمیم جنگو چیست و چه کاربردهایی داره باید دقت کنیم به سرورها . اولین چیز و مهمترین کار یک سرور این است که برای شما یک صفحه وب را نمایش بگذارد . شما یک صندوق پستی را تصور کنید که نامه ها را دریافت میکند و میخواند . این وظیفه یک سرور می باشد . بعد از خواندن نامه ها یکی یکی صفحاتی که درخواست شده برای نمایش را به نمایش میزاره . اما وقتی میخواهید چیزی را ارسال کنید، باید محتوایی داشته باشید. و جانگو چیزی است که به شما در ایجاد محتوا کمک می کند. چه اتفاقی می افتد وقتی کسی از یک سرور وب سایت شما درخواست می کند؟ هنگامی که یک درخواست به یک وب سرور می آید، به جنگو منتقل می شود که تلاش می کند تا آنچه را که واقعا درخواست شده است، بفهمد. ابتدا آدرس صفحه وب رو تلاش میکنه تا پیدا کنه . این قسمت توسط urlresolver Django انجام می شه . یک لیست از الگوها را می گیرد و تلاش می کند URL را مطابقت بده . جانگو الگوها را از بالا به پایین بررسی می کنه و اگر چیزی هماهنگ باشه با درخواست کاربر ، جانگو درخواست را به تابع مربوطه می فرسته (که آن تابع نمایش داده بشه ). شما دقیقا یک پستچی رو در نظر بگیرید که داره تو یه خیابون راه میره و طبق آدرس نامه ها داره نامه هارو توی خونه ها میندازه . یکی از کارای جنگو هم همینه. پس متوجه شدید که چگونه urlresolver کار می کنه! به نظرم همین توضیح کوتاه کفایت میکنه راجب جنگو در کل همین قدر بدونید که جنگو فریم ورکی و یا به زبان ساده تر یه کتابخونه ای پر از کد هست که قواعد استفاده خاص خودش رو داره و به ما کمک میکنه برای طراحی سایت با پایتون وقت کمتری رو هدر بدیم . وقتی به آموزش های پروژه محور جنگو در لینک زیر نگاه کنید کم کم متوجه خواهید شد که این فریم ورک چقدر کار مارو راحت تر میکنه برای طراحی سایت آموزش پروژه محور جنگو موفق و پیروز باشید . پایتونی ها
  6. View ها و URLconf های پیشرفته در جنگو ( جلسه هشتم ) در آموزش view و urlconf جنگو ، اصول اولیه توابع view و URLconf ها توضیح داده شد. این فصل به جزئیان بیشتری درباره ی عمکرد پیشرفته ی این دو مبحث درون فریم ورک جنگو (Django) خواهد پرداخت. فوت و فن URLconf نکته ی ویژه ای درباره ی URLconf ها وجود ندارد – همانند جنگو، همه چیز فقط کد پایتون می باشد. می توان از این موضوع در روش های مختلفی بهره جست، همانطور که در بخش های این فصل توضیح داده شده است. ساده کردن import توابع URLconf زیر را مشاهده کنید، که در آموزش view و urlconf جنگو ساخته شده است: from django.conf.urls.defaults import * from mysite.views import hello, current_datetime, hours_ahead urlpatterns = patterns('', (r'^hello/$', hello), (r'^time/$', current_datetime), (r'^time/plus/(\d{1,2})/$', hours_ahead), ) همانطور که در آموزش view و urlconf جنگو توضیح داده شده است، هر آیتم در URLconf شامل تابع view همراه خود می باشد، که به طور مستقیم به صورت شیء تابع، ارسال شده است. این بدین معناست که import کردن توابع view در بالای ماژول امری ضروری می باشد. ولی همانطور که یک برنامه ی جنگو به سمت پیچیدگی رشد می کند، URLconf آن نیز رشد می کند، از این رو استفاده از روش import قبلی می تواند کمی خسته کننده باشد. (برای هر تابع view جدید، باید import کردن آن را نیز فراموش نکرد، و عبارت import در صورتیکه از این روش استفاده کنید بیش از حد بلند می باشد.) این امکان وجود دارد که روش قبلی را با import کردن خود ماژول views دُر بزنید. مثال URLconf زیر برابر با مثال قبلی می باشد: from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^hello/$', views.hello), (r'^time/$', views.current_datetime), (r'^time/plus/(d{1,2})/$', views.hours_ahead), ) جنگو روش دیگری را نیز جهت تعیین تابع view برای یک الگوی خاص در URLconf ارائه می کند: می توان یک رشته حاوی نام ماژول و نام تابع به جای خود شیء تابع ارسال کرد: from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^hello/$', 'mysite.views.hello'), (r'^time/$', 'mysite.views.current_datetime'), (r'^time/plus/(d{1,2})/$', 'mysite.views.hours_ahead'), ) (به علامت تک کتیشن دور نام view ها توجه کنید. در کد فوق از 'mysite.views.current_datetime' با علامت کتیشن به جای mysite.views.current_datetime استفاده شده است.) با استفاده از این تکنیک، import کردن توابع view دیگر ضروری نمی باشد؛ جنگو به طور خودکار با استفاده از رشته ی مشخص شده با نام و مسیر تابع view، تابع view مناسب را import می کند. یک میانبر دیگر که می توان هنگام استفاده از تکنیک رشته از آن استفاده کرد، از قلم انداختن پیشوند view می باشد. در مثال URLconf، هر رشته ی view با 'mysite.views' شروع شده است، که یک حالت اضافی می باشد. می توان پیشوند مشترک این رشته را حذف کرده و آن را به عنوان اولین آرگومان patterns() مانند زیر استفاده کرد: from django.conf.urls.defaults import * urlpatterns = patterns('mysite.views', (r'^hello/$', 'hello'), (r'^time/$', 'current_datetime'), (r'^time/plus/(d{1,2})/$', 'hours_ahead'), ) توجه داشته باشید که نقطه ی عقبی را در پیشوند و رشته های view قرار ندهید. جنگو این نقطه ها را به صورت خودکار قرار خواهد داد. با در نظر گرفتن دو روش فوق، کدام روش بهتر است؟ این بستگی به نحوه ی کد زدن شما و نیازهای کد دارد. مزایای روش رشته: *** این روش بسیار جمع و جور می باشد، زیرا در این روش دیگر نیازی به import کردن توابع view نمی باشد. *** این روش خواناتر بوده و قابلیت مدیریت URLconf ها در صورتیکه توابع view درون چندین ماژول مختلف پخش شده باشد آسان تر خواهد بود. مزایای روش شیء تابع: *** در این روش دسته بندی توابع view آسان می باشد. بخش "دسته بندی توابع view" که در این فصل می باشد را مطالعه کنید. *** این روش پایتونی تر می باشد – چرا که این روش بیشتر در راستای سنت های پایتون می باشد، مانند ارسال توابع به صورت شیء. هر دو روش معتبر می باشند، و می توان حتی این دو روش را درون یک URLconf یکسان با یکدیگر ترکیب کرد. انتخاب با خود شماست. استفاده از پیشوند چندگانه ی view در عمل، در صورتیکه از تکنیک رشته استفاده می کنید، ممکن است هنگامی که URLconf دارای پیشوند مشترک نیست ترکیب view ها را پایان دهید. البته در این حالت نیز می توان هنوز از میانبر پیشوند view برای حذف موارد تکراری سود برد. تنها کافیست از شیء های چندگانه ی patterns() به صورت زیر استفاده کنیم: کد قدیمی: from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^hello/$', 'mysite.views.hello'), (r'^time/$', 'mysite.views.current_datetime'), (r'^time/plus/(\d{1,2})/$', 'mysite.views.hours_ahead'), (r'^tag/(\w )/$', 'weblog.views.tag'), ) کد جدید: from django.conf.urls.defaults import * urlpatterns = patterns('mysite.views', (r'^hello/$', 'hello'), (r'^time/$', 'current_datetime'), (r'^time/plus/(\d{1,2})/$', 'hours_ahead'), ) urlpatterns = patterns('weblog.views', (r'^tag/(\w )/$', 'tag'), ) تمام چهارچوب کار این است که یک متغیر در سطح ماژول با نام urlpatterns وجود داشته باشد. این متغیر می تواند به صورت پویا ساخته شده باشد، همانطور که در مثال فوق انجام داده شده است. به طور خاص باید اشاره کرد که شیء های برگردانده شده با patterns() می توانند به یکدیگر اضافه شده باشند، که این موضوعی است که امکان دارد انتظار آن را نداشته باشید. پوشش خاص URL ها در حالت Debug بعد از صحبت درباره ی ساختن urlpatterns به طور پویا، ممکن است بخواهید از این تکنیک برای تغییر رفتار URLconf ها در حالت debug جنگو استفاده کنید. برای انجام این کار، تنها کافیست مقدار تنظیم DEBUG را در زمان اجرا بررسی کنید، مانند زیر: from django.conf import settings from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^$', views.homepage), (r'^(\d{4})/([a-z]{3})/$', views.archive_month), ) if settings.DEBUG: urlpatterns = patterns('', (r'^debuginfo/$', views.debug), ) در این مثال، آدرس /debuginfo/ تنها در صورتیکه مقدار تنظیم DEBUG، True باشد در دسترس خواهد بود. استفاده از Named Groups در تمام مثال های URLconf ای که تاکنون در این کتاب آورده شده است، از regular expression های ساده ی بدون نام استفاده شده است – یعنی اینکه، تنها آن قسمت از URL مورد نظر درون پرانتز قرار داده شده است، و جنگو آن متن داخل پرانتز را به تابع view به صورت یک آرگومان موضعی (positional argument) ارسال می کرد. برای کاربرد پیشرفته تر، این امکان وجود دارد که از گروه های regular expression نام گذاری شده، برای ارسال قسمت هایی از URL، به صورت آرگومان های کیورد به view استفاده کرد. آرگومان های کیورد در مقابل آرگومان های موضعی یک تابع پایتون می تواند با استفاده از آرگومان های کیورد یا آرگومان های موضعی فراخوانی شود – و در برخی موارد، با استفاده از هردوی آن ها در یک زمان. در یک فراخوانی با استفاده از آرگومان کیورد، شما نام هایی را، برای آرگومان های به همراه مقدارهایی که ارسال خواهد شد، تعیین می کنید. در یک فراخوانی با استفاده آرگومان موضعی، شما به سادگی آرگومان هایی را بدون تعیین صریح مقدار برای آن ارسال می کنید؛ مقدار آن آرگومان به ترتیب قرار گیری آرگومان ها بستگی دارد. برای مثال تابع ساده ی زیر را ملاحظه کنید: def sell(item, price, quantity): print "Selling %s unit(s) of %s at %s" % (quantity, item, price) جهت فراخوانی تابع فوق با آرگومان های موضعی، شما آرگومان ها را به ترتیبی که در تعریف تابع چیده شده اند قرار می دهید: sell('Socks', '$2.50', 6) جهت فراخوانی آن با آرگومان های کیورد، شما نام های آرگومان ها را به همراه مقادیر برای آنها تعیین می کنید. عبارات زیر با هم برابر می باشند: sell(item='Socks', price='$2.50', quantity=6) sell(item='Socks', quantity=6, price='$2.50') sell(price='$2.50', item='Socks', quantity=6) sell(price='$2.50', quantity=6, item='Socks') sell(quantity=6, item='Socks', price='$2.50') sell(quantity=6, price='$2.50', item='Socks') در پایان، تا زمانی که تمام آرگومان های موضعی قبل از آرگومان های کیورد قرار بگیرند می توان آرگومان های کیورد و موضعی را ترکیب کرد،: sell('Socks', '$2.50', quantity=6) sell('Socks', price='$2.50', quantity=6) sell('Socks', quantity=6, price='$2.50') در regular expression های پایتون، نحوه ی کد نویسی برای گروه های نام گذاری شده ی regular expression به این شکل می باشد: (?P<name>pattern)، که name نام گروه و pattern الگوی تطبیق داده شده می باشد. مثال زیر URLconf ای می باشد که از گروه های بدون نام استفاده کرده است: from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^articles/(\d{4})/$', views.year_archive), (r'^articles/(\d{4})/(\d{2})/$', views.month_archive), ) مثال زیر URLconf همسان با مثال قبلی می باشد که با استفاده از گروه های نام گذاری شده باز نویسی شده است: from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^articles/(?P<year>\d{4})/$', views.year_archive), (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive), ) کد فوق دقیقا همان کاری را که در مثال قبلی آمد انجام می دهد، تنها با یک تفاوت: مقادیر داخل پرانتز به جای آرگومان های موضعی به صورت آرگومان های کیورد به توابع view ارسال می شوند. به عنوان مثال، برای گروه های بدون نام، یک درخواست به /articles/2006/03/ در یک فراخوانی تابع برابر با کد زیر خواهد بود: month_archive(request, '2006', '03') برای گروه های نام گذاری شده، فراخوانی تابع به صورت زیر خواهد بود: month_archive(request, year='2006', month='03') در عمل، استفاده از گروه های نام گذاری شده، URLconf ها را کمی واضح تر می کند و آن ها را کمتر در معرض خطاهای ترتیب آرگومان قرار می دهد – و می توان با استفاده از گروه های نام گذاری شده ترتیب آرگومان ها را در تعریف توابع view تغییر داد. در مثال قبلی، در صورت استفاده از گروه های بدون نام اگر می خواستیم آدرس ها را طوری تغییر دهیم که ماه قبل از سال قرار بگیرد، باید این تغییرات را درون تابع month_archive نیز اعمال می کردیم. ولی در صورت استفاده از گروه های نام گذاری شده، تغییر دادن ترتیب پارامتر های داخل پرانتز در regular expression درون URL هیچ تاثیری در view نخواهد داشت. البته،در کنار مزایای گفته شده برای گروه های نام گذاری شده، این روش با هزینه هایی در اختصار همراه است، برخی توسعه دهندگان، گروه های نام گذاری شده را، کد اضافه و بد منظر تشخیص می دهند. ولی همچنان مزیت دیگر گروه های نامگذاری شده خوانایی آن ها می باشد، به ویژه برای کسانی که با regular expression آشنایی نزدیکی در برنامه های جنگو دارند. با یک نگاه در یک URLconf ای که از گروه های نامگذاری شده استفاده کرده است به سادگی می توان آنچه را که اتفاق افتاده است را تشخیص داد. فهمیدن الگوریتم Matchin/Grouping نکته ی مهمی که در استفاده از گروه های نامگذاری شده قابل اهمیت می باشد این است که، یک الگوی URLconf به تنهایی، نمی تواند حاوی گروه های بدون نام و گروه های نام گذاری شده به طور همزمان باشد. در صورتیکه همچین حالتی پیش آید، جنگو هیچ خطایی ایجاد نخواهد کرد، ولی ممکن است URL های شما را، آن طور که انتظار آن را دارید تشخیص ندهد. به طور خاص، در اینجا الگوریتم تجزیه کننده ی URLconf، با توجه به گروه های نام گذاری شده در مقابل گروه های بدون نام در یک regular expression ذکر شده است. *** در صورتیکه هر آرگومان نام گذاری شده ای وجود داشته باشد، از آن ها استفاده خواهد شد و آرگومان های بدون نام نادیده گرفته می شوند. *** در غیر اینصورت، تمام آرگومان های بدون نام به صورت آرگومان های موضعی ارسال می شوند. *** در هر دو مورد، option هایی اضافه به صورت آرگومان های کیورد ارسال می شود. برای اطلاعات بیشتر بخش بعدی را مطالعه کنید. ارسال Option های اضافی به توابع view گاهی اوقات متوجه این موضوع می شوید که توابع view نوشته شده، با وجود اندکی تفاوت، کاملا مشابه با یکدیگر می باشند. برای مثال، فرض می کنیم دو تابع view وجود دارد که بجز template هایی که مورد استفاده قرار می دهند حاوی محتویات یکسان می باشند: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^foo/$', views.foo_view), (r'^bar/$', views.bar_view), ) # views.py from django.shortcuts import render_to_response from mysite.models import MyModel def foo_view(request): m_list = MyModel.objects.filter(is_new=True) return render_to_response('template1.html', {'m_list': m_list}) def bar_view(request): m_list = MyModel.objects.filter(is_new=True) return render_to_response('template2.html', {'m_list': m_list}) در کد فوق تقریبا همه چیز تکرار شده است و این نحوه ی کد زنی به هیچ وجه روش زیبایی به نظر نمی رسد. در ابتدا، ممکن است تصور کنید که با استفاده از یک view برای هر دو URL می توان کدهای اضافه را حذف کرد، و URL ها را در URLconf داخل پرانتز قرار داد، و در آخر نیز آن ها را درون view گفته شده مانند زیر بررسی کنیم: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^(foo)/$', views.foobar_view), (r'^(bar)/$', views.foobar_view), ) # views.py from django.shortcuts import render_to_response from mysite.models import MyModel def foobar_view(request, url): m_list = MyModel.objects.filter(is_new=True) if url == 'foo': template_name = 'template1.html' elif url == 'bar': template_name = 'template2.html' return render_to_response(template_name, {'m_list': m_list}) مشکل راهکار فوق این است که، اگرچه URL های شما با کد شما جفت شده است، ولی در صورتیکه تصمیم بگیرید /foo/ را به /fooey/ تغییر نام دهید، شما نباید فراموش کنید که کد view را نیز تغییر دهید. راهکار زیبا برای این مورد استفاده از یک پارامتر اختیاری برای URLconf می باشد. هر الگویی در یک URLconf ممکن است شامل یک آیتم سوم باشد: یک دیکشنری از آرگومان های کیورد برای ارسال به تابع view. با در نظر گرفتن این، می توان مثال قبلی را به این شکل باز نویسی کرد: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}), (r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}), ) # views.py from django.shortcuts import render_to_response from mysite.models import MyModel def foobar_view(request, template_name): m_list = MyModel.objects.filter(is_new=True) return render_to_response(template_name, {'m_list': m_list}) همانطور که مشاهده می کنید، URLconf در مثال فوق، template_name را درون URLconf تعیین کرده است. تابع view مانند پارامترهای دیگر با template_name رفتار می کند. تکنیک option های اضافه ی URLconf روش مناسبی برای ارسال اطلاعات اضافی برای توابع view با حداقل کد می باشد. به همین دلیل، در بسیاری از برنامه های جنگو از آن استفاده می شود، مهمترین خصوصیت این روش حالت generic داشتن view ها می باشد، که در view های generic درباره ی آن صحبت خواهد شد. بخش های بعدی حاوی تعدادی از ایده ها، نسبت به نحوه ی استفاده از تکنیک option های اضافه ی URLconf در پروژه ها می باشد. Faking Captured URLconf Values فرض را بر این بگیرید که مجموعه ای از view ها دارید که از یک الگو طبعیت می کنند، البته به همراه URL ای دیگر که با الگو سازگار نبوده ولی منطق view آن یکی است. در این مورد، می توان مقدار داخل پرانتز URL را، با استفاده از option های اضافه ی URLconf، برای کنترل URL اضافه با view همسان جا زد. برای مثال، ممکن است برنامه ای داشته باشید که برخی داده ها برای یک روز خاص را نمایش دهند، با URL هایی مانند زیر: /mydata/jan/01/ /mydata/jan/02/ /mydata/jan/03/ # ... /mydata/dec/30/ /mydata/dec/31/ به کار بردن URL های فوق به اندازه ی کافی ساده می باشد – می توان آن ها را درون یک URLconf مانند زیر کنترل کرد (با استفاده از گروه نام گذاری شده): urlpatterns = patterns('', (r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view), ) و یک تابع view مانند زیر: def my_view(request, month, day): # .... روش فوق بسیار ساده می باشد – چیزی وجود ندارد که قبلا گفته نشده باشد. تکنیک و فن خاص زمانی پیش می آید، که بخواهید URL دیگری اضافه کنید که از my_view استفاده می کند، ولی حاوی month و day نباشد. برای مثال، ممکن است بخواهید URL دیگری مانند /mydata/birthday/ اضافه کنید، که برابر با /mydata/jan/06/ باشد. می توان از امکان option های اضافه URLconf مانند زیر استفاده کرد: urlpatterns = patterns('', (r'^mydata/birthday/$', views.my_view, {'month': 'jan', 'day': '06'}), (r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view), ) نکته ی جالب در کد فوق این است که شما هیچوقت مجبور به تغییر تابع view نمی باشد. تابع view تنها پارامترهای month و day سر و کار دارد – مشکلی نیست اگر این پارامترها به صورت URL داخل پرانتز و یا پارامترهای اضافه ارسال شوند. ساختن یک View Generic حذف کد های تکراری یک تمرین مناسب برای برنامه نویسی می باشد. برای مثال، با این دو تابع پایتون: def say_hello(person_name): print 'Hello, %s' % person_name def say_goodbye(person_name): print 'Goodbye, %s' % person_name می توان hello و goodbye را حذف کرده و آنرا به عنوان پارامتر یک تابع قرار داد: def greet(person_name, greeting): print '%s, %s' % (greeting, person_name) می توان این فلسفه را در view های جنگو نیز با استفاده از پارامترهای اضافه ی URLconf به کار برد. با در نظر گرفتن این موضوع، می توان تصورات سطح بالایی را از view ها ایجاد نمود. بجای آنکه فرض کنیم "این view لیستی از شیء های Event را نمایش می دهد،" می توان در نظر گرفت که "آن view لیستی از شیء های BlogEntry را نمایش می دهد". البته به این موضوع دقت کنید که هر دوی آن ها مورد خاصی هستند "یک view لیستی از شیء ها را نمایش می دهد، که نوع شیء قابل تغییر می باشد." به عنوان مثال نگاهی به کد زیر بیاندازید: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^events/$', views.event_list), (r'^blog/entries/$', views.entry_list), ) # views.py from django.shortcuts import render_to_response from mysite.models import Event, BlogEntry def event_list(request): obj_list = Event.objects.all() return render_to_response('mysite/event_list.html', {'event_list': obj_list}) def entry_list(request): obj_list = BlogEntry.objects.all() return render_to_response('mysite/blogentry_list.html', {'entry_list': obj_list}) هر دو view فوق اساسا یک کار انجام می دهند: آن ها لیستی از شیء ها را نمایش می دهند. بنابراین اجازه دهید نوع شیءی را که نمایش می دهند را حذف کنیم: # urls.py from django.conf.urls.defaults import * from mysite import models, views urlpatterns = patterns('', (r'^events/$', views.object_list, {'model': models.Event}), (r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}), ) # views.py from django.shortcuts import render_to_response def object_list(request, model): obj_list = model.objects.all() template_name = 'mysite/%s_list.html' % model.__name__.lower() return render_to_response(template_name, {'object_list': obj_list}) با تغییرات کوچک فوق، ما به طور ناگهانی دارای یک view قابل استفاده ی مجدد و عمومی شده ایم! از حالا به بعد، در هر زمان که نیاز به یک view داشته باشیم که مجموعه ای از شیء ها را لیست کند، می توان به سادگی از object_list به جای نوشتن کد view استفاده کرد. در زیر توضیحاتی درباره ی کارهای انجام داده ی فوق وجود دارد: کلاس های مدل به طور مستقیم به صورت پارامتر model ارسال شده اند. پارامترهای ارسالی اضافه در URLconf می توانند نه تنها رشته ها، بلکه هر نوعی از شیء های پایتون را ارسال کنند. *** خط model.objects.all() یک مثال ساده از duck typing می باشد: "در صورتیکه چیزی مانند اردک راه برود و مانند اردک صحبت کند، می توان با آن مانند اردک رفتار کرد." دقت کنید که کد مورد نظر نمی داند، که نوع شیء model چه می باشد، تنها نکته ی لازم این است که model دارای یک attribute به نام objects باشد که آن نیز به نوبه ی خود دارای یک متد all() باشد. *** در تعیین نام template از model.__name__.lower() استفاده شده است. هر کلاس پایتون دارای یک attribute با نام __name__ می باشد که نام کلاس را بر می گرداند. این ویژگی برای زمان هایی مانند مثال فوق مفید می باشد، هنگامی که نام کلاس را تا زمان اجرای برنامه نمی دانیم. برای مثال مقدار __name__ برای کلاس BlogEntry رشته ی 'BlogEntry' می باشد. *** تفاوت جزئی بین این مثال و مثال قبلی این است که، متغیر generic ای با نام object_list به template ارسال شده است. می توان به سادگی نام این متغیر را به blogentry_list و یا even_list تغییر داد، ولی ما به عنوان تمرین برای خواننده آن را بدین صورت باقی گذاشته ایم. به دلیل آن که وب سایت های پایگاه داده محور، دارای چندین الگوی مشترک می باشند، جنگو مجموعه ای از "generic view" ها را که دقیقا از تکنیک فوق برای صرفه جویی در زمان استفاده می کنند، ارائه می کند. view های داخلی generic در view های generic توضیح داده شده اند. دادن Option های پیکربندی View در صورتیکه یک برنامه ی جنگو را توزیع (distribute) می کنید، این احتمال وجود دارد که کاربران شما برخی درجات پیکربندی را بخواهند. در این مورد، ایده ی خوبی است که برای هر انتخاب پیکربندی که فکر می کنید افراد ممکن است بخواهند آن را تغییر دهند، hook هایی را در view ها اضافه کنید. یک قسمت مشترک از یک برنامه برای ایجاد قابلیت پیکربندی، نام template می باشد: def my_view(request, template_name): var = do_something() return render_to_response(template_name, {'var': var}) فهمیدن اولویت مقدار داخل پرانتز در مقابل Option های اضافه هنگام وجود مغایرت، پارامترهای اضافه ی URLconf بر پارامترهای داخل پرانتز اولویت دارند. به عبارت دیگر، در صورتیکه URLconf شما، یک متغیر از نوع گروه نام گذاری شده درون پرانتز داشته باشد، و همچنین یک پارامتر اضافه ی URLconf را با متغیر همنام با آن، در این صورت مقدار پارامتر اضافه ی URLconf استفاده خواهد شد. برای مثال URLconf زیر را مشاهده کنید: from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^mydata/(?P<id>\d )/$', views.my_view, {'id': 3}), ) در کد فوق، هر دوی regular expression و دیکشنری اضافه، حاوی یک id می باشند که دیکشنری اضافه دارای اولویت می باشد. این بدین معناست که هر درخواستی (مانند /mydata/2/ یا /mydata/432432) بدین صورت رفتار خواهد کرد که مقدار id بدون در نظر گرفتن مقدار داخل پرانتز URLconf عدد 3 می باشد. خوانندگان زیرک در این مورد توجه خواهند داشت، که قرار دادن id داخل پرانتز در regular expression اتلاف وقت می باشد، زیرا مقدار آن همواره توسط مقدار دیکشنری باز نویسی می شود. درست آن است که؛ در دست ترجمه ... استفاده از آرگومان های پیشفرض View فوت و فن مناسب دیگر، تعیین پارامتر های پیشفرض برای آرگومان های view می باشد. با استفاده از این تکنیک در صورتیکه مقدار یک پارامتر اصلا تعیین نشود از مقدار پیشفرض تعیین شده استفاده می کند. مثال: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^blog/$', views.page), (r'^blog/page(?P<num>\d )/$', views.page), ) # views.py def page(request, num='1'): # Output the appropriate page of blog entries, according to num. # ... در کد فوق، هر دو الگوی URL به یک view اشاره می کنند – views.page – ولی اولین الگو درون URL هیچ مقداری داخل پرانتز قرار نداده است. در صورتیکه اولین الگو تطبیق پیدا کند، تابع page() از مقدار آرگومان پیشفرض num یعنی '1' استفاده خواهد کرد. همچنین در صورت تطبیق الگوی دوم، تابع page() از هر مقداری که توسط regular expression درون پرانتز حاصل می شود استفاده خواهد کرد. (توحه داشته باشید که بایستی مقدار پیشفرض آرگومان را رشته ی '1' قرار دهیم، نه یک integer. زیرا هر مقداری که داخل پرانتز URLconf برای num قرار گرفته است همواره یک رشته خواهد بود.) استفاده از این تکنیک، در رابطه با option های پیکربندی نیز متداول می باشد، همانطور که پیش تر توضیح داده شد. مثال زیر مثال بهبود پیدا کرده ی بخش "دادن option های پیکربندی view" با تهیه ی یک مقدار پیشفرض برای template_name می باشد: def my_view(request, template_name='mysite/my_view.html'): var = do_something() return render_to_response(template_name, {'var': var}) موارد خاص View ها گاهی اوقات شما الگویی در URLconf خواهید داشت که مجموعه ی بزرگی از URL ها را کنترل می کند، ولی شما تنها به یک مورد خاص از آن ها نیاز خواهید داشت. در این موارد، از روش خطی یک URLconf ای که پردازش شده است می توانید استفاده کنید و مورد خاص را اول قرار دهید. برای مثال، می توانید صفحات "add an object" در سایت مدیر جنگو را به صورت نمایش داده شده با یک URLpattern مانند زیر تصور کنید: urlpatterns = patterns('', # ... ('^([^/] )/([^/] )/add/$', views.add_stage), # ... ) کد فوق با URL هایی از قبیل /myblog/entries/add/ و /auth/groups/add/ تطبیق پیدا می کند. اگرچه صفحه ی "add" برای یک شیء user (/auth/user/add/) یک مورد خاص می باشد – تمام فیلدهای فرم را نمایش نمی دهد، بلکه دو فیلد رمز عبور و الی آخر را نمایش می دهد. ما این مشکل را به شکل زیر حل کرده ایم: def add_stage(request, app_label, model_name): if app_label == 'auth' and model_name == 'user': # do special-case code else: # do normal code ولی روش فوق برای یک دلیل که چندین بار در این فصل آن را لمس کرده ایم روش زیبایی نیست: روش فوق منطق URL را درون view قرار می دهد. راهکار بهتر این است که، از این واقعیت سود ببریم که URLconf ها از بالا به پایین پردازش می شوند: urlpatterns = patterns('', # ... ('^auth/user/add/$', views.user_add_stage), ('^([^/] )/([^/] )/add/$', views.add_stage), # ... ) با استفاده از روش فوق، درخواست برای /auth/user/add/ از طریق user_add_stage کنترل خواهد شد. اگرچه که URL با الگوی دوم مطابقت دارد، ولی ابتدا با الگوی بالاتر تطبیق پیدا می کند. پوشش دادن متن در URL ها هر آرگومان پوشش داده شده ای به صورت یک رشته ی یونیکد پایتون به view فرستاده می شود. به عنوان مثال در خط URLconf زیر: (r'^articles/(?P<year>\d{4})/$', views.year_archive), آرگومان year برای views.year_archive() یک رشته خواهد بود، نه یک integer، حتی اگر \d{4} تنها با رشته های از نوع integer مطابقت داشته باشد. بخاطر داشتن این موضوع هنگامی که کد view را می نویسید مهم می باشد. بسیاری از توابع داخلی پایتون نسبت به قبول کردن تنها شیء های از نوع مشخص حساس می باشند. یکی از خطاهای متداول ساختن یک شیء datetime.date با مقادیر رشته به جای مقادیر integer می باشد: >>> import datetime >>> datetime.date('1993', '7', '9') Traceback (most recent call last): ... TypeError: an integer is required >>> datetime.date(1993, 7, 9) datetime.date(1993, 7, 9) تبدیل شده ی به یک URLconf و view، خطایی مانند زیر خواهد بود: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', (r'^articles/(\d{4})/(\d{2})/(\d{2})/$', views.day_archive), ) # views.py import datetime def day_archive(request, year, month, day): # The following statement raises a TypeError! date = datetime.date(year, month, day) به جای day_archive() می توان به این شکل آنرا اصلاح نمود: def day_archive(request, year, month, day): date = datetime.date(int(year), int(month), int(day)) توجه داشته باشید که تابع int() خودش هنگامی که یک رشته ی غیر قابل تبدیل به integer به آن ارسال شود یک خطای ValueError ایجاد می کند، ولی از آن جهت که regular expression در URLconf در این مورد تنها رشته های قابل تبدیل به integer (مانند "245") را قبول می کند دیگر نگرانی برای این موضوع وجود نخواهد داشت. تعیین آنچه را که URLconf به دنبال آن جستجو می کند هنگامی که یک درخواست ارسال می شود، جنگو در تلاش بر می آید که الگوهای URLconf را برای URL درخواست شده به صورت رشته ی پایتون تطبیق دهد. این شامل پارامترهای GET یا POST و یا نام دامین نمی شود. همچنین شامل علامت (/) آغازین نیز نمی شود، زیرا هر URL دارای یک علامت (/) آغازین می باشد. برای عنوان مثال، در یک درخواست به http://www.example.com/myapp/، جنگو تلاش می کند تا آن را با myapp/ تطبیق دهد. در یک درخواست به exampl.com جنگو تلاش می کند تا آن را با myapp/ تطبیق دهد. method درخواست (مانند POST، GET) هنگام عبور کردن URLconf به حساب نمی آید. به عبارت دیگر، تمام method های درخواست درون تابع همسان برای URL همسان بررسی می شوند. اجرا کردن method های درخواست به عهده ی تابع view می باشد. تصور سطح بالا از توابع view صحبت کردن درباره ی روش branching based در method درخواست، اجازه دهید به نحوه ی ساخت یک روش زیبا از انجام این روش نگاهی بیاندازیم. لایه ی URLconf و view زیر را ملاحظه کنید: # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', # ... (r'^somepage/$', views.some_page), # ... ) # views.py from django.http import Http404, HttpResponseRedirect from django.shortcuts import render_to_response def some_page(request): if request.method == 'POST': do_something_for_post() return HttpResponseRedirect('/someurl/') elif request.method == 'GET': do_something_for_get() return render_to_response('page.html') else: raise Http404() در مثال فوق، some_page()، درخواست های POST و GET را کاملا متفاوت کنترل می کند. تنها چیزی که به صورت مشترک دارا می باشند یک URL به اشتراک گذاشته می باشد: /somepage/. به همین دلیل، اینکه با هر دوی POST و GET در یک تابع view سر و کار داشت، روش زیبایی نمی باشد. روش مناسب آن است که دو تابع view مجزا داشته باشیم – یکی درخواست های GET را کنترل کرده و دیگری درخواست های POST را – و مطمئن بود که هر یک تنها در زمان مناسب فراخوانی می شوند. می توان با توشتن یک تابع view که نماینده ی دیگر view ها می باشد، قبل و بعد اجرا برخی جملات منطقی این کار را انجام داد. در مثال زیر نحوه ی انجام این روش در some_page() وجود دارد: # views.py from django.http import Http404, HttpResponseRedirect from django.shortcuts import render_to_response def method_splitter(request, GET=None, POST=None): if request.method == 'GET' and GET is not None: return GET(request) elif request.method == 'POST' and POST is not None: return POST(request) raise Http404 def some_page_get(request): assert request.method == 'GET' do_something_for_get() return render_to_response('page.html') def some_page_post(request): assert request.method == 'POST' do_something_for_post() return HttpResponseRedirect('/someurl/') # urls.py from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', # ... (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}), # ... ) اجازه دهید کد فوق را مورد بررسی قرار دهیم: *** یک view جدید با نام method_splitter() نوشته شده است، که نماینده ی view های دیگر می باشد. این تابع دو آرگومان کیورد یعنی GET و POST که باید توابع view باشند را جستجو می کند. در صورتیکه request.method مقدارش 'GET' باشد، view مورد نظر یعنی GET را فراخوانی و در صورتیکه مقدار آن 'POST' باشد POST را فراخوانی می کند. همچنین در صورتیکه request.method چیزی غیر از موارد ذکر شده باشد (مانند HEAD و غیره ...) و یا در صورتیکه GET یا POST در تابع عرضه نشده باشند، سپس یک Http404 ایجاد خواهد شد. *** درون URLconf به /somepage/ در method_splitter() اشاره شده و آرگومان های اضافه به آن ارسال شده اند – توابع view به ترتیب برای استفاده از GET و POST. *** در پایان، تابع some_page() به دو تابع view تقسیم شده است – some_page_get() و some_page_post(). این روش بسیار زیباتر از نشان دادن تمام منطق درون یک view می باشد. توجه داشته باشید این توابع view از نظر فنی دیگر لازم نیست request.method را بررسی کنند، زیرا method_splitter() این کار را انجام می دهد. (در آن زمان که some_page_post() فراخوانی شده است، می توان مطئمن بود که مقدار request.method، 'post' می باشد.) حالا، ما دارای یک تابع generic خوب برای خودمان می باشیم که منطق نمایندگی دادن به یک view را با استفاده از request.method به اصطلاح encapsulate کرده است. هیچ چیزی درباره ی method_splitter() گره خورده به برنامه ی خاص نیست، بنابراین می توان در پروژه های دیگر نیز از آن استفاده کرد. یک روش برای بهبود method_splitter() وجود دارد. همانطور که نوشته شده است، این تابع فرض می کند که view های GET و POST آرگومان های غیر از request دریافت نمی کنند. چه می شود اگر بخواهیم از method_splitter یا view هایی که، پارامترهایی متنی را از URL ها می گیرند و یا آرگومان های اختیاری برای خود می گیرند استفاده کنیم؟ برای انجام چنین کاری، می توان از یک ویژگی زیبای پایتون استفاده کرد: آرگومان های متغیر با علامت ستاره. در ابتدا مثالی را نشان خواهیم داد و سپس آن را توضیح می دهیم: def method_splitter(request, *args, **kwargs): get_view = kwargs.pop('GET', None) post_view = kwargs.pop('POST', None) if request.method == 'GET' and get_view is not None: return get_view(request, *args, **kwargs) elif request.method == 'POST' and post_view is not None: return post_view(request, *args, **kwargs) raise Http404 در کد فوق، method_splitter() را تغییر داده ایم، به طوری که آرگومان های کیورد GET و POST در آن حذف شده اند و جای آن ها از *args و **kwargs (به علامت ستاره توجه کنید) استفاده شده است. این یک خصوصیت پویای پایتون می باشد که به یک تابع اجازه می دهد یک تعداد دلخواه از آرگومان ها را که نام آن ها تا زمان اجرا مشخص نخواهد بود قبول کند. در صورتیکه یک علامت ستاره تکی در تعریف یک تابع قبل یک پارامتر قرار دهید، هر آرگومان موضعی به آن تابع در یک تاپل جمع خواهد شد. در صورتیکه دو علامت ستاره قبل از یک پارامتر در تعریف تابع قرار دهید، هر آرگومان کیورد به آن تابع داخل یک دیکشنری جمع می شوند. def foo(*args, **kwargs): print "Positional arguments are:" print args print "Keyword arguments are:" print kwargs در زیر نحوه ی عملکرد آن مشخص شده است: >>> foo(1, 2, 3) Positional arguments are: (1, 2, 3) Keyword arguments are: {} >>> foo(1, 2, name='Adrian', framework='Django') Positional arguments are: (1, 2) Keyword arguments are: {'framework': 'Django', 'name': 'Adrian'} به method_splitter() باز می گردیم، می توانید مشاهده کنید که برای قبول کردن هر آرگومان به تابع و ارسال آنها به همراه view مناسب از *args و **kwargs استفاده کرده ایم. ولی بعد از انجام این کار، دو فراخوانی به kwargs.pop() برای بدست آوردن آرگومان های GET و POST در صورت دسترس ایجاد کرده ایم. (از pop() با یک مقدار پیشفرض None جهت دوری از خطای KeyError در صورتیکه یکی از آن ها تعریف نشده باشد استفاده شده است.) Wrapping View Functions آخرین فن view سود جستن از یک تکنیک پیشرفته ی پایتون می باشد. تصور کنید در سرتاسر view های مختلف متوجه دسته ای از کدهای تکراری شده اید مانند مثال زیر: def my_view1(request): if not request.user.is_authenticated(): return HttpResponseRedirect('/accounts/login/') # ... return render_to_response('template1.html') def my_view2(request): if not request.user.is_authenticated(): return HttpResponseRedirect('/accounts/login/') # ... return render_to_response('template2.html') def my_view3(request): if not request.user.is_authenticated(): return HttpResponseRedirect('/accounts/login/') # ... return render_to_response('template3.html') در کد فوق، هر view با بررسی اینکه request.user تایید شده است یا خیر شروع می شود – کاربر فعلی با موفقیت وارد سایت شده است – و به مسیر /accounts/login/ تغییر مسیر داده می شود. (توجه داشته باشید که هنوز request.user توضیح داده نشده است – در بخش کاربران عضویت و session درباره ی این موضوع بحث شده است – ولی، همانطور که ممکن است تصور کنید، request.user کاربر فعلی را نمایش می دهد) بسیار زیبا می باشد اگر قسمت های تکراری کد موجود در هر کدام از view ها حذف شوند و تنها در صورت نیاز آن ها را علامت گذاری کرد. می توان این کار را با ساختن یک view wrapper انجام داد. چند لحظه ای کد زیر را مطالعه کنید: def requires_login(view): def new_view(request, *args, **kwargs): if not request.user.is_authenticated(): return HttpResponseRedirect('/accounts/login/') return view(request, *args, **kwargs) return new_view تابع فوق، requires_login، یک تابع view (view) را دریافت می کند و یک تابع view جدید (new_view) بر می گرداند. تابع جدید، new_view داخل requires_login تعریف شده و منطق بررسی request.user.is_authenticated() و محول کردن view اصلی (view) را کنترل می کند. حالا می توان بررسی if not request.user.is_authenticated() از view ها حذف کرد و با requires_login در URLconf قرار داد: from django.conf.urls.defaults import * from mysite.views import requires_login, my_view1, my_view2, my_view3 urlpatterns = patterns('', (r'^view1/$', requires_login(my_view1)), (r'^view2/$', requires_login(my_view2)), (r'^view3/$', requires_login(my_view3)), ) کد فوق تاثیر یکسانی را به صورت قبل داراست، ولی با زوائد کد کمتر. حالا ما یک تابع generic زیبا ساخته ایم – requires_login() که می توان برای هر تابع view به منظور نیاز به ورود به سایت استفاده کرد. در بر داشتن URLconf های دیگر در صورتیکه قصد دارید کد شما در سایت های گوناگون ایجاد شده توسط جنگو استفاده شود، شما باید URLconf های خود را به روشی تنظیم کنید که "including" برای آن ها مقدور باشد. در هر نقطه، URLconf شما می تواند ماژول های دیگر URLconf را شامل شود. برای مثال، URLconf زیر حاوی URLconf های دیگری نیز می باشد: from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^weblog/', include('mysite.blog.urls')), (r'^photos/', include('mysite.photos.urls')), (r'^about/$', 'mysite.views.about'), ) (روش فوق را قبل تر در سایت مدیر مشاهده کرده اید، هنگامی که سایت مدیر جنگو معرفی شده است. سایت مدیر دارای URLconf خودش می باشد که شما تنها داخل URLconf دیگر آن ها را وارد کردید.) یک مفهوم مهم در اینجا وجود دارد: regular expression ها که در این مثال به یک include() اشاره می کنند، دارای علامت ($) نمی باشند. هر زمان که جنگو با include() برخورد می کند، هر بخش از URL مطابقت داده شده با آن نقطه را برش می دهد و رشته ی باقیمانده برای URLconf ای که Include شده را جهت پردازش بیشتر می فرستد. به مثال زیر توجه کنید: from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^(\d\d\d\d)/$', 'mysite.blog.views.year_detail'), (r'^(\d\d\d\d)/(\d\d)/$', 'mysite.blog.views.month_detail'), ) با این دو URLconf، در اینجا نحوه ی کنترل تعدادی از درخواست ها وجود دارند: *** /weblog/2007/: در اولین URLconf، الگوی r'weblog/' تطبیق داده می شود. زیرا آن یک include() است، جنگو تمام متن مطابق را در می آورد، که در این مورد 'weblog/' می باشد. پاقیمانده ی بخش URL 2007/ می باشد، که اولین خط در URlconf مورد نظر یعنی mysite.blog.urls تطبیق داده می شود. *** /weblog//2007/ (با دو علامت /) در اولین URLconf، الگوی r'weblog/' تطبیق داده می شود. زیرا یک include() می باشد، جنگو تمام متن مطابق را در می آورد، که در این مورد 'weblog/' می باشد. باقیمانده ی بخش URL /2007/ می باشد (با یک علامت / اولیه)، که هیچ خطی از URLconf مورد نظر یعنی mysite.blog.urls با آن تطبیق داده نمی شود. *** /about/: این URL در URLconf اول و view مورد نظر یعنی mystie.views.about تطبیق داده می شود، نشان می دهد که می توان الگوهای include() را با الگوهای non-include() ترکیب کرد. نحوه ی کار با include() پارامترهای پوشش داده شده یک URLconf شامل شده، هر پارامتر پوشش داده شده ای از URLconf های پدر را دریافت می کند، برای مثال: # root urls.py from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^(?P<username>\w )/blog/', include('foo.urls.blog')), ) # foo/urls/blog.py from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^$', 'foo.views.blog_index'), (r'^archive/$', 'foo.views.blog_archive'), ) در مثال فوق، متغیر پوشش داده شده ی username به URLconf شامل شده و هر تابع view موجود در آن URLconf ارسال شده است. توجه داشته باشید که پارامترهای پوشش داده شده همواره به هر خط در URLconf شامل شده صرف نظر از اینکه آیا view آن خط واقعا آن پارامتر های به صورت معتبر قبول خواهد کرد یا خیر ارسال شده خواهند بود. به همین دلیل، این تکنیک تنها در صورتیکه شما مطمئن باشید که هر view در URLconf شامل شده پارامترهای ارسال شده را قبول می کند مفید خواهد بود. نحوه option های اضافه URLconf در کار با include() به طور مشابه، می توان انتخاب های اضافه ی URLconf به include() ارسال کرد، همانطور که می توان option های اضافه ی URLconf را به یک view معمولی ارسال کرد – به صورت یک دیکشنری. هنگامی که شما این کار را انجام دهید، هر خط در URLconf شامل شده، option اضافه ی ارسال شده خواهد بود. برای مثال، دو دسته ی URLconf زیر دارای عملکرد یکسان می باشند. دسته ی اول: # urls.py from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^blog/', include('inner'), {'blogid': 3}), ) # inner.py from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^archive/$', 'mysite.views.archive'), (r'^about/$', 'mysite.views.about'), (r'^rss/$', 'mysite.views.rss'), ) دسته دوم : # urls.py from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^blog/', include('inner')), ) # inner.py from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^archive/$', 'mysite.views.archive', {'blogid': 3}), (r'^about/$', 'mysite.views.about', {'blogid': 3}), (r'^rss/$', 'mysite.views.rss', {'blogid': 3}), ) خسته نباشید دوستان عزیز . جلسه هشتم کتاب جنگو به پایان رسید . امیدوارم که موفق باشید . برگرفته از سایت oruji.org ترجمه از سایت www.djangobook.com