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

 

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

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

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



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

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

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

نوع محتوا


تالار ها

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

وبلاگ‌ها

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

دسته ها

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

دسته ها

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

دسته ها

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

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

  1. نگارش 1.0.0

    24 دریافت

    کتاب آموزش برنامه نویسی اندروید با پایتون ( Pro Android Python with SL4A ) این کتاب آموزشی به زبان انگلیسی است و در ادامه سر فصل های این کتاب رو در اختیار شما عزیزان قرار میدیم تا در صورت لزوم دانلود کرده و استفاده کنید . About the Author xi About the Technical Reviewer xii Acknowledgments xiii Preface xiv Chapter 1: Introduction Chapter 2: Getting Started Chapter 3: Navigating the Android SDK Chapter 4: Developing with Eclipse Chapter 5: Exploring the Android API Chapter 6: Background Scripting with Python Chapter 7: Python Scripting Utilities Chapter 8: Python Dialog Box–based GUIs Chapter 9: Python GUIs with HTML Chapter 10: Packaging and Distributing این کتاب 300 صفحه می باشد و برای کسانی که به دنبال آموزش برنامه نویسی اندروید با زبان پایتون هستند مناسب می باشد . لطفا بعد از دانلود و مطالعه کتاب برای کمک به دیگران نظرات خود را درباره این کتاب در ادامه مطلب باز گو کنید . با تشکر پایتونی ها

    رایگان

  2. این تاپیک پشتیبانی برای آموزش است آموزش ایجاد پنل مدیریت در جنگو ( جلسه ششم ) - بخش دوم 12/04/96 11:13 12/04/96 11:13 لطفا اگرهر سوال یا بازخوردی دارید اینجا ارسال کنید.
  3. آموزش سایت مدیرت پیشفرض در جنگو ( بخش دوم ) صفحه ی فوق تمام کاربران موجود در پایگاه داده را نمایش می دهد، می توانید این را به صورت پرس وجو پایگاه داده یک نسخه ی زیبا شده از عبارت SELECT * FROM auth_user تصور کنید. در صورتیکه همراه با مثال های کتاب حرکت می کنید، تنها یک کاربر را مشاهده خواهید کرد، ولی هنگامی که کاربران بیشتری وجود داشته باشد، امکانات مفیدی از قبیل فیلتر کردن، چیدن و جستجوی بین آیتم ها را مشاهده خواهید کرد. امکان فیلتر کردن در سمت راست صفحه موجود می باشد، چیدمان از طریق کلیک کردن روی یک header ستون عملی می شود، و جعبه ی جستجو (search box) در قسمت بالا صفحه می باشد اجازه می دهد بر اساس نام کاربری به جستجو بپردازید. بر روی نام کاربری که ساخته اید کلیک کنید، فرم ویرایش برای کاربر را مشاهده خواهید کرد. صفحه ی فوق این اجازه را می دهد که خصوصیات کاربر را تغییر دهید، مانند نام و نام خانوادگی و حق دسترسی های گوناگون. (توجه داشته باشید که برای تغییر رمز عبور کاربر به جای ویرایش کد hash، می بایست بر روی "change password form" در زیر فیلد رمز عبور کلیک کرد.) نکته ی دیگر قابل توجه اینکه فیلدهای مختلف به شکل های مختلف پیاده سازی شده اند؛ به عنوان مثال، فیلد زمان و تاریخ دارای کنترل تقویم، فیلدهای Boolean دارای checkbox ها و فیلدهای حروف حاوی فیلد ساده ی مربوط به متن می باشند. می توان برای حذف کردن یک رکورد بر روی دکمه ی delete در قسمت پایین سمت چپ از فرم ویرایش کلیک کرد. بسته به شیء هایی که قصد حذف کردن آن را دارید، صفحه ی مربوط به تایید برای حذف رکورد نمایان خواهد شد، به عنوان مثال، در صورتیکه یک ناشر را حذف کنید، هر کتاب مربوط به ناشر نیز حذف خواهد شد! همچنین می توان با کلیک کردن بر روی "Add" درون ستون مناسب از صفحه ی خانگی مدیر یک رکورد را اضافه کرد. بعد از کلیک صفحه ای با فیلدهای خصوصیات خالی نمایان می شود که آماده برای پر شدن است. همچنین متوجه این موضوع خواهید شد که رابط مدیر همچنین معتبر بودن ورودی ها را برای شما کنترل می کند. یکی از فیلدهایی را که باید حتما پر شود را خالی بگذارید و یا یک مقدار نا معتبر درون یکی از فیلدها قرار دهید، سپس شما خطاهایی را هنگام ذخیره مانند شکل 5-6 مشاهده خواهید نمود. هنگامی که یک شیء موجود را ویرایش می کنید، متوجه یک لینک History در قسمت راست بالای صفحه خواهید شد. هر تغییری درون رابط مدیر اتفاق بیافتد در اینجا ثبت خواهد شد، و می توان با کیک کردن بر روی لینک History آن تغییر را بررسی کرد. اضافه کردن مدل ها به سایت مدیر یک بخش بسیار مهمی هنوز انجام نشده است. اجازه دهید مدل های خود را به سایت مدیر اضافه کنیم، بنابراین می توان شیء های درون جداول پایگاه داده ی مورد نظر را با این رابط عالی حذف، اضافه و تغییر داد. در این فصل نیز مثال books را دنبال خواهیم کرد که در آن سه مدل به نام های Publisher، َAuthor و book تعریف شده است. درون دایرکتوری books (mysite/books)، یک فایل با نام admin.py ایجاد کرده و کد زیر درون آن وارد کنید: from django.contrib import admin from mysite.books.models import Publisher, Author, Book admin.site.register(Publisher) admin.site.register(Author) admin.site.register(Book) کد فوق برای هر یک از مدل ها یک رابط به مدیر جنگو اضافه می کند. هنگامی که این کار انجام داده شد، به صفحه ی خانگی مدیر درون مرورگر خود رفته (http://127.0.0.1/admin/)، شما باید قسمت "Books" را با لینک های Authors، Books و Publishers مشاهده کنید. (برای موثر واقع شدن تغییرات می بایست سرور را متوقف کرده و دوباره اجرا runserver کنید) شما هم اکنون برای هر از این سه مدل یک رابط مدیر در حال کار خواهید داشت. بسیار ساده است! می توانید زمانی را برای اضافه کردن و تغییر رکوردها اختصاص دهید، تا داده هایی را درون پایگاه داده اضافه کنید. در صورتیکه مثال های آموزش مدل جنگو (ساختن شیء های Publisher) را دنبال کرده و آن ها را حذف نکرده باشید، آن رکوردهای ساخته شده در آموزش مدل جنگو را در صفحه ی لیست تغییرات publisher مشاهده خواهید کرد. یکی از خصوصیات با ارزشی که می توان در اینجا ذکر کرد، کنترل سایت مدیر برای کلیدهای خارجی و رابطه های چند به چند می باشد، هر دوی این حالت ها در مدل Book وجود دارند، برای یادآوری کد زیر مدل Book می باشد: class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return self.title درون صفحه ی "Add book" مدیر (http://127.0.0.1:8000/admin/books/book/add/)، Publisher (یک ForeignKey) با یک جعبه ی انتخاب (select box) نمایش داده شده است، و فیلد Authors (یک ManyToManyField) با یک جعبه ی چند انتخابی (multiple-select box) نمایش داده شده است. هر دو فیلد فوق دارای یک علامت سبز رنگ جمع در جلوی خود می باشند که برای اضافه کردن رکوردهای مرتبط به آن ها می باشد. برای مثال، در صورتیکه شما بر روی آن علامت سبز رنگ جلوی فیلد "Publisher" کلیک کنید، یک پنجره ی pop-up برای اضافه کردن یک ناشر باز می باشد. بعد از آنکه یک ناشر در پنجره ی باز شده ساخته شود، صفحه ی "Add book" با جدید ترین ناشر ساخته شده به روزرسانی می شود. نحوه ی کار سایت مدیر در پشت صحنه، سایت مدیر چه طور کار می کند؟ نحوه ی کار آن بسیار ساده می باشد. هنگامی که جنگو URLconf را هنگام اجرای سرور در urls.py بارگذاری می کند، عبارت admin.autodiscover() که در درون این برای فعال کردن سایت مدیر قرار داده شده است اجرا می شود. این تابع درون تنظیم INSTALLED_APPS به دنبال فایلی به نام admin.py که درون هر یک از ایتم ها جستجو می کند. در صورتیکه admin.py درون یکی از app های داده شده وجود داشته باشد، کد درون آن فایل اجرا می شود. در فایل admin.py درون app مورد نظر یعنی books، فراخوانی هر admin.site.register() به سادگی مدل داده شده را درون سایت مدیر عضو می کند. سایت مدیر تنها یک رابط ویرایش/تغییر برای مدل های عضو شده را نمایش می دهد. همانطور که مشاهده شد، سایت مدیر به صورت خودکار Users و Groups را نمایش می دهد که درون app خود یعنی django.contrib.auth می باشند که این app شامل فایل admin.py خود و Users و Groups درون آن می باشد. app های دیگر django.contrib، مانند django.contrib.redirects، نیز خودشان را درون سایت مدیر اضافه می کنند. از این گذشته، سایت مدیر جنگو تنها یک application جنگو با مدل های خود، view ها و URLpattern ها می باشد. با استفاده از URLconf آن را به برنامه ی خود اضافه می کنید، تنها درون view ها خود از آن استفاده می کنید. می توان template ها، view ها و URLpattern های آن را با رفتن به مسیر django.contrib/admin مشاهده و بازرسی کنید ولی تحریک به تغییر چیزی به طور مستقیم در آنجا نشوید چرا که امکانات استفاده ی غیر مستقیم زیادی برای شما وجود دارد. ایجاد فیلدهای اختیاری بعد از آنکه کمی با سایت مدیر آشنا شده و از آن استفاده کردید، ممکن است متوجه محدودیت هایی شده باشید، مانند اینکه هر فیلد باید پر شده باشد، در حالیکه در بسیاری از موارد شما می خواهید پر کردن بعضی از فیلدها اختیاری باشد، به عنوان مثال، می خواهیم فیلد email مدل Author اختیاری باشد یعنی بتوان فیلد را خالی گذاشت. در دنیای واقعی، شما ممکن است هیچ آدرس الکترونیکی نداشته باشید. برای تعیین کردن فیلد email اختیاری، مدل Book را ویرایش می کنیم (این مدل درون فایل mysite/books/models.py می باشد.) برای این کار به سادگی blank=True را به مانند مثال زیر به فیلد email اضافه می کنیم: class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(blank=True) حرکت فوق به جنگو می گوید که برای آدرس پست الکترونیک نویسندگان می توان مقدار خالی را نیز در نظر گرفت. به صورت پیش فرض، تمام فیلدها blank=False می باشند، بدین معنی که مقدار خالی را نمی توان برای آن ها در نظر گرفت. تا حالا، بجز متد __unicode__()، مدل های ما به صورت جداول پایگاه داده ما بکار می رفتند یعنی مدل ها عبارات پایتونی معادل عبارات CREATE TABE در SQL بودند. با اضافه کردن blank=True، ما شروع به گسترش دادن مدل فراتر از تعریف ساده ی مشابه با جدول پایگاه داده کرده ایم. حال، کلاس مدل در حال تبدیل شدن به یک مجموعه ی غنی از دانش درباره ی آنچه که شیء های Author هستند و می توانند انجام دهند، می باشد. نه تنها فیلد email یک ستون VARCHAR در پایگاه داده می باشد، بلکه همچنین می دانیم که یک فیلد اختیاری در سایت مدیر جنگو نیز می باشد. این حالت بدین معنی می باشد که فیلد مورد نظر اختیاری می باشد. حالا می توان نویسندگان را بدون نیاز به تهیه ی آدرس الکترونیک اضافه کرد؛ در صورتیکه فرم مورد نظر را با فیلد خالی آدرس الکترونیک Submit کنید دیگر هیچ پیام "This field is required" با رنگ قرمز مشاهده نخواهید کرد. هنگامی که blank=True اضافه شد، فرم ویرایش "Add author" را دوباره بارگذاری کنید (http://127.0.0.1:8000/admin/books/author/add/)، متوجه خواهید شد که نام فیلد "Email" دیگر به صورت تو پر و پر رنگ نمی باشد. ایجاد فیلد های از نوع تاریخ و عددی به صورت اختیاری نکته ی مهم در رابطه با blank=True این است که انجام این حرکت بر روی فیلدهای از نوع عددی و تاریخ نیازمند مقداری توضیح و پیش زمینه می باشد. SQL برای تعیین مقدار خالی دارای روش خاص خودش می باشد – یک مقدار ویژه به نام NULL. NULL می تواند به معنای ناشناخته، نامعتبر یا ... معنی شود. در SQL یک مقدار NULL با یک مقدار رشته ی خالی متفاوت می باشد، درست مثال شیء None در پایتون که با یک رشته ی خالی پایتون ("") متفاوت می باشد. این بدان معنی است که ممکن است یک فیلد حرفی (مانند یک ستون VARCHAR) به طور همزمان هم حاوی مقدار NULL و هم حاوی یک رشته ی خالی باشد. این موضوع می تواند موجب ابهام و گیجی نا خواسته شود. "چرا این رکورد دارای مقدار NULL ولی آن رکورد دیگر دارای یک رشته ی خالی است؟ ایا تفاوتی وجود دارد، یا فقط داده به صورت نا سازگار وارد شده است؟" و: "چطور می توان تمام رکوردهایی که دارای مقدار خالی می باشند را بدست آورد – ایا می توان هر دو رکوردهای NULL و رشته ی خالی را جستجو کرد، یا یک از آن ها را با مقدار رشته ی خالی انتخاب کرد؟" برای کمک به خلاص شدن از این قبیل ابهامات، جنگو به صورت خودکار عبارت های CREATE TABLE (که در آموزش مدل جنگو توضیح داده شده اند) اضافه و برای هر ستون مقدار NOT NULL را در نظر می گیرد. برای مثال، کد زیر عبارت تولید شده برای مدل Author در آموزش مدل جنگو می باشد: CREATE TABLE "books_author" ( "id" serial NOT NULL PRIMARY KEY, "first_name" varchar(30) NOT NULL, "last_name" varchar(40) NOT NULL, "email" varchar(75) NOT NULL ) ; در اغلب موارد، این حالت پیشفرض برای برنامه مطلوب بوده و شما را از درد سر های تناقض و نا هماهنگی های داده حفظ می کند. و برای بقیه ی قسمت های جنگو به خوبی کار می کند، مانند سایت مدیر جنگو، که در زمان خالی گذاشتن یک فیلد یک رشته ی خالی (نه مقدار NULL) وارد می کند. ولی برای نوع ستون هایی که رشته ی خالی را به عنوان مقدار معتبر قبول نمی کنند – ازقبیل تاریخ ها، زمان ها، و اعداد، یک استثناء وجود دارد. در صورتیکه سعی کنید یک رشته ی خالی برای ستون های ذکر شده وارد کنید، بسته به نوع پایگاه داده ی شما احتمالا خطای پایگاه داده رخ خواهد. در این حالت، NULL تنها راه برای تعیین مقدار خالی می باشد. در مدل های جنگو، می توان مقدار NULL را با اضافه کردن null=True به یک فیلد تعیین کرد. در صورتیکه بخواهید اجازه دهید مقادیر خالی در فیلد تاریخ (مانند DateField، TimeField، DateTimeField) یا فیلد عددی (مانند IntegerField، DecimalField، FloatField) قرار گیرند نیاز است از null=True و blank=True با هم استفاده کنید. اجازه دهید مدل Book را برای اینکه بتوان فیلد publication_date را خالی گذاشت تغییر دهیم: class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField(blank=True, null=True) اضافه کردن null=True پیچیده تر از اضافه کردن blank=True می باشد، زیرا null=True از نظر معنایی پایگاه داده را تغییر می دهد – در این حالت عبارت CREATE TABLE تغییر می کند بدین شکل که NOT NULL از فیلد publication_date حذف می شود. برای کامل کردن این تغییر، نیاز است پایگاه داده به روز رسانی شود. به دلایلی، جنگو تلاشی برای تغییرات خودکار در شمای پایگاه داده نمی کند، بنابراین مسئولیت اجرای یک عبارت ALTER TABLE هر زمان که که تغییری در مدل ایجاد شد، به عهده خودتان می باشد. می توان از manage.py dbshell برای این منظور استفاده کرد. در کد زیر نحوه ی حذف NOT NULL در این مورد خاص را مشاهده می کنید: ALTER TABLE books_book ALTER COLUMN publication_date DROP NOT NULL; (توجه داشته باشید که کد فوق برای پایگاه داده ی PostgreSQL می باشد.) توضیح و بحث عمیق تر در مورد این تغییرات در آموزش مدل پیشرفته بحث شده است. به سایت مدیر بر می گردیم، اکنون فرم ویرایش "Add book" اجازه می دهد تا مقدار خالی را برای publication date قرار دهیم. سفارشی کردن نام فیلدها در فرم های ویرایش سایت مدیر، نام هر فیلد از روی نام مدل فیلد تولید می شود. الگوریتم آن بسیار ساده می باشد: جنگو تنها خط های تیره (_) را با فاصله ها جایگزین کرده و حروف اول را تبدیل به حروف بزرگ می کند، بنابراین، برای مثال، فیلد publication_date مدل Book دارای نام "Publication date" خواهد بود. اگر چه نام فیلدها درون مدل به طور زیبایی درون سایت مدیر نیز تغییر می کنند، ولی در برخی موارد ممکن است بخواهید آن نام ها را خودتان تعیین کنید. با استفاده از verbose_name می توان این کار را انجام داد. برای مثال، در زیر نحوه ی تغییر نام فیلد Author.email به "e-mail" نشان داده شده است: class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(blank=True, verbose_name='e-mail') تغییر فوق را ایجاد کرده و صفحه را دوباره بارگذاری کنید، شما باید فیلد مورد نظر با نام جدید مشاهده کنید. توجه داشته باشید، در صورتیکه حرف اول نامی که انتخاب می کند حرف بزرگ نباشد جنگو به طور خودکار آن را تبدیل به حروف بزرگ می کند. در پایان، توجه داشته باشید که می توان verbos_name را به صوت یک آرگومان موضعی نیز ارسال کرد، کد زیر برابر با مثال قبلی می باشد: class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField('e-mail', blank=True) حرکت فوق برای فیلدهای ManyToManyField و ForeignKey کار نخواهد کرد، زیرا در این فیلدها باید اولین آرگومان یک کلاس مدل باشد. در این موارد، می بایست از verbose_name به صورت واضح استفاده کرد. کلاس های ModelAdmin مرسوم نغییراتی که تاکنون اعمال شد – blank=True، null=True و verbose_name – تغییراتی در سطح مدل بوده اند، نه تغییرات در سطح مدیر. خیلی پیش می آید که تغییرات مورد نیاز سایت مدیر در یک بخش از مدل انجام پذیرد و استفاده شوند، هیچ چیز تعیین شده ای برای مدیر وجود ندارد. گذشته از این، سایت مدیر جنگو امکانات و اختیارات قدترمندی برای سفارشی کردن نحوه ی کار سایت مدیر برای مدل خاص ارائه می کند. سفارشی کردن لیست های تغییر اجازه دهید از طریق تعیین کردن فیلدها که درون لیست تغییر برای مدل Author قرار دارند وارد مسائل سفارشی سازی مدیر شویم. به طور پیشفرض، لیست تغییر نتیجه ی __unicode__() برای هر شیء را نمایش می دهد. در آموزش مدل جنگو، متد __uncode__() برای شیء های Author جهت نمایش نام و فامیلی با هم تعریف شد. class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(blank=True, verbose_name='e-mail') def __unicode__(self): return u'%s %s' % (self.first_name, self.last_name) در نتیجه لیست تغییر برای شیء های Author نام و نام خانوادگی را با هم نمایش می دهد، همانطور که در شکل 8-6 مشاهده می کنید. می توان این رفتار پیشفرض را با اضافه کردن تعدادی از فیلدها برای تغییر نمایش لیست بهبود بخشید. برای مثال، برای دیدن آدرس الکترونیک هر نویسنده در این لیست، و همچنین اضافه کردن امکان چیدمان بر اساس نام و نام خانوادگی می توان یک کلاس ModelAdmin برای مدل Author تعریف کرد. این کلاس کلید سفارشی سازی مدیر، و یکی از اولیه ترین چیزهایی است که اجازه می دهد لیست فیلدها را جهت نمایش در صفحه ی لیست تغییر تعیین کنید. فایل admin.py را جهت این تغییرات ویرایش کنید: from django.contrib import admin from mysite.books.models import Publisher, Author, Book class AuthorAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'email') admin.site.register(Publisher) admin.site.register(Author, AuthorAdmin) admin.site.register(Book) در زیر مثال فوق، توضیح داده شده است: ** کلاس AuthorAdmin ساخته شده است. کلاس AuthorAdmin که از کلاس پدر خود یعنی django.admin.ModelAdmin ارث بری کرده است پیکربندی های تعیین شده برای مدل مدیر را نگه می دارد. تنها یک پیکربندی – list_display، انجام شده است که نام فیلدهایی را که قرار است درون لیست تغییر نمایش داده شوند، درون یک تاپل قرار گرفته اند. البته نام فیلدها باید در مدل وجود داشته باشند. ** فراخوانی admin.site.register با اضافه کردن AuthorAdmin بعد از Author تغییر کرده است که می توان آنرا بدین صورت خواند: "مدل Author با امکانات AuthorAdmin عضو شده است." تابع admin.site.register() کلاس فرزند ModelAdmin را به صورت اختیاری به عنوان دومین آرگومان دریافت می کند. در صورتیکه دومین آرگومان را تعیین نکنید (همانطور در مورد Publisher و Book صدق می کند)، جنگو از اختیار پیشفرض مدیر برای آن مدل استفاده می کند. با تغییرات فوق، لیست تغییر نویسنده را دوباره بارگذاری کنید، شما حالا در این صفحه سه ستون را مشاهده خواهید کرد – نام، نام خانوادگی و آدرس الکترونیک. علاوه بر آن، هر کدام از این ستون ها قابلیت چیدمان بر اساس سرتیتر ستون را با کلیک کردن رو آن خواهند داشت. در قدم بعدی اجازه دهید یک نوار جستجوی ساده اضافه کنیم. مانند زیر search_fields را به AuthorAdmin اضافه کنید: class AuthorAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'email') search_fields = ('first_name', 'last_name') صفحه را درون مرورگر دوباره بارگذاری کنید، شما باید یک نوار جستجو را در قسمت بالای صفحه مشاهده کنید (شکل 10-6). در کد فوق تنها به صفحه ی تغییر گفته شده است که یک نوار جستجو برای جستجو بر حسب فیلدهای نام و نام خانوادگی ایجاد کند. همانطور که ممکن است کاربر انتظار داشته باشد، جستجو به حروف کوچک و بزرگ حساس نمی باشد و درون هر دو فیلد صورت می گیرد، بنابراین برای رشته ی "bar" هم نویسنده ای که نام وی Barney بوده را خواهد یافت و هم نویسنده ای که نام خانوادگی وی Hobarson می باشد را خواهد یافت. در قدم بعدی، اجازه دهید تعدادی فیلتر برای صفحه ی لیست تغییر مدل Book اضافه کنیم: from django.contrib import admin from mysite.books.models import Publisher, Author, Book class AuthorAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'email') search_fields = ('first_name', 'last_name') class BookAdmin(admin.ModelAdmin): list_display = ('title', 'publisher', 'publication_date') list_filter = ('publication_date',) admin.site.register(Publisher) admin.site.register(Author, AuthorAdmin) admin.site.register(Book, BookAdmin) در کد فوق با آیتم های زیادی سر و کار داریم، در کد فوق یک کلاس BookAdmin از نوع ModelAdmin به طور جداگانه ساخته شده است. ابتدا، یک list_display تنها برای ایجاد لیست زیباتر تعریف شده است. سپس، از list_filter استفاده شده است، که فیلدهایی برای استفاده را درون تاپل قرار می دهد و در سمت راست صفحه ی تغییر لیست نمایش داده می شود. برای فیلدهای تاریخ، جنگو میانبرهایی را برای فیلتر لیست می کند "Today"، "Past 7 days"، "This month"و "This year". list_filter فقط محدود به DateField نمی باشد بلکه با داده های نوع دیگر نیز کار می کند. (سعی کنید با فیلدهای BooleanField و foreignKey هم کار کنید) فیلترها تا زمانیکه حداقل دو مقدار برای انتخاب فرم وجود داشته باشد نمایش داده می شوند. روش دیگربرای ارائه ی فیلترهای تاریخ استفاده از date_hierarcy مانند کد زیر می باشد: class BookAdmin(admin.ModelAdmin): list_display = ('title', 'publisher', 'publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' با اضافه کرد date_hierarchy صفحه ی لیست تغییر یک نوار تاریخ در بالای لیست ایجاد می شود، که در شکل 12-6 مشاهده می کنید، که با یک لیست از سال های در دسترس شروع می کند سپس می توان برای ماه حتی نمایان شدن روز بر روی آن کلیک کرد. توجه داشته باشید که date_hierarchy یک رشته دریافت می کند، نه یک تاپل، زیرا تنها یک فیلد تاریخ می تواند در آن استفاده شود. در پایان، اجازه دهید ترتیب چیدمان پیشفرض لیست را به طوری تغییر دهیم که کتاب ها در صفحه ی لیست تغییر همیشه بر اساس تاریخ به صورت نزولی قرار بگیرند. به طور پیشفرض، لیست تغییر شیء ها را بر اساس کلاس Meta مربوط به مدل مودر نظر چیده می شوند (که در آموزش مدل جنگو به آن اشاره شده است.) – ولی شما این مقدار مرتب کردن را تعیین نکرده اید، پس ترتیب تعریف نشده است. class BookAdmin(admin.ModelAdmin): list_display = ('title', 'publisher', 'publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) این اختیار چیدمان مدیر دقیقا به صورت چیدمان در کلاس Meta کار می کند، با این تفاوت که آن تنها از اولین فیلد نام در لیست استفاده می کند. تنها یک لیست یا تاپل از نام فیلدها به آن ارسال کنید و یک علامت (-) در ابتدای فیلد برای چیدمان نزولی آن قرار دهید. صفحه ی لیست تغییر را برای مشاهده ی حرکت فوق دوباره بارگذاری کنید. توجه داشته باشید که تیتر "Publication date" حالا شامل یک فلش کوچک می باشد که به نحوه ی چیدمان اشاره می کند. اختیارات اصلی لیست تغییر در اینجا توضیح داده شد. با استفاده از این اختیارات می توانید با قدرت تر کار کنید، با استفاده از تنها چند خط می توانید از یک رابط آماده و پر قدرت استفاده کنید. سفارشی کردن فرم های ویرایش همانطور که لیست تغییر می تواند سفارشی شده باشد، فرم های ویرایش نیز می توانند با روش های مختلف سفارشی شوند. ابتدا اجازه دهید روش چیده شدن فیلدها را سفارشی کنیم. به طور پیشفرض، ترتیب فیلدها در یک فرم ویرایش مطابق با ترتیبی است که آنها در مدل تعریف شده اند. می توان با استفاده از اختیار fields در کلاس فرزند ModelAdmin آن را تغییر داد: class BookAdmin(admin.ModelAdmin): list_display = ('title', 'publisher', 'publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) fields = ('title', 'authors', 'publisher', 'publication_date') بعد از تغییر فوق، فرم ویرایش برای کتاب ها از ترتیب داده شده برای فیلدها استفاده خواهد کرد. این که نویسنده بعد از عنوان کتاب قرار بگیرد کمی طبیعی تر می باشد. البته، ترتیب فیلد باید بسته به به اطلاعات ورودی جریان کار باشد. هر فرم متفاوت است. نکته ی دیگر مفید در اختیار fields این است که اجازه می دهد بعضی فیلد ها را از قرار داشتن در فرم ویرایش کلا محروم کرد. تنها کافیست، فیلدهایی که نمی خواهید در فرم باشند را درون تاپل قرار ندهید. ممکن است از این امکان هنگامی که کاربران مدیر تنها برای ویرایش بعضی از بخش ها مورد اعتماد هستند استفاده کنید. برای مثال، در پایگاده داده ی کتاب ما، فیلد publication_date از حالت قابل ویرایش بودن خارج و مخفی شده است: class BookAdmin(admin.ModelAdmin): list_display = ('title', 'publisher', 'publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) fields = ('title', 'authors', 'publisher') نتیجتا، فرم ویرایش برای کتاب ها هیچ روشی برای تعیین publication date ارائه نمی کند. این حرکت می تواند در صورتیکه یک ویرایشگر ترجیح می دهد نویسندگانش تاریخ را عقب نزنند مفید باشد. هنگامی که یک کاربر از این فرم برای اضافه کردن یک کتاب جدید استفاده می کند، جنگو به آسانی مقدار publication_date را None در نظر می گیرد – بنابراین اطمینان حاصل کنید که فیلد مورد نظر دارای null=True می باشد. استفاده ی عمومی دیگر فرم ویرایش سفارشی برای کار با فیلدهای چند به چند می باشد. همانطور که در فرم ویرایش برای کتاب ها مشاهده کردید، سایت مدیر هر ManyToManyField را به صورت یک جعبه ی چند انتخابه نمایش می دهد، که منطقی ترین راه برای ورودی HTML برای استفاده می باشد – ولی استفاده از جعبه های چند انتخابه می تواند کمی سخت باشد. در صورتیکه که می خواهید چند ایتم را انتخاب کنید، باید برای انجام چنین کاری کلید control و یا در Mac کلید command را نگه پایین نگه داشته و آن ها را انتخاب کنید. سایت مدیر برای این مشکل یک توضیحی را در زیر این فیلد قرار داده است، ولی هنوز هم دارای مشکلاتی می باشد مخصوصا زمانی که فیلد شما حاوی صدها انتخاب باشد. راه حل سایت مدیر filter_horizontal می باشد. آنرا به BookAdmin اضافه کرده و نتیجه را مشاهده کنید: class BookAdmin(admin.ModelAdmin): list_display = ('title', 'publisher', 'publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) filter_horizontal = ('authors',) فرم ویرایش برای کتاب ها را دوباره بارگذاری کنید، بخش "Authors" حالا از یک رابط جاوا اسکریپت کاراتر استفاده می کند که می توان به راحتی درون انتخاب ها جستجو کردن و هر آنچه را که درون "Available authors" انتخاب می کنید را به درون "Chosen authors" و بر عکس ارسال می کند. اکیدا توصیه می شود که برای فیلدهای ManyToManyField که بیشتر از 10 ایتم دارند از filter_horizontal استفاده کنید. روش فوق بسیار آسانتر از استفاده از جعبه ی چند انتخابه می باشد. توجه داشته باشید که همچنین می توان برای چندین فیلد نیز از filter_horizontal استفاده کرد – تنها کافیست نام هر کدام را درون تاپل قرار دهید. کلاس های ModelAdmin همچنین از filter_vertical که تنها در فیلدهای ManyToManyField و نه ForeignKey کار می کند نیز پشتیبانی می کنند، به طور پیشفرض، سایت مدیر برای فیلدهای ForeignKey به سادگی از <select> استفاده می کند، ولی همانطور که برای ManyToManyField نیز از <select> استفاده می شود، ممکن است شما مایل نباشید برای نمایش تمام شیء ها به صورت منوی باز شونده در پایین بار اضافی ای را متحمل شوید. برای مثال در صورتیکه پایگاه داده ی کتاب حاوی صدها ناشر شده باشد، فرم "Add book" مدتی برای بارگذاری زمان خواهد برد، زیرا باید تمام ناشران را برای نمایش در <select> بارگذاری کند. برای حل این مشکل می بایست از raw_id_fields استفاده کرد. نام فیلد ForeignKey را درون این تاپل قرار دهید، فیلدهای مذکور به جای <select> به صورت یک متن ساده نمایش داده می شوند (<input type="text") class BookAdmin(admin.ModelAdmin): list_display = ('title', 'publisher', 'publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) filter_horizontal = ('authors',) raw_id_fields = ('publisher',) درون جعبه ی ورودی چه چیزی وارد می کنید؟ ID مربوط به پایگاه داده ی ناشر. نمی توان به طور عادی ID هر شخص را به خاطر سپرد، به همین دلیل یک شکل ذره بین نیز در شکل فوق مشاهده می کنید که می توان با کلیک بر روی آن توسط یک پنجره ی pop-up ناشران را که می خواهید اضافه کنید. کاربران، گروه ها و حق دسترسی ها بدلیل اینکه با یک superuser وارد می شویم، می توان برای ساختن، ویرایش و حذف کردن هر شیء اقدام کرد. به طور طبیعی، محیط های مختلف نیازمند حق دسترسی های متفاوتی می باشد – بدین صورت نباید باشد که هر شخصی بتواند superuser باشد. سایت مدیر جنگو یک سیستم حق دسترسی را بکاربرده است که می توان برای دادن دسترسی به کاربران خاص برای بخش هایی ار رابط که مورد نیاز است استفاده کرد. همانطور که در اوایل فصل مشاهده کردیم می توان کاربران و حق دسترسی ها را از طریق رابط مدیر همانند دیگر شیء ها ویرایش کرد. شیء های کاربر دارای فیلد های استاندارد نام کاربری، رمز عبور، آدرس پست الکترونیک و نام واقعی به همراه یک مجموعه از فیلد ها که اختیارات کاربر را در درون رابط مدیر تعیین می کند، می باشد. در ابتدا، سه گزینه ی boolean وجود دارد: ** گزینه ی "active" کنترل می کند که ایا کاربر فعال است یا خیر. در صورتیکه این گزینه تیک نخورده باشد و کاربر سعی کند وارد شود، به وی اجازه ی ورود داده نمی شود حتی اگر رمز عبور وی معتبر باشد. ** گزینه ی "staff" کنترل می کند که ایا کاربر اجازه ی ورود به رابط مدیر را دارد یا خیر (مانند اینکه ایا کاربر مورد نظر به عنوان یکی از کارمندان شرکت در نظر گرفته شده است یا خیر). ** گزینه ی "superuser" به کاربر دسترسی کامل را برای اضافه، ساختن و حذف کردن هر ایتم در رابط مدیر را می دهد. در صورتیکه یک کاربر این گزینه را داشته باشد، در آن صورت تمام قوانین دسترسی برای آن کاربر نقض خواهد شد. کاربران مدیر "Normal"، کاربر superuser نیستند بلکه دارای دسترسی مدیر از طریق دسترسی های اختصاص داده شده به آنها می باشند که می تواند شامل محدودیت های دسترسی باشد. هر شیء قابل ویرایش از طریق رابط مدیر (مانند کتاب ها، نویسندگان، ناشران) دارای سه حق دسترسی می باشد: حق دسترسی ساخت، حق دسترسی ویرایش و حق دسترسی حذف. اختصاص دادن حق دسترسی ها به یک کاربر، محدوده اختیارات آن کاربر را برای ایجاد، حذف و یا اعمال تغییرات تعیین می کند. زمانیکه یک کاربر می سازید، کاربر ساخته شده هیچ حق دسترسی ای ندارد، و برای دادن حق دسترسی های خاص حاضر می باشد. برای مثال، شما می توانید حق دسترسی ای برای تغیییر ناشران به آن بدهید، ولی حق حذف کردن ناشران را به کاربر ندهید. توجه داشته باشید که این حق دسترسی ها برای هر مدل تعریف شده می باشند و نه برای هر شیء، بنابراین شما می توانید اینطور بگویید که "john می تواند روی هر کتاب تغییر ایجاد کند"، ولی نمی توان گفت "john می تواند بر روی هر کتابی که با Apress منتشر شده است تغییرات ایجاد کند." قابلیت دوم، حق دسترسی های هر شیء می باشد که کمی پیچیده تر بوده و خارج از حوصله ی این کتاب می باشد ولی در مستندات جنگو درباره ی آن صحبت شده است. نکته : دسترسی به ویرایش کاربران و حق دسترسی ها نیز از طریق سیستم حق دسترسی کنترل شده است. در صورتیکه به شخصی حق دسترسی برای ویرایش کاربران را بدهید، آن شخص قادر به ویرایش حق دسترسی های خود می باشد که این ممکن است آن چیزی نباشد که شما می خواهید! دادن حق دسترسی کاربر برای ویرایش کاربران اساسا تغییر کاربر به superuser می باشد. همچنین می توان کاربران را به گروه ها اختصاص داد. گروه مجموع ای از حق دسترسی هایی می باشد که برای تمام اعضای آن گروه بکار برده می شود. گروه ها برای دادن حق دسترسی های یکسان به زیرمجموعه ای از کاربران مفید می باشد. چه زمانی و به چه دلیل از رابط مدیر استفاده می شود و چه زمانی استفاده نمی شود بعد از آشنایی و کار در این فصل، شما باید یک ایده ی خوب در مورد نحوه ی استفاده از سایت مدیر جنگو داشته باشید. ولی می خواهیم در اینجا چند موضوع را باز کنید و آن هم این است که چرا و کی باید از سایت مدیر جنگو استفاده کرد و چه زمانی نباید از آن استفاده کرد. سایت مدیر جنگو زمانی بسیار پر ارزش می شود که کاربران غیر فنی به وارد کردن داده نیاز داشته باشند، در روزنامه جایی که جنگو اولین توسعه را در آنجا پیدا کرد یک گزارش ویژه در مورد کیفیت آب شهری که چیزی شبیه به مراحل زیر بود، ارائه شده بود: ** گزارشگر مسئولیت داشت برای پروژه با یکی از توسعه دهندگان ملاقات کند و داده ی در دسترس را توضیح دهد. ** توسعه دهنده مدل های جنگو را برای متناسب بودن با آن داده ها طراحی کرده سپس سایت مدیر را برای گزارشگر باز می کرد. ** گزارشگر سایت مدیر را بررسی کرده و کمبود ها و فیلدهای غیر اصلی را به آن اشاره می کرد، توسعه دهنده مکررا مدل ها را تغییر می داد. ** هنگامی که مدل ها مورد توافق قرار گرفت، گزارشگر شروع به وارد کردن داده با استفاده از سایت مدیر می کرد. هم زمان، برنامه نویس می تواند روی توسعه ی عمومی قسمت های views و template ها کار کند (قسمت جالب کار). ورای وظایف واضح برای وارد کردن داده، سایت مدیر در موارد دیگر که در زیر آمده است نیز مفید می باشد: ** بررسی کردن داده ی مدل ها: هنگامی که تعدادی مدل تعریف می کنید، فراخوانی آن ها در رابط مدیر و وارد کردن برخی داده های ساختگی می تواند کاملا مفید باشد. در برخی موارد، می تواند باعث آشکار شدن اشتباهات data-modeling و یا مشکلات دیگر با مدل های شما شود. ** مدیریت داده ی بدست آمده: برای برنامه هایی که بر روی آمدن داده از منابع بیرونی تکیه دارند، سایت مدیر روشی ساده برای بازرسی یا ویرایش این داده ها به شما می دهد. ممکن است آن را کم قدرت تصور کنید، ولی بسیار مناسب تر از امکان خط فرمان پایگاه داده ی شما می باشد. ** مدیریت داده ی app ها به صورت سریع: می توان برای ساخت مدیریت داده ی بسیار سبک app از سایت مدیر استفاده کرد. در صورتیکه که تنها می خواهید برای نیازهای خود چیزی بسازید، نه برای مصارف عمومی، سایت مدیر می تواند راه مناسبی باشد. یک نکته ی پایانی اینکه می خواهیم واضح باشد: سایت مدیر برای همه وقت و همه چیز نیست. سایت مدیر برای یک رابط عمومی بودن در نظر گرفته نشده است، همچنین برای چیدمان و جستجوی پیچیده ی داده ها نیز در نظر گرفته نشده است. همانطور پیش تر در این فصل گفته شد، سایت مدیر برای مدیران مورد اعتماد سایت می باشد. خسته نباشید دوستان عزیز . جلسه ششم بخش دوم کتاب جنگو به پایان رسید . امیدوارم که موفق باشید . ترجمه از سایت www.djangobook.com
  4. آموزش مدل ها در جنگو در آموزش view و urlconf جنگو، اصول ساختن وب سایت های پویا در جنگو (Django) شرح داده شد به عبارت دیگر اصول راه اندازی view ها و URLconf ها را بررسی کردیم. همانطور که توضیح داده شد، view مسئولیت انجام برخی منطق های اختیاری و برگرداندن یک پاسخ را به عهده دارد. در یکی از مثال ها، منطق اختیاری، محاسبه کردن زمان و تاریخ فعلی بود. در برنامه های وب پیشرفته، منطق اختیاری اغلب درگیر تعامل با یک پایگاه داده می باشد. در پشت صحنه، یک وب سایت پایگاه داده محور، وب سایت به یک سرور پایگاه داده متصل می شود، برخی داده ها را از درون آن بازیابی می کند و آن داده ها را درون یک صفحه ی وب نمایش می دهد. یک سایت همچنین ممکن است روش هایی برای بازدیدکنندگان سایت تهیه کند تا بتوانند محتویات پایگاه داده را برای خودشان افزایش دهند. بسیاری از وب سایت های پیچیده یک سری ترکیب از دو موضوع را تهیه می کنند. به عنوان نمونه Amazon.com، یک مثال عالی برای یک سایت پایگاه داده محور می باشد. هر صفحه ی محصول اساسا یک پرس وجو (Query) قالب بندی شده به صورت HTML، درون پایگاه داده ی محصول آمازون می باشد و هنگامی که شما یک بررسی مشتری را ارسال می کنید، آن بررسی ها درون پایگاه داده درج می شوند. جنگو برای ساختن وب سایت های پایگاه داده محور مناسب می باشد، زیرا جنگو (Django) با استفاده از پایتون (Python) ابزار قدرتمندی را برای اجرای پرس و جوهای پایگاه داده ایجاد کرده است. در این فصل به عملکرد لایه ی پایگاه داده ی جنگو پرداخته می شود. (نکته: بهتر است با تئوری های پایگاه داده ی relational و SQL تاحدودی آشنا باشید. آشنا سازی برای این مفاهیم خارج از حوصله ی این کتاب می باشد، ولی حتی اگر شما یک کاربر جدید پایگاه داده می باشید باز هم این کتاب را بخوانید. ممکن است بتوانید مفاهیم و اصول اولیه پایگاه داده را درک کنید.) روش اولیه ی اجرای پرس و جوهای پایگاه داده در view ها همانطور که در آموزش view و urlconf جنگو توضیح داده شد، روش اولیه ی برای تولید خروجی درون یک view (از طریق نوشتن کد به طور مستقیم درون view) برای بازیابی داده از یک پایگاه داده درون یک view می باشد. این روش ساده می باشد زیرا فقط نیاز به استفاده از کتابخانه ی پایتون برای اجرای یک پرس و جوی SQL و کار با نتایج بدست آمده می باشد. در مثال view زیر، از کتابخانه ی MySQLdb (قابل دسترس از طریق آدرس http://wwww.djangoproject.com/r/python-mysql/ استفاده شده است. برای اتصال به پایگاه داده MySQL، بازیابی برخی رکوردها و پر کردن آن برای یک template جهت نمایش به صورت یک صفحه ی وب: from django.shortcuts import render_to_response import MySQLdb def book_list(request): db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT name FROM books ORDER BY name') names = [row[0] for row in cursor.fetchall()] db.close() return render_to_response('book_list.html', {'names': names}) روش فوق می تواند جوابگوی نیاز ما باشد، اما معایبی دارد که در ادامه به آنها اشاره شده است: ** پارامترهای connection پایگاه داده به صورت مستقیم درون کد قرار گرفته اند. ایده آل آن است که، این پارامترها درون پیکربندی جنگو ذخیره شوند. ** تعداد زیادی کد تکراری مانند ساختن connection، ساختن cursor، اجرا کردن جملات و بستن connection در مثال فوق وجود دارد. برای بهره وری مناسب تر ایده آل آن است که تنها نیازمند تعیین نتایج مورد نیاز برنامه باشیم. ** روش فوق برنامه نویس را به MySQL گره می زند. در صورتیکه برنامه نویس بخواهد پایگاه داده ی خود را تغییر دهد، به عنوان مثال، اگر بخواهد بجای MySQL از PostgreSQL استفاده کند، می بایست از یک adapter پایگاه داده ی متفاوت (psycopg به جای MySQLdb)، پارامتر های connection دیگر و همچنین بسته به ذات پایگاه داده، از جملات SQL متفاوت دیگر استفاده کرد. ولی همانطور که قبلا هم اشاره کردیم ایده آل آن است که، در صورت تغییر پایگاه داده، برنامه نویس دیگر نگران تغییر جملات و ... نباشد. همانطور که انتظار داریم، لایه ی پایگاه داده ی جنگو راه حلی برای حل این مشکلات ارائه کرده است. مثال زیر کد بازنویسی شده ی قبلی را با استفاده از API پایگاه داده ی جنگو نشان می دهد: from django.shortcuts import render_to_response from mysite.books.models import Book def book_list(request): books = Book.objects.order_by('name') return render_to_response('book_list.html', {'books': books}) کد فوق کمی بعد در همین فصل شرح داده خواهد شد. تنها برای حالا کافی است دید کلی نسبت به این API پیدا کنید. الگوی توسعه ی MTV (یا MVC) تاکنون در این کتاب، همواره به درون کد تمرکز شده است، اجازه دهید برای لحظاتی به بررسی یک برنامه ی وب پایگاه داده محور جنگو بپردازیم. همانطور که در فصل گذشته بیان شد، جنگو به نحوی طراحی شده است که برنامه نویس را تشویق کند تا اصول loose coupling و جداسازی بین قسمت های یک برنامه را رعایت کند. در صورتیکه این فلسفه را دنبال کنید، ایجاد تغییرات در یک قسمت مشخص از برنامه هیچ تاثیری بر روی قسمت های دیگر برنامه نخواهد داشت. برای نمونه در توابع view، اهمیت جداسازی منطق برنامه از قسمت ظاهر برنامه با استفاده از template توضیح داده شد. در لایه ی پایگاه داده، همین فلسفه را برای دسترسی به داده بکار خواهیم برد. این سه قسمت با یکدیگر (دسترسی به داده، منطق برنامه و ظاهر برنامه) یک مفهومی را در بر دارد که الگوی Model-View-Controller (MVC) از معماری نرم افزار نامیده می شود. در این الگو، Model به لایه ی دسترسی داده اشاره می کند، View به بخشی از سیستم که به انتخاب آنچه را که باید نمایش دهد و اینکه چطور باید آن را نمایش دهد اشاره می کند و Controller به بخشی از سیستم که بسته به ورودی کاربر تصمیم می گیرد کدام view باید استفاده شود اشاره دارد. چرا از شکل مخفف استفاده می شود؟ هدف از تعریف کردن الگوها بن شکل مخفف مانند MVC، غالبا برای ساده تر کردن صحبت و مکاتبه بین توسعه دهندگان می باشد. بجای آنکه به همکارتان بگویید؛ "بیا یک دسترسی داده بسازیم، سپس بیا جدا کنیم لایه ها را برای کنترل نمایش آن ها، و بعد از آن بیا یک لایه در میان آن قرار دهیم که آن را تنظیم و مرتب کند." می توانید از این خصوصیت استفاده کرده و بگویید؛ "بیا در اینجا از الگوی MVC استفاده کنیم." جنگو الگوی MVC را به اندازه ی کافی از نزدیک دنبال می کند به طوری که می توان آن را یک فریم ورک MVC نامید. در زیر نحوه ی تقسیم بندی M، V و C به درون جنگو را مشاهده می کنید: M، بخش دسترسی به داده می باشد که توسط لایه پایگاه داده جنگو کنترل می شود و در این فصل توضیح داده خواهد شد. V، انتخاب داده برای نمایش و نحوه ی نمایش آن، که با view ها و template ها کنترل شده است. C، بخشی که توسط خود فریم ورک کنترل می شود، بدینصورت که با توجه به URLconf مشخص شده تابع پایتون مناسب برای URL داده شده را فراخوانی می کند. به دلیل آنکه C ("Controler") توسط خود فریم فرک کنترل می شود و بیشترین تحرکات در models ،template و view ها اتفاق می افتد، جنگو به صورت یک فریم ورک MTV نیز شناخته می شود. در الگوی توسعه ی MTV: M مخفف "Model"، لایه ی دسترسی داده می باشد. این لایه حاوی همه اطلاعات درباره ی داده یعنی نحوه ی دسترسی به داده، نحوه ی معتبر ساختن داده، رفتارهایی که داده دارد و ارتباط بین داده می باشد. T مخفف "Template"، لایه ی نمایش می باشد. این لایه حاوی مسائلی درباره ی نحوه ی نمایش می باشد: این که اطلاعات باید به چه نحوی روی یک صفحه ی وب و یا سند دیگر نمایش داده شود. V مخفف "view"، لایه ی منطق برنامه می باشد. این لایه حاوی منطق برنامه برای دسترسی به model و ارائه ی به template مناسب می باشد. می توانید این لایه را به صورت پلی بین model ها و template ها تصور کنید. در صورتیکه با فریم ورک های دیگر توسعه ی وب مانند Ruby on Rails کار کرده باشید، ممکن است تصور کنید view های جنگو نقش "Controller" را بازی می کنند و template ها هم در حکم "views" می باشند. همچین تفسیری درباره ی MVC مایه ی تاسف می باشد. تفسیر جنگو نسبت به MVC، این است که "view" ارائه دادن داده به کاربر را شرح می دهد، این لزوما تنها ظاهر داده نمی باشد، بلکه منظور داده ی ارائه شده می باشد. در مقابل، Ruby on Rails و فریم ورک های مانند آن پیشنهاد می کنند که تصمیم گیری درباره ی اینکه کدام داده باید به کاربر ارائه داده شود از جمله وظایف controller می باشد، در حالیکه، ظاهر داده به طور موکد بر عهده ی view می باشد. پیکربندی پایگاه داده با در نظر گرفتن تمام فلسفه های گفته شد، اجازه دهید کار با لایه ی پایگاه داده ی جنگو را شروع کنیم. در ابتدا، نیاز به تعدادی پیکر بندی اولیه می باشد، در واقع بایستی به جنگو گفته شود که از کدام سرور پایگاه داده استفاده خواهد کرد و به چه صورت به آن متصل خواهد شد. فرض بر این است که سرور پایگاه داده نصب و فعال شده است، و همچنین یک پایگاه داده درون آن ساخته شده است (به عنوان مثال، با استفاده از دستور CREATE DATABASE STATEMENT). در صورتیکه از SQLite استفاده می کنید، به هیچگونه نصب نیاز نخواهد بود، زیر SQLite از فایل های مستقلی روی سیستم برای ذخیره ی داده های خود استفاده می کند. درست مانند TEMPLATE_DIRS که در فصل گذشته استفاده شد، پیکربندی مربوط به پایگاه داده نیز درون فایل settings می باشد: DATABASE_ENGINE = '' DATABASE_NAME = '' DATABASE_USER = '' DATABASE_PASSWORD = '' DATABASE_HOST = '' DATABASE_PORT = '' توجه داشته باشید برای استفاده از هر کدام نیاز به دانلود و نصب adapter مناسب خود می باشد. هر کدام از پایگاه های داده ی فوق به صورت آزاد درون وب در دسترس می باشند؛ تنها کافیست به سایت مورد نظر که درون جدول 1-5 آمده است مراجعه کرده آن را دانلود کنید. در صورتیکه با سیستم عامل لینوکس کار می کنید، package-management سیستم شما ممکن است package های مناسبی را ارئه دهد. (برای مثال به دنبال package هایی با نام python-postgresql یا python‑psycopg بگردید.) مثال: DATABASE_ENGINE = 'postgresql_psycopg2' DATABASE_NAME نام پایگاه داده ی شما را به جنگو اطلاع می دهد: DATABASE_NAME = 'mydb' در صورتیکه از SQLite استفاده می کنید، آدرس کامل پایگاه داده ی خود را درون این تنظیم قرار دهید: DATABASE_NAME = '/home/django/mydata.db' DATABASE_USER نام کاربری که برای اتصال به پایگاه داده لازم است را به جنگو اطلاع می دهد. DATABASE_PASSWORD رمز عبوری که برای اتصال به پایگاه داده لازم است را به جنگو اطلاع می دهد. در صورتیکه از SQLite استفاده می کنید یا اینکه می خواهید پسوردی در نظر نگیرید، می توانید آن را خالی بگذارید. DATABASE_HOST host مورد نظری که برای اتصال به پایگاه داده لازم است را به جنگو اطلاع می دهد. در صورتیکه پایگاه داده ی شما همانند نصب جنگو در یک رایانه می باشد (مانند localhost) آن را خالی بگذارید. همچنین اگر از SQLite استفاده می کنید نیز می توانید آن را خالی بگذارید. MySQL در اینجا یک مورد خاص می باشد. در صورتیکه مقدار این تنظیم (DATABASE_HOST) با علامت (/) شروع شود و شما از MySQL استفاده کنید، MySQL از طریق یک Unix socket برای socket تعیین شده متصل خواهد شد: DATABASE_HOST = '/var/run/mysql' هنگامی که تنظیمات فوق را انجام داده و فایل settings.py ذخیره کردید، ایده ی خوب است که پیکربندی انجام شده را مورد آزمون قرار دهید. برای انجام این کار، مانند فصل گذشته درون دایرکتوری پروژه ی mysite دستور python manage.py shell را اجرا کنید. (همانطور که در فصل گذشته اشاره شد دستور manage.py shell روشی برای اجرای interpreter پایتون، با تنظیمات صحیح فعال شده ی جنگو می باشد. در این مورد این ضروری است، زیرا نیاز است جنگو تنظیمات فایل را به منظور به دست آوردن اطلاعات connection پایگاه داده برای استفاده بداند.) درون خط فرمان، دستورات زیر را به منظور آزمودن پیکربندی پایگاه داده تایپ کنید: >>> from django.db import connection >>> cursor = connection.cursor() ایجاد اولین App اکنون که مشخص شد اتصال به پایگاه داده با موفقیت انجام شده است، زمان آن رسیده است که یک app برای جنگو ایجاد کنیم، app یک بسته از کد جنگو می باشد که model ها و view ها در آن قرار می گیرد، که همگی با هم درون یک پکیج پایتون قرار گرفته اند و یک برنامه (application) جنگو را نمایش می دهند. در شروع کار جنگو نحوه ی ساختن یک پروژه ی جنگو توضیح داده شد، اکنون فرق بین یک پروژه با یک app(اپلیکیشن)در چیست؟ تفاوت آن در پیکربندی در مقابل کد است: یک پروژه یک نمونه از یک مجموعه ی خاص از app های جنگو به همراه پیکربندی برای آن ها می باشد. از نظر فنی، تنها فرق اساسی که در پروژه وجود دارد ایجاد یک فایل settings می باشد، که اطلاعات connection پایگاه داده، لیست app های نصب شده، تنظیم TEMPLATE_DIRS و غیره را تعریف می کند. app یک دسته ی قابل حمل از عمکرد جنگو می باشد، که معمولا شامل model ها و view ها می باشد که با هم در یک پکیج پایتون قرار دارند. برای مثال، جنگو به همراه تعدادی از app ها، از قبیل سیستم کامنت و رابط خودکار مدیر، ارائه شده است، نکته ی قابل توجه درباره ی این app ها این است که، آن ها قابل حمل می باشند بدین معنی که می تواند آن ها را در چندین پروژه دیگر نیز دوباره استفاد کرد. مقدار بسیار کمی قوانین سخت و محکم نسبت به وفق دادن کد جنگو با این طرح وجود دارد. در صورتیکه بخواهید یک وب سایت ساده بسازید، ممکن است تنها از یک app استفاده کنید. و اگر می خواهید یک وب سایت بزرگ و پیچیده با چندین قسمت مرتبط به هم مانند یک سیستم تجارت الکترونیک و یک تابلوی پیام (message board) بسازید، احتمالا این قسمت ها را درون app ها جدا قرار خواهید داد، به طوری که قادر باشید در صورت نیاز آن ها را به صورت منحصر به فرد در اینده استفاده کنید. در واقع، لزوما همیشه نیاز به ساختن app ها در پروژه نیست، به عنوان نمونه توابع view که تاکنون ساخته شده است حاکی این موضوع می باشد. در آن مواردبه سادگی یک فایل views.py ساخته شده و با توابع view مورد نیاز درون آن پر می شد، و URLconf نیز به آن توابع اشاره می کرد. نیازی به app ها نبود. با این وجود، در یک صورت باید از app ها استفاده شود: در صورتیکه شما از لایه ی پایگاه داده ی (models) جنگو استفاده می کنید، باید یک app جنگو بسازید. model ها باید درون app ها ایجاد شوند. در نتیجه، به منظور ساختن model ها، نیزا به ساختن یک app جدید می باشد. درون دایرکتوری پروژه ی mysite، دستور زیر را برای ساختن app مورد نظر با نام books اجرا کنید: python manage.py startapp books دستور فوق هیچ خروجی ای را تولید نمی کند، در عوض دایرکتوری books را درون دایرکتوری mysite می سازد. در زیر محتویات این دایرکتوری را مشاهده می کند: books/ __init__.py models.py tests.py views.py این فایل ها حاوی model ها و view ها برای این app می باشد. درون ویرایشگر متن مورد علاقه ی خود نگاهی به فایل های models.py و views.py بیاندازید. جفت فایل ها خالی هستند، به غیر از کامنت ها و یک import که درون فایل models.py قرار دارد. تعریف Model ها در پایتون همانطور که پیش تر در این فصل توضیح داده شد، "M" در "MTV" مخفف "Model" می باشد. model جنگو توصیف و شرح داده در پایگاه داده ی شما می باشد، که به صورت کد پایتون نمایش داده می شود. model لایه ی داده ی شما می باشد معادل عبارات SQL مانند CREATE TABLE با این تفاوت که این عبارات بجای SQL درون پایتون می باشند و همچنین آن ها شامل مواردی بیشتر از تعریف ستون های پایگاه داده می باشند. جنگو برای اجرای کد های SQL در پشت صحنه و برگرداندن ساختارهای داده ی پایتون مناسب از model ها استفاده می کند که از طریق آن ها ردیف های جداول پایگاه داده را نمایش می دهد. جنگو همچنین از model ها برای نمایش مفاهیم سطح بالا که SQL لزوما قادر به کنترل آن ها نمی باشد نیز استفاده می شود. در صورتیکه با پایگاه های داده آشنا می باشید، این تفکر برای شما ایجاد می شود که "آیا تعریف کردن data model ها بجای SQL درون پایتون کار زائد و اضافه ای نیست؟" جنگو به چندین دلیل به این روش عمل می کند: ** درون گرایی (استفاده از کد های SQL) مستلزم بار اضافی بوده و همچنین ناقص می باشد. به منظور تهیه ی API ها برای دسترسی به داده، جنگو به طریقی نیاز به شناختن لایه ی پایگاه داده دارد، و دو روش برای انجام آن وجود دارد. روش اول به طور واضح توضیح دادن داده در پایتون می باشد، و روش دوم تعیین data model ها درون پایگاه داده در هنگام اجرا می باشد. روش دوم تمیز تر به نظر می رسد، زیرا داده های جداول شما در یک جا می باشند، ولی این روش دارای مشکلاتی می باشد. اول اینکه تعیین داده های درون پایگاه داده در زمان اجرا بدیهی است که نیازمند یک بار اضافه خواهد بود. در صورتیکه فریم ورک در هر زمان بخواهد درون پایگاه داده اعمالی را انجام دهد خود به خود یک درخواست را پردازش کرده است، و یا حتی، در زمان اولیه وب سرور ممکن است یک بار اضافی در سطح غیر قابل قبول را متحمل شود. دوم آنکه برخی از پایگاه های داده، به ویژه نسخه های قدیمی MySQL، metadata مناسبی را به طور دقیق ذخیره نمی کنند. ** کد نویسی در پایتون لذت بخش می باشد، و نگه داشتن همه چیز در محدوده ی کد پایتون باعث می شود تعداد باری که شما را مجبور کند محیط کد نویسی را تغییر دهد کم می کند. این موضوع یعنی نگه داشتن برنامه نویس در یک محیط کد نویسی بهره وری و راندمان را تا حد امکان افزایش می دهد. نوشتن کد SQL و سپس پایتون و دوباره SQL کاری ذهنیت برنامه نویس را مختل خواهد کرد. ** داشتن data model های ذخیره شده به صورت کد بجای استفاده مستقیم از پایگاه داده، کنترل model هار بسیار آسان تر خواهد کرد. با این روش می توان به سادگی رد تغییرات در لایه های داده را دنبال کرد. ** SQL تنها اجازه ی استفاده از داده های قطعی موجود می دهد، اغلب سیستم های پایگاه داده، به عنوان مثال؛ داده های تخصصی برای نمایش دادن آدرس های email یا URL را تهیه نمی کنند. در صورتیکه model های جنگو این کار را انجام می دهند. مزیت داده های نوع سطح بالا بهره وری بیشتر آن ها و قابلیت دوباره استفاده شدن آن ها می باشد. ** SQL در پایگاه های داده ی مختلف یکجور نبوده و ناسازگار می باشد. بدین معنی که جملات و عبارت SQL برای مثال join ها و یا ... در پایگاه های داده ی مختلف مانند MySQL، PostgreSQL و یا SQLite ممکن است متفاوت از یکدیگر پیاده سازی شوند و هرکدام به روش خود آن را پیاده سازی کنند. تنها ایراد در این روش (استفاده از data model پایتون) این است که کدهای پایتون حالت همزمانی و موازات را به طور واقعی با پایگاه داده ندارند. در صورتیکه در model جنگو تغییر ایجاد کنید، نیاز می باشد که همان تغییرات را نیز درون پایگاه داده انجام دهید تا پایگاه داده با model شما سازگاری خود را حفظ کند. در ادامه ی این فصل استراتژی هایی توضیح داده خواهد شد که از طریق آن ها خواهید توانست این مشکلات را کنترل کنید. اولین Model شما برای داشتن مثالی که هم در این فصل و فصل بعدی بتوان از آن استفاده کرد و آن را پیشرفت داد، بر روی لایه ی داده ی book/author/publisher تمرکز خواهد شد. از این مثال به دلیل اینکه دارای رابطه های شناخته شده ای بین books، authors و publishers می باشد، و داده های استفاده شده داده های مقدماتی استفاده شده در SQL می باشد. داده های استفاده شده با خصوصیات زیر فرض شده اند: * یک نویسنده دارای یک نام، یک فامیلی و یک نشانی پست الکترونیک می باشد. * یک ناشر دارای یک نام، یک نشانی کوچه، یک شهر، یک استان، یک کشور و یک وب سایت می باشد. * یک کتاب دارای یک عنوان و یک تاریخ انتشار می باشد. همچنین هر کتاب دارای یک یا بیشتر نویسنده (رابطه ی چند به چند با authors) و یک ناشر (رابطه ی یک به چند به publishers) می باشد. اولین قدم برای استفاده کردن لایه ی پایگاه داده با جنگو، بیان آن به صورت کد پایتون می باشد. درون فایل models.py که با استفاده از دستور startapp ساخته شده است، کد زیر را وارد کنید: from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() اجازه دهید کد فوق را به طور اجمالی مورد بررسی قرار دهیم. اولین نکته ی قابل توجه این است که هر model به صورت یک کلاس پایتون نمایش داده شده است و هر model کلاس فرزند از کلاس پدر django.db.models.Model می باشد. کلاس پدر Model، حاوی تمام ابزار آلات ضروری برای ساختن شیء هایی می باشد که توانایی تعامل با یک پایگاه داده را داشته باشند. مشاهده می کنید که تعریف فیلدها به چه اندازه مختصر و ساده می باشند. باور کنید یا نه، این تمام کدی می باشد که برای داشتن دسترسی داده ی اولیه با جنگو لازم است. هر model عموما با یک جدول پایگاه داده و هر attribute در یک model با یک ستون جدول در پایگاه داده مطابق می باشد، نام attribute مطابق با نام ستون، و نوع فیلد (مانند CharField) مطابق با نوع ستون (مانند varchar) می باشد. برای مثال مدل Publisher برابر با جدول زیر می باشد (با فرض عبارت CREATE TABLE درون پایگاه داده ی PostgreSQL): CREATE TABLE "books_publisher" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(30) NOT NULL, "address" varchar(50) NOT NULL, "city" varchar(60) NOT NULL, "state_province" varchar(30) NOT NULL, "country" varchar(50) NOT NULL, "website" varchar(200) NOT NULL ); در واقع، جنگو می تواند عبارت CREATE TABLE را به صورت خودکار تولید کند که در کد فوق مشاهده کردید. در این قانون که برای هر جدول پایگاه داده، یک کلاس در نظر گرفته می شود، در مورد رابطه های چند به چند یک استثنا وجود دارد. در مثال مدل های فوق، Book دارای یک فیلد چند به چند با نام authors می باشد. این فیلد مشخص می کند که هر کتاب دارای یک یا چند نویسنده می باشد، در صورتیکه جدول پایگاه داده Book دارای ستونی به نام authors نمی باشد. در عوض، جنگو یک جدول اضافه می سازد (یک "join table" چند به چند) که رابطه بین کتاب ها و نویسندگان را کنترل می کند. در پایان، توجه داشته باشید که به طور صریح برای هر یک از مدل ها یک کلید اصلی (primary key) تعریف نشده است. جنگو به صورت خودکار برای هر مدل یک فیلد auto_incremen integer primary key ایجاد می کند که id نام دارد. هر مدل جنگو لازم است یک ستون primary key داشته باشد. نصب کردن Model کد مربوط به مدل ها نوشته شد، حالا اجازه دهید جدول ها را درون پایگاه داده نیز ایجاد کنیم. به منظور انجام این کار؛ قدم اول این است که مدل های ساخته شده درون پروژه جنگو را فعال کنیم. برای انجام این کار باید app مورد نظر یعنی books را به لیست "installed apps" درون فایل settings اضافه کنیم. فایل settings.py را دوباره باز کرده، و تنظیم INSTALLED_APPS را پیدا کنید. INSTALLED_APPS به جنگو می گوید که کدام app ها برای پروژه مورد نظر فعال هستند. به طور پیشفرض، این تنظیم به این شکل خواهد بود: INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', ) به طور موفت با گذاشتن علامت (#) در ابتدای هر کدام از رشته ها آن ها را کامنت کنید. (این رشته ها موارد کامنت شده ای برای راحتی کار می باشند که در فصل های بعدی آن ها را فعال کرده و در مورد آن ها بحث خواهیم کرد.) همچنین تنظیمات مربوط به MIDDLEWARE_CLASSES را نیز کامنت کنید؛ مقادیر پیشفرض در MIDDLEWARE_CLASSES به برخی از app هایی که ما آن ها را کامنت کردیم وابسته می باشند. سپس 'mysite.books'را به لیست INSTALLED_APPS اضافه کنید، در پایان تنظیم انجام داده شده چیزی شبیه به مثال زیر خواهد بود: MIDDLEWARE_CLASSES = ( # 'django.middleware.common.CommonMiddleware', # 'django.contrib.sessions.middleware.SessionMiddleware', # 'django.contrib.auth.middleware.AuthenticationMiddleware', ) INSTALLED_APPS = ( # 'django.contrib.auth', # 'django.contrib.contenttypes', # 'django.contrib.sessions', # 'django.contrib.sites', 'mysite.books', ) (همانطور که در فصل گذشته، هنگام تنظیم TEMPLATE_DIRS گفته شد، لازم است حتما یک علمت کاما (,) در انتهای mysite.books قرار دهید، زیرا mysite.books در اینجا یک تک المان تاپل پایتون می باشد، اتفاقا، نویسندگان این کتاب ترجیح می دهند بعد از هر المان تاپل، بدون در نظر گرفتن این که یک تک المان است یا خیر، یک کاما در انتهای آن قرار میدهند. این کار باعث می شود از فراموش کردن قرار دادن کاما در انتهای المان های تک تاپل جلوگیری شود، و گذاشتن کامای اضافه هیچ مشکلی به وجود نخواهد آورد.) 'mysite.books' به app ای که با کار می کنیم اشاره می کند. هر app ای که در تنظیم INSTALLED_APPS قرار دارد با آدرس کامل پایتون آن نمایش داده می شود (مسیر پکیج ها با نقطه جدا شده و به پکیج app هدایت می شوند.) اکنون که app مورد نظر در فایل settings فعال شد، می توانیم جداول پایگاه داده را درون پایگاه داده ایجاد کنیم. ابتدا، اجازه دهید با دستور زیر از معتبر بودن کد های برنامه اطمینان حاصل کنیم: python manage.py validate دستور validate بررسی می کند که ایا کدها و منطق مدل های نوشته صحیح می باشد یا خیر. در صورتیکه همه چیز درست باشد، شما پیام message 0 errors found را مشاهده خواهید کرد. در غیر اینصورت، اطمینان حاصل کنید کدهای مدل شما صحیح می باشد. خطای خروجی، اطلاعات مفیدی درباره ی ایراد موجود در کد، در اختیار شما می گذارد. هر زمان که تصور کردید مشکلاتی درون مدل ها وجود دارد، دستور python manage validate را اجرا کنید. دستور فوق به شما کمک می کند تا تمام مشکلات موجود در مدل را بر طرف کنید. در صورتیکه کد مربوط به مدل شما معتبر می باشد، دستور زیر را برای تولید عبارت های CREATE TABE مربوط به مدل ها در app مورد نظر (books) وارد کنید: python manage.py sqlall books در دستور فوق، books نام app می باشد. این نام همان چیزی است که شما با اجرای دستور manage.py startapp ایجاد کرده اید. هنگامی که شما دستور فوق manage.py sqlall books را اجرا می کنید چیزی شبیه به این را در خروجی مشاهده خواهید کرد: BEGIN; CREATE TABLE "books_publisher" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(30) NOT NULL, "address" varchar(50) NOT NULL, "city" varchar(60) NOT NULL, "state_province" varchar(30) NOT NULL, "country" varchar(50) NOT NULL, "website" varchar(200) NOT NULL ) ; CREATE TABLE "books_author" ( "id" serial NOT NULL PRIMARY KEY, "first_name" varchar(30) NOT NULL, "last_name" varchar(40) NOT NULL, "email" varchar(75) NOT NULL ) ; CREATE TABLE "books_book" ( "id" serial NOT NULL PRIMARY KEY, "title" varchar(100) NOT NULL, "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id") DEFERRABLE INITIALLY DEFERRED, "publication_date" date NOT NULL ) ; CREATE TABLE "books_book_authors" ( "id" serial NOT NULL PRIMARY KEY, "book_id" integer NOT NULL REFERENCES "books_book" ("id") DEFERRABLE INITIALLY DEFERRED, "author_id" integer NOT NULL REFERENCES "books_author" ("id") DEFERRABLE INITIALLY DEFERRED, UNIQUE ("book_id", "author_id") ) ; CREATE INDEX "books_book_publisher_id" ON "books_book" ("publisher_id"); COMMIT; به نکات زیر توجه کنید: ** نام جدول ها به طور خودکار با ترکیب نام app (books) و نام مدل (publisher، book و author) به صورت حروف کوچک تولید می شود. ** همانطور که پیش تر توضیح داده شد، جنگو برای هر جدول به طور خودکار یک کلید اصلی (با نام id) اضافه می کند. ** رابطه ی کلید خارجی با عبارت REFERENCES، صریح و روشن ساخته شده است. ** عبارت CREATE TABLE برای پایگاه داده ای که شما استفاده می کنید مناسب خواهد بود، بنابراین تعیین نوع فیلد مانند auto_increment (MySQL)، serial (PostgreSQL)، یا integer primary key (SQLite) به طور خودکار توسط جنگو انجام خواهد شد. همچنین در مورد کتیشن برای نام ستون ها (مانند استفاده از دابل کتیشن یا تک کتیشن) نیز این موضوع صدق می کند. مثال فوق خروجی برای PostgreSQL می باشد. دستور sqlall، در حقیقت جداول پایگاه داده را تولید نمی کند و به عبارت دیگر پایگاه داده نیز لمس نمی کند، تنها خروجی تولید شده توسط جنگو را به زبان SQL مورد نظر نشان می دهد بنابراین شما می توانید آنچه را که جنگو درون پایگاه داده می خواهد اجرا کند را مشاهده کنید. در صورت تمایل، می توانید این خروجی SQL را درون پایگاه داده ی کلاینت کپی کنید، یا با استفاده از علامت (|) یونیکس آن را به صورت مستقیم ارسال کنید (مانند python manage.py sqlall books | psql mydb). با این وجود، جنگو روشی ساده را برای ارسال خروجی تولید شده به پایگاه داده ارائه کرده است: دستور syncdb: python manage.py syncdb بعد از اجرای دستور فوق، خروجی شبیه به مثال زیر مشاهده خواهید کرد: Creating table books_publisher Creating table books_author Creating table books_book Installing index for books.Book model دستور syncdb یک هماهنگی ساده بین مدل ها و پایگاه داده می باشد. دستور فوق تمام مدل های موجود در هر app را درون تنظیم INSTALLED_APPS بررسی می کند، و در صورتیکه جدول مناسب برای مدل های مورد نظر وجود نداشته باشد آن ها را ایجاد می کند. توجه داشته باشید که syncdb تغییرات بوجود آمده در مدل ها و یا حذف مدل ها را با پایگاه داده هماهنگ نمی کند؛ در صورتیکه شما یک تغییر را در مدل ایجاد کرده و یا مدلی را حذف کنید، هنگامی که بخواهید پایگاه داده را با این تغییرات به روز رسانی کنید، دستور syncdb نمی تواند این کار را انجام دهد. (در انتهای همین فصل این موضوع بحث خواهد شد.) در صورتیکه که دستور python manage.py syncdb را دوباره اجرا کنید، اتفاقی رخ نخواهد داد، زیرا هیچ مدل به app مورد نظر (books) اضافه نشده است و یا هیچ app ای به تنظیم INSTALLED_APPS اضافه نشده است. بنابراین اجرای دستور python manage.py syncdb همواره مشکلی بوجود نخواهد آورد. در صورتیکه کنجکاو هستید، می توانید برای لحظاتی به درون خط فرمان پایگاه داده رفته جداول ایجاد شده درون پایگاه داده ی خود را مشاهده کنید. می توانید به صورت دستی دستوراتی را که می خوهید درون خط فرمان کلاینت اجرا کنید (مانند psql برای PostrgreSQL) یا اینکه می توانید دستور python manage.py dbshell، را اجرا کنید، و بسته به تنظیم DATABASE_SERVER، خواهید فهمید کدام خط فرمان اجرا می شود. شیوه ی دوم تقریبا همیشه مناسب تر می باشد. اصول اولیه ی دسترسی به داده هنگامی که شما یک مدل ساخته می شود، جنگو به طور خودکار یک API سطح بالا پایتون را برای کار با آن مدل ها ایجاد می کند. دستور python manage.py shell را اجرا کرده و کدهای زیر را امتحان کنید: >>> from books.models import Publisher >>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue', ... city='Berkeley', state_province='CA', country='U.S.A.', ... website='http://www.apress.com/') >>> p1.save() >>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.', ... city='Cambridge', state_province='MA', country='U.S.A.', ... website='http://www.oreilly.com/') >>> p2.save() >>> publisher_list = Publisher.objects.all() >>> publisher_list [<Publisher: Publisher object>, <Publisher: Publisher object>] چند خط کد فوق کار زیادی را انجام می دهند. نکات برجسته در کد فوق: ** ابتدا، مدل Publisher به import شده است. با این کار می توان با جدول پایگاه داده که حاوی اطلاعات ناشران می باشد در ارتباط بود. ** یک شیء Publisher با مقدار دهی مقدار دهی اولیه ی آن با مقادیری برای هر فیلد (name، address و غیره ...) ساخته شده است. ** برای ذخیره ی شیء درون پایگاه داده، متد save() آن فراخوانی شده است. در پشت صحنه، جنگو عبارت INSERT برای SQL را در اینجا اجرا می کند. ** برای بازیابی اطلاعات ناشران از پایگاه داده، از attribute مورد نظر Publisher.objects برای بدست آوردن مجموعه تمام ناشران استفاده شده است. لیست تمام شیء های Publisher با استفاده از عبارت Publisher.objects.all() واکشی شده است. در پشت صحنه جنگو یک عبارت SELECT را به صورت SQL در اینجا اجرا می کند. نکته ای با اهمیتی که در این مورد واضح و یا روشن به نظر نمی رسد اینکه، هنگامی که شما با استفاده از API مدل جنگو در حال ساختن شیء ها می باشید، جنگو تا وقتی که متد save() را فراخوانی نکنید شیء ها را درون پایگاه داده ذخیره نمی کند. p1 = Publisher(...) # At this point, p1 is not saved to the database yet! p1.save() # Now it is. در صورتیکه می خواهید یک شیء ساخته و آن را درون پایگاه داده با یک حرکت ذخیره کنید، می توانید از متد objects.create() استفاده کنید. مثال زیر با مثال قبلی برابر است: >>> p1 = Publisher.objects.create(name='Apress', ... address='2855 Telegraph Avenue', ... city='Berkeley', state_province='CA', country='U.S.A.', ... website='http://www.apress.com/') >>> p2 = Publisher.objects.create(name="O'Reilly", ... address='10 Fawcett St.', city='Cambridge', ... state_province='MA', country='U.S.A.', ... website='http://www.oreilly.com/') >>> publisher_list = Publisher.objects.all() >>> publisher_list به طور طبیعی می توانید کارهای بسیار زیادی را به استفاده از API پایگاه داده ی جنگو انجام دهید، اما در ابتدا با کارهای کوچک بسنده می کنیم. ‫اضافه كردن نمايش رشته اي براي مدل‬ هنگامی که لیستی از ناشران را چاپ می کنیم، خروجی مفیدی نمایش داده نمی شود و بخش های شیء به هیچ وجه قابل تشخیص نیستند: [<Publisher: Publisher object>, <Publisher: Publisher object>] می توان این مشکل را به راحتی با اضافه کردن متد __unicode__() به کلاس Publisher حل کرد. متد __unicode__() به پایتون می گوید که یک شیء را به چه شکل در خروجی نمایش دهد. می توانید نحوه ی استفاده از آن را در عمل با اضافه کردن یک متد __unicode__() درون سه مدل فوق مشاهده کنید: from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() def __unicode__(self): return self.name class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() def __unicode__(self): return u'%s %s' % (self.first_name, self.last_name) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return self.title همانطور که مشاهده می کنید، متد __unicode__() می تواند هر آنچه را که برای برای نمایش یک شیء نیاز است انجام دهید. در مثال فوق متدهای __unicode__() برای Publisher و Book به سادگی نام و عنوان شیء را به ترتیب برمی گردانند، ولی متد __unicode__() برای Author کمی پیچیده تر از بقیه می باشد، بدین صورت که فیلد های first_name و last_name را به یک فاصله به هم وصل کرده و بر می گرداند. تنها الزام برای متد __unicode__() این است که یک شیء یونیکد را بر می گرداند. در صورتیکه متد __unicode__() یک شیء یونیکد را بر نگرداند به عنوان مثال یک integer بر گرداند، در اینصورت پایتون خطای TypeError را با پیامی مانند "coercing to Unicode: need string or buffer, int found"ایجاد خواهد کرد. ‫آبجكت هاي يونيكد‬ شیء یونیکد چیست؟ می توانید بدین شکل تصور کنید که شیء یونیکد یک رشته ی پایتون است که می تواند با بیشتر از یک میلیون نوع محتلف حروف را کار کرده و آن ها را کنترل کند، از نسخه های حروف لهجه دار لاتین، حروف غیر لاتین گرفته تا نمادها و علامت های مبهم و نا مفهوم. رشته های معمولی پایتون رمزی شده (encoded) می باشند، بدین معنی که آن ها به صورت رمز شده مانند ASCII، ISO-8859-1 یا UTF-8 استفاده می شوند. در صورتیکه بخواهید حروف تجملی (هرچیزی خارج از 128 حرف ASCII مانند 0-9 و A-Z) را درون یک رشته ی معمولی پایتون ذخیره کنید، این حروف هنگام چاپ و یا نمایش به صورت به هم ریخته در می ایند. مشکلات زمانی رخ می دهند که شما داده ای را درون یک encoding ذخیره کرده و سعی می کنید آن را با یک encoding متفاوت دیگر ترکیب کنید و یا سعی می کنید آن را درون یک برنامه که دارای یک encoding مشخص می باشد نمایش دهید. همه ی ما صفحات وب و پست الکترونیکی را مشاهده کرده ایم که با حالت "??? ??????" و یا دیگر حروف خراب شده اند؛ این مشکلات عموما مشکلات encoding تلقی می شوند. شیء های یونیکد، اگر چه encoding ندارند؛ ولی آن ها از یک مجموعه از حروف جهانی و سازگار که "Unicode" نامیده می شوند استفاده می کنند. هنگامی که شما با شیء های یونیکد در پایتون سر و کار دارید، می توانید بدون هیچگونه نگرانی نسبت به مسائل encoding آن ها را با یکدیگر ترکیب و استفاده کنید. جنگو در سرتاسر فریم ورک از شیء های یونیکد استفاده می کند. شیء های مدل به صورت شیء های یونیکد بازیابی شده اند، view ها با داده ی یونیکد ارتباط برقرار می کنند و template ها به صورت یونیکد ارائه می شوند. عموما، توسعه دهندگان درون فریم ورک جنگو هیچگونه نگرانی نسبت به درست بودن encoding درون برنامه های نوشته شده توسط جنگو نخواهند داشت. توجه داشته باشید که سطح بالا بودن مطالب در اینجا باعث می شود که اطلاعات شما در مورد شیء های یونیکد کمی گمگ و مبهم باشد، در صورتیکه می خواهید می توانید در نشانی زیر مورد آن اطلاعات بیشتری کسب کنید. http://www.joelonsoftware.com/articles/Unicode.html برای اینکه تغییرات ایجاد شده درون مدل ها (اضافه کردن متد __unicode__()) اعمال شود، از shell پایتون خارج شده و با دستور python manage.py shell دوباره وارد آن شوید. (این ساده ترین راه برای اعمال تغییرات ایجاد شده می باشد) حالا لیست شیء های Publisher قابل فهم تر شده اند: >>> from books.models import Publisher >>> publisher_list = Publisher.objects.all() >>> publisher_list [<Publisher: Apress>, <Publisher: O'Reilly>] اطمینان حاصل کنید که تمام مدل های تعریف شده دارای متد __unicode__() می باشند، نه فقط برای راحتی خودتان هنگامی که از interactive interpreter استفاده می کنید، بلکه جنگو نیز در مکان های زیادی از خروجی __unicode__() برای نمایش شیء ها استفاده می کند. در پایان، توجه داشته باشید که __unicode__() یک مثال خوب برای اضافه کردن یک رفتار برای مدل ها می باشد. یک مدل جنگو بیشتر از جدول لایه پایگاه داده برای یک شیء توضیح می دهد؛ همچنین مدل جنگو هر عملکردی را که شیء نحوه انجام آن را می داند را توضیح دهد. __unicode__() یک مثال برای عملکرد می باشد بدین معنی که یک مدل نحوه ی نمایش خود را می داند. ‫ درج و به روز رساني داده‬ طریقه ی درج کردن داده درون پایگاه داده را مشاهده کردید: ابتدا یک نمونه از یک مدل را با استفاده از ارگومان های آن مانند زیر ساخته: >>> p = Publisher(name='Apress', ... address='2855 Telegraph Ave.', ... city='Berkeley', ... state_province='CA', ... country='U.S.A.', ... website='http://www.apress.com/') همانطور که در کد فوق ملاحظه می کنید، حرکت فوق تعریف اولیه ی یک کلاس مدل می باشد و پایگاه داده به هیچ وجه لمس نشده است. رکورد مورد نظر تا زمانی که متد save() فراخوانی نشود درون پایگاه داده ذخیره نخواهد شد: >>> p.save() عملیات بالا را تقریبا می تواند به شکل زیر به زبان SQL ترجمه کرد: INSERT INTO books_publisher (name, address, city, state_province, country, website) VALUES ('Apress', '2855 Telegraph Ave.', 'Berkeley', 'CA', 'U.S.A.', 'http://www.apress.com/'); به دلیل آنکه مدل Publisher از یک کلید اصلی به نام id که با خاصیت افزایش خودکار تعریف شده است استفاده می کند، نخستین فراخوانی save() یک کار بیشتر انجام می دهد: ارزش کلید اصلی را برای رکورد محاسبه کرده و آن را درون attribute مورد نظر یعنی id که درون نمونه (instance) می باشد، قرار می دهد: >>> p.id 52 # this will differ based on your own data فراخوانی های بعدی save() رکورد را در مکانی ذخیره می کند، بدون ساختن رکورد جدید (مانند عملکرد عبارت Upadate به جای INSERT در SQL) >>> p.name = 'Apress Publishing' >>> p.save() عملیات فوق را می توان تقریبا به شکل زیر به SQL تبدیل کرد: UPDATE books_publisher SET name = 'Apress Publishing', address = '2855 Telegraph Ave.', city = 'Berkeley', state_province = 'CA', country = 'U.S.A.', website = 'http://www.apress.com' WHERE id = 52; بله، توجه داشته باشید که نه تنها فیلد مورد نظر بلکه تمام فیلدها به روز رسانی خواهند شد. برای پی بردن به نحوه ی اجرای پرس و جوی زیر بخش "به روز رسانی چندین شیء در یک عبارت" را مطالعه کنید: UPDATE books_publisher SET name = 'Apress Publishing' WHERE id=52; واكشي آبجكت ها‬ برای ساختن برنامه های وب دانستن نحوه ی ساخت و به روز رسانی رکورد های پایگاه داده ضروری می باشد، ولی احتمال این وجود دارد که برنامه های وبی که خواهید ساخت نیاز به به اجرای پرس و جوهای بیشتری نیز داشته باشد. روش بازیابی رکوردها را نیز پیش تر مشاهده کردید: >>> Publisher.objects.all() [<Publisher: Apress>, <Publisher: O'Reilly>] مدل کد فوق در SQL چیزی شبیه به کد زیر خواهد بود: SELECT id, name, address, city, state_province, country, website FROM books_publisher; نكته‬ توجه داشته باشید که جنگو هنگامی که به دنبال داده ها می باشد از SELECT * استفاده نمی کند، در عوض لیست تمام فیلدها را به صورت واضح بازیابی می کند. در بعضی شرایط SELECT * می تواند کندتر باشد و (خیلی مهم است) لیست کردن فیلدها به طرز نزدیکی از مکتب پایتون (Zen of Python) پیروی کند: "صراحت بهتر از ابهام است". اجازه دهید از نزدیک بخش های Publisher.objects.all() را مورد بررسی قرار دهیم: ** ابتدا، یک مدل داریم که Publisher تعریف شده است. چیز خاصی در اینجا وجود ندارد: هنگامی که شما می خواهید داده ای را جستجو کنید از یک مدل برای آن داده استفاده می کنید. ** و اما در مورد attribute متد objects. این attribute یک manager نامیده می شود. manager ها به تفصیل در آموزش مدل پیشرفته توضیح داده شده اند. چیزی که برای الان باید بدانید این است که manager ها از تمامی عملکردهای سطح جدول در داده مراقبت می کنند که برای جستجوی داده ها بسیار پر اهمیت می باشند. تمام مدل ها به طور خود کار یک manager، objects دریافت می کنند؛ شما در هر زمان که بخواهید نمونه های مدل را جستجو کنید از استفاده خواهید کرد. ** در نهایت، all() یک متد برای manager، objects می باشد که تمام ردیف های پایگاه داده را بر می گرداند. اگرچه این شیء شبیه به لیست می باشد، اما در واقع یک QuerySet می باشد (یک شیء که مجموعه مشخصی از ردیف های پایگاه داده می باشد.) در ادامه فصل تنها درباره آن ها همانند لیست ها بحث خواهیم کرد. فیلتر کردن داده به طور طبیعی، کم پیش می اید که بخواهیم همه چیز را از پایگاه داده یکباره واکشی کنیم؛ در اغلب موارد، می خواهید با قسمتی از داده ها سر و کار داشته باشید. در API جنگو، شما می توانید داده ی خود را با استفاده از متد filter() فیلتر کنید: >>> Publisher.objects.filter(name='Apress') [<Publisher: Apress>] filter() یک آرگومان به صورت کیورد در یافت می کند که معادل آن در SQL عبارت WHERE می باشد. معادل کد SQL مثال قبلی چیزی مانند کد زیر بود: SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE name = 'Apress'; جهت محدود کردن بیشتر خروجی می توانید چندین آرگومان را به درون filter() ارسال کنید: >>> Publisher.objects.filter(country="U.S.A.", state_province="CA") [<Publisher: Apress>] می توان ارسال چندین آرگومان به متد filter() درون SQL مانند عبارت AND داست. در نتیجه، مثال فوق می تواند به شکل زیر یه کد SQL تبدیل شود: SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE country = 'U.S.A.' AND state_province = 'CA'; توجه داشته باشید که به طور پیشفرض جستجو درون SQL با علامت = دقیقا یکسان بودن را بررسی می کند. نوع دیگر جستجو نیز در دسترس می باشد: >>> Publisher.objects.filter(name__contains="press") [<Publisher: Apress>] همانطور که مشاهده می کنید دو علامت (_) بین name و contains قرار دارد. مانند خود پایتون، جنگو از این خصوصیت برای اشاره به این که چیزی به صورت "magic" در حال اتفاق افتادن می باشد استفاده می کند (در اینجا قسمت __contains به عبارت LIKE در SQL تبدیل می شود.) SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE name LIKE '%press%'; انواع دیگر جستجو نیز در دسترس می باشد، از جمله icontains (عبارت LIKE که به حروف کوچک و بزرگ حساس می باشد)، starstwith، endswith و range (پرس و جوی BETWEEN در SQL). بازیابی شیء های تک مثال های filter() فوق همگی یک QuerySET را بر می گردانند، که می توان با آن ها مانند لیست ها کار کرد. گاهی اوقات بسیار مناسب می باشد که تنها یک تک شیء را از پایگاه داده واکشی کنیم. برای این منظور متد get() در دسترس می باشد: >>> Publisher.objects.get(name="Apress") <Publisher: Apress> بجای یک لیست (QuerySet) یک تک شیء برگشت داده شده است. به دلیل آنکه در صورتیکه نتیجه پرس و جو (query) چند شیء باشد موجب بروز خطای MultipleObjectsReturned خواهد شد: >>> Publisher.objects.get(country="U.S.A.") Traceback (most recent call last): ... MultipleObjectsReturned: get() returned more than one Publisher -- it returned 2! Lookup parameters were {'country': 'U.S.A.'} همچنین در صورتیکه هیچ شیءی برگدانده نشود موجب بروز خطای DoesNotExist خواهد شد >>> Publisher.objects.get(name="Penguin") Traceback (most recent call last): ... DoesNotExist: Publisher matching query does not exist. خطای DoesNotExist یک attribute از کلاس مدل می باشد (Publisher.DoesNotExist). در برنامه های خود می توانید مانند زیر خطاها را کنترل کنید: try: p = Publisher.objects.get(name='Apress') except Publisher.DoesNotExist: print "Apress isn't in the database yet." else: print "Apress is in the database." مرتب سازی داده ها همانطور که در مثال های قبلی مشاهده کردید، ممکن است متوجه این موضوع شده باشید که ترتیب قرار گیری شیء هایی که برگردانده می شوند به صورت تصادفی است. تا تکنون در مورد ترتیب چیدمان داده هایی که از پایگاده داده استخراج می شوند صحبت نشده است، ولی می توان خیلی ساده داده ها را با ترتیب چیدمان دلخواه بازیابی کرد. در برنامه های جنگو، ممکن است بخواهید نتیجه استخراج شده از پایگاه داده را بر اساس یکی از معیارها مرتب کنید (برای مثال بر اساس حروف الفبا). برای انجام این کار از متد order_by() استفاده می شود: >>> Publisher.objects.order_by("name") [<Publisher: Apress>, <Publisher: O'Reilly>] مثال فوق فرق چندانی با متد قبلی یعنی all() ندارد، تنها فرق در این است که حالا SQL ترتیب تعیین شده را نیز لحاظ می کند: SELECT id, name, address, city, state_province, country, website FROM books_publisher ORDER BY name; شما می توانید بر اساس هر فیلدی که مایلید خروجی را مرتب کنید: >>> Publisher.objects.order_by("address") [<Publisher: O'Reilly>, <Publisher: Apress>] >>> Publisher.objects.order_by("state_province") [<Publisher: Apress>, <Publisher: O'Reilly>] برای مرتب کردن بر اساس چندین فیلد (در مواردی استفاده می شود که آرگومان اول درون هر دو فیلد یکی باشد، در آن زمان برای رفع ابهام از آرگومان دوم استفاده می شود.) مانند زیر: >>> Publisher.objects.order_by("state_province", "address") [<Publisher: Apress>, <Publisher: O'Reilly>] همچنین می توان ترتیب چیدمان را با استفاده از یک علامت (-) به صورت بر عکس انجام داد: >>> Publisher.objects.order_by("-name") [<Publisher: O'Reilly>, <Publisher: Apress>] در اغلب موارد شما همواره می خواهید در حالت پیشفرض خروجی داده های شما بر اساس یکی از فیلد های چیده شده باشد، در این صورت جنگو این امکان را فراهم می کند که به صورت پیشفرض درون مدل خود این کار انجام دهید، این امکان زمانی مفید واقع می شود که بخواهید به صورت مکرر از order_by() استفاده کنید، در این صورت منطقی این است که روش زیر را انتخاب کنید: class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() def __unicode__(self): return self.name class Meta: ordering = ['name'] در مثال فوق، یک مفهوم جدید معرفی شده است: class Meta، کلاسی می باشد که درون کلاس Publisher تعریف شده است (این کلاس درون class Publisher به صورت داخل رفته indented قرار گرفته است). می توان از کلاس Meta روی هر مدل برای تعیین اختیارات مختلفی استفاده کرد. که در اینجا ما از اختیار مرتب کردن آن استفاده کرده ایم. این اختیار به جنگو می گوید که اگر به صورت واضح برای چیدمان داده از order_by() استفاده نشده است، تمام شیء های Publisher هر زمان که با API پایگاه داده بازیابی شدند، باید بر اساس فیلد name مرتب شوند. جستجوی زنجیری نحوه ی فیلتر کردن داده را مشاهده کردید، همچنین نحوه ی مرتب کردن آن ها را نیز مشاهده نمودید. اغلب، نیز می باشد هر دو مورد فوق را انجام دهید. در این موارد می توان به سادگی با استفاده از قابلیت جستجوی زنجیری هر دوی موارد فوق در یک خط انجام داد: >>> Publisher.objects.filter(country="U.S.A.").order_by("-name") [<Publisher: O'Reilly>, <Publisher: Apress>] همانطور که انتظار می رود، معادل کد فوق در SQL استفاده از یک WHERE و یک ORDER BY می باشد: SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE country = 'U.S.A' ORDER BY name DESC; تقسیم کردن داده یکی دیگر از امکانات مورد نیاز، جستجوی تنها تعدادی از داده های مشخص از ردیف می باشد. تصور کنید تعداد صد ناشر درون پایگاه داده وجود دارد، در صورتیکه شما می خواهید تنها اولین ناشر را نمایش دهید. می توان برای انجام چنین کاری از خصوصیت تقسیم استاندار لیست پایتون استفاده کنید: >>> Publisher.objects.order_by('name')[0] <Publisher: Apress> کد فوق به شکل زیر تبدیل می شود: SELECT id, name, address, city, state_province, country, website FROM books_publisher ORDER BY name LIMIT 1; به همین صورت، می توان زیر مجموعه ای از داده را نیز بازیابی کرد: >>> Publisher.objects.order_by('name')[0:2] مثال فوق دو شیء را بر می گرداند، و درون SQL به شکل زیر تبدیل خواهد شد: SELECT id, name, address, city, state_province, country, website FROM books_publisher ORDER BY name OFFSET 0 LIMIT 2; توجه داشته باشید که قسیم کردن به صورت منفی در اینجا پشتیبانی نمی شود: >>> Publisher.objects.order_by('name')[-1] Traceback (most recent call last): ... AssertionError: Negative indexing is not supported. با وجود این می توانید به راحتی محدودیت فوق را دور بزنید. تنها کافیست عبارت order_by() را به صورت زیر تغییر دهید: >>> Publisher.objects.order_by('-name')[0] به روز رسانی چند شیء در یک عبارت در بخش "درج و به روز رسانی داده" اشاره شد که متد save() تمام ستون های یک ردیف را به روز رسانی می کند. بسته به برنامه ی شما، ممکن است بخواهید تنها یک قسمت از ستون ها را به روز رسانی کنید. به عنوان مثال، تصور کنید می خواهیم Apress را درون Publisher از 'Apress' به 'Apress Publishing' تغییر دهیم. با استفاده از save() به این صورت عمل می توان کرد: >>> p = Publisher.objects.get(name='Apress') >>> p.name = 'Apress Publishing' >>> p.save() که درون SQL نیز به این شکل تبدیل خواهد شد: SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE name = 'Apress'; UPDATE books_publisher SET name = 'Apress Publishing', address = '2855 Telegraph Ave.', city = 'Berkeley', state_province = 'CA', country = 'U.S.A.', website = 'http://www.apress.com' WHERE id = 52; (توجه داشته باشید که مثال فوق فرض را بر این گرفته است که Apress دارای id = 52 می باشد.) می توان در مثال فوق مشاهده نمود که متد save() جنگو نه تنها ستون name را بلکه ارزش تمام ستون ها را به روز رسانی می کند. منطقی تر و بهتر آن است که تنها ستون مورد نظر تغییر کند. برای انجام چنین کاری می توان از متد update() موجود در شیء های QuerySet استفاده مانند زیر استفاده کرد: >>> Publisher.objects.filter(id=52).update(name='Apress Publishing') کد فوق درون SQL به این شکل تبدیل می شود: UPDATE books_publisher SET name = 'Apress Publishing' WHERE id = 52; متد update() بر روی هر QuerySet ای کار می کند، بدین معنی که می توان چندین رکورد را نیز ویرایش کرد. در مثال زیر نحوه تغییر country درون هر رکورد Publisher از 'U.S.A' به USA نشان داده شده است. >>> Publisher.objects.all().update(country='USA') 2 متد update() یک integer بر می گرداند که تعداد رکوردهای تغییر داده شده می باشد، در مثال فوق 2 رکورد تغییر داده شده اند. حذف کردن شیء ها برای حذف کردن یک شیء از پایگاه داده، به سادگی متد delete() را می توان فراخوانی کرد: >>> p = Publisher.objects.get(name="O'Reilly") >>> p.delete() >>> Publisher.objects.all() [<Publisher: Apress Publishing>] همچنین می توان چندین شیء را نیز با فراخوانی متد delete() از هر QuerySet حذف کرد. این حالت مانند متد update() که در بخش گذشته نشان داده شد می باشد: >>> Publisher.objects.filter(country='USA').delete() >>> Publisher.objects.all().delete() >>> Publisher.objects.all() [] هنگام حذف کردن داده ها مراقب باشید! برای احتیاط از حذف شدن تمام داده های موجود در یک جدول مشخص، در صورتیکه می خواهید هر آنچه که درون جدول می باشد را حذف کنید، می توان از متد all() استفاده کرد. به عنوان مثال کد زیر کار نخواهد کرد: >>> Publisher.objects.delete() Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'Manager' object has no attribute 'delete' ولی اگر متد all() را اضافه کنید کار خواهد کرد: >>> Publisher.objects.all().delete() در صورتیکه می خواهید تنها بخشی از داده را حذف کنید، نیازی به متد all() نمی باشد: >>> Publisher.objects.filter(country='USA').delete() خسته نباشید دوستان عزیز . جلسه پنجم کتاب جنگو به پایان رسید . کار ترجمه این کتاب زیاد عالی نیست . ولی برای شروع بد نیست . امیدوارم که موفق باشید . ترجمه از سایت www.djangobook.com
  5. این تاپیک پشتیبانی برای آموزش است آموزش مدل ها ( models ) در جنگو ( قسمت پنجم ) 11/04/96 17:57 11/04/96 17:57 لطفا اگرهر سوال یا بازخوردی دارید اینجا ارسال کنید.
  6. به نام خدا با عرض سلام خدمت دوستانم عزیزم امیدوارم تا اینجای آموزش براتون مفید واقع شده باشه . در قسمت هشتم از سری آموزش برنامه نویسی پایتون مقدماتی میخوایم انواع داده در زبان پایتون و نحوه استفاده از آنها رو برای شما عزیزان آموزش بدیم . با ما همراه باشید . معرفی انواع داده ها ( Data Type ) در زبان برنامه نویسی پایتون یکی از کارهای اساسی که هر زبان برنامه نویسی باید انجام بده دریافت اطلاعات و دیتا و ایجاد یکسری تغییرات بر روی این اطلاعات و در نهایت نمایش تغییرات دیتا در خروجی . در پایتون چند نوع اولیه وجود دارند که در این بخش به انواع عددی و بولی و رشته ای می پردازیم . 8-1 : نوع داده عددی انواع عددی شامل ۲ مورد زیر است : --- نوع صحیح ( int ) : اعداد صحیح مثبت و منفی ( اعدادی که نقطه اعشار ندارند ) می باشند . در پایتون اندازه عددهای صحیح فقط با حافظه ماشین محدود میشن و ارتباطی با تعداد ثابتی از بایت ها مشخص نمیشن . مثال = اعداد زیر همه صحیح هستند : - 4588 54565966694 - 5656551 بنابراین شما حتی می توانید عدد صحیحی ایجاد کنید که ۲۰۰ رقم داشته باشد . هیچ مشکلی به وجود نمیاد . فقط شاید یکم کندتر اجرا شوند . اعداد صحیح می توانند در مبنای ۱۰ ( دسیمال ) و مبنای ۲ ( باینری ) و مبنای ۸ ( هشت ) و مبنای ۱۶ ( شانزده ) باشند . اعداد در مبنای ۱۰ به صورت طبیعی نوشته می شوند : 58485484 اعداد در مبنای ۲ با پیشوند 0b نوشته می شوند : 0b0101001 اعداد در مبنای ۸ با پیشوند 0o نوشته می شوند : 0o2367652 اعداد در مبنای ۱۶ با پیشوند 0x نوشته می شوند : 0x2DEFFF ---- نوع ممیز شناور ( floating point ) : زبان برنامه نویسی پایتون ۳ نوع مقدار ممیز شناور را فراهم میکنه . Float و complex و decimal . float : نوع float اعداد ممیز شناور رو با دقت مضاعف نگه میداره که بازه اون مربوط میشه به کامپایلر C که پایتون از اون ساخته شده است . این نوع داده تقریبا دقت پایینی داره . با استفاده از ممیز میتوانید اعداد به صورت توان دار هم بنویسید . 57.00 - 23.200 - 8.8e-4 برای نگه داری اعداد float از تعداد ثابتی بیت در کامپیوتر استفاده می شود . بخاطر همین تعداد اعدادی که میتواند نگهداری شود محدود است . داده های نوع عددی رو میتوان با هم دیگه ترکیب کرد . حاصل ترکیب int و float عددی از نوع float است . مثال : 8.0 = 3.0 + 5 Complex : اعداد مختلط نوعی از داده هستند که شاید تا الان اسم آن را نشنیده باشید . این نوع اعداد معمولا در دروس دانشگاهی استفاده می شوند . نوع داده مختلط نوع غیر قابل تغییری است که یک جفت float را نگهداری می کند که یک بخش آن نشان دهنده قسمت حقیقی و یک بخش آن نشان دهنده قسمت موهومی عدد مختلط است . مثلا عدد مختلط ( 5.6j + 4 ) به صورت زیر نوشته می شود در زبان پایتون : >>> a = 4.0 + 5.6j >>> a.real 4.0 >>> a.imag 5.0 8.2 : نوع داده رشته ای رشته ها با نوع داده str مشخص می شوند که غیر قابل تغییر است و دنباله از کاراکتر های یونیکد رو در خود نگهداری میکنند . معمولا از این نوع داده برای نگه داری اشیا ( اسم ها و ... ) استفاده می شود . رشته ها میتوانند در بین تک کوتیشن ( ' ) و یا دابل کوتیشن ( " ) قرار بگیرند . ' Mostafa ' "My first program " ' Hello World ' 8.3 : نوع داده بولین گاهی اوقات لازم است در زمان اجرای کدهای برنامه، مفسر پایتون درست یا نادرست بودن چیزی را ارزیابی کند. مثلاً فرض کنید که در زمان کدنویسی یک بازی کامپیوتری بگوییم که در صورت برخورد موشک به سفینه، یک انفجار رخ دهد. برای اجرای این دستور در زمان بازی، مفسر دائماً این شرط را بررسی می کند که آیا موشک با سفینه برخورد کرده است یا نه. در واقع باید داده ای در اختیار کامپیوتر قرار بگیرد که درست یا نادرست بودن این شرط را نشان دهد. بدین منظور در زبان برنامه نویسی پایتون از نوع داده هایی که از کلاس bool ساخته می شوند استفاده می کنیم که در حقیقت زیر مجموعه ای از نوع int است، چرا که این نوع داده ها تنها می توانند دو مقدار 0 یا 1 را داشته باشند. مقدار 0 نشان دهنده ی حالت False یا نادرست و مقدار 1 نشان دهنده ی حالت True یا درستاست. تا وقتی که داده ای با مقدار Falsee در اختیار مفسر قرار بگیرد انفجار صورت نمی گیرد، اما به محض آن که مفسر داده ای را دریافت کند که در ارزیابی مقدار آن را True تشخیص دهد، سفینه منفجر می شود! معرفی واژه های کلیدی در زبان برنامه نویسی پایتون واژه های کلیدی واژه هایی هستند که برای زبان برنامه نویسی پایتون معنای خاصی دارند و کار خاصی را انجام می دهند . ما حق نداریم از این کلمات بجز مواردی که خود پایتون اعلام کرده استفاده کنیم . مثلا ما نمیتوانیم از هیج کدوم برای نام گذاری متغیر ها استفاده کنیم . تمام واژه های کلیدی در جدول زیر آورده شده اند : نکته : رعایت حروف کوچک و بزرگ مهم است . False elif lambda None else nonlocal True except not and finally or as for pass assert from raise break global return class if try continue import while def in whith del is yield خب امیدواریم از این بخش آموزش لذت برده باشید . با ما باشید با سری کامل آموزش پایتون مقدماتی امیدوارم که از جلسه هشتم آموزش استفاده کامل رو برده باشید . تمامی حقوق برای انجمن پایتونی ها محفوظ می باشد . پایتونی ها
  7. این تاپیک پشتیبانی برای آموزش است معرفی انواع داده ها ( Data Type ) در پایتون ( جلسه هشتم ) 31/02/96 17:17 31/02/96 17:18 لطفا اگرهر سوال یا بازخوردی دارید اینجا ارسال کنید.
  8. به نام خدا با سلام خدمت همه عزیزان . با جلسه ششم آموزش مقدماتی برنامه نویسی به زبان پایتون همراه شما عزیزان هستیم . همانطور که در جلسه های قبلی با ما همراه بودید توانستیم که پایتون رو بر روی سیستم عامل های ویندوز و مکینتاش و لینوکس نصب کنیم . حالا نوبت به اجرای مفسر پایتون و شروع کد نویسی رسیده است . آموزش شروع کار با حالت اسکریپتی مفسر زبان پایتون وقتی شما شروع می کنید به کد نویسی به زبان پایتون مهم نیست که کجا این کد نویسی انجام می شود ( در ویراشگر متن یا مفسر پایتون و ... ) . در نهایت شما باید یک فایل داشته باشید با پسوند .py و سیستم عامل شما هر زمان که با این فایل مواجه شود متوجه می شود که با فایل پایتون ( معمولا به این فایل ها اسکریپت پایتون گفته می شود ) روبرو شده است . شما برای نوشتن برنامه خود و اجرای آن از ۲ طریق می توانید اقدام کنید : ۱ - یک فایل متنی ایجاد کنید ( خالی ) و اسم آن را تست بگذارید ولی فقط باید حتما پسوند این فایل .py باشد . وقتی شما این فایل رو ایجاد کردید و بعدا داخل آن شروع کردید به کد نویسی و آن را ذخیره کردید کار تمام است . حالا هرگاه لازم بود فقط کافیست روی اسکریپت ( ماژول ) خود دابل کلیک کنید . چون پسوند فایل مربوط به زبان پایتون هست خود سیستم عامل میدونه که باید چجوری فایل رو اجرا کنه ( به سراغ برنامه های py.exe و pyw.exe که لانچرهای ویندوز هستند می رود و با استفاده از آن ها ماژول برنامه را اجرا می کند ) . ۲ - روش دوم از طریق کد نویسی در پنجره کامند ( CMD ) در ویندوز می باشد . اگر از لینوکس و مکینتاش استفاده میکنید باید از طریق پنجره ترمینال این کار را انجام دهید . بعد از باز شدن پنجره ترمینال باید کلمه python را نوشته و در ادامه آدرس فایل مورد نظر را بنویسیم . مثلا شما فایل را با اسم test.py در درایو C و پوشه python-project ایجاد کرده اید . به صورت زیر فرمان مورد نظر را اجرا کنید : python C:\python-project\test.py بعد از اجرا دستور فوق می بینید که محتوای فایلی که نوشته اید اجرا می شود . برای شروع داخل فایل خود کد زیر را بنویسید . این کد یه دستور چاپ ساده است که با یک نگاه متوجه آن می شوید . اگر باز هم متوجه نشدید نگران نباشید چون میریم جلوتر کامل توضیح می دهیم . print("Hello Pythonyha.ir! It is my script .") خب . حالا این فایل را به هرکدوم از ۲ روش بالا اجرا کنید ( چه روی اون دابل کلیک کنید و چه از طریق CMD آدرس اون رو وارد و اجرا کنید ) خواهید دید که جمله فوق پرینت گرفته شده و نمایش داده خواهد شد . این از اجرای برنامه های پایتون با حالت اسکریپتی . آموزش شروع کار با حالت تعاملی مفسر زبان پایتون خب . این روش بهتر و معقولانه تر هست . برای راحتی ما برنامه نویسان زبان پایتون یک محیط کد نویسی آماده کردند که زیاد اذیت نشیم . که بهش محیط تعاملی یا کامند لاین تعاملی ( Interactive Prompt ) می گن . این محیط با محیط کامند لاین ویندوز فرقی نداره . برای اجرای کامند لاین تعاملی اگر سیستم عاملتون ویندوز هست به محل نصب پایتون خود برید ( که معمولا در درایو C و در پوشه ای به نام python هست ) برید . در آنجا فایلی پیدا میکنید با اسم python یا python.exe . این فایل را اجرا کنید . محیط شبیه محیط کامند لاین باز میشود که به راحتی می توانید داخل آن کد پرینتی که بهتون گفته بودم رو اجرا کنید و نتیجه آن را ببینید . البته مستقیما از طریق خود کامند لاین هم میتونید به این محیط برسید . کافیست کامند لاین را باز کنید ( Windows+R ) و ابتدا وارد مسیر محل نصب پایتون شده : cd C:\program Files\Python3.5.2 (ممکن است مسیر فوق برای شما متفاوت باشد ) و بعد پایتون را اجرا کنید : Python فرقی نداره که با کدوم روش به محیط تعاملی پایتون برسید . مهم اینه که به این محیط رسیده اید و می توانید کد نویسی کنید . برای خروج از محیط تعاملی برنامه پایتون کافیست کلمه quit() رو نوشته و اینتر بزنید . همانطور که می بینید سه علامت <<< در ابتدای خط وجود دارد . هرگاه این ۳ علامت را دیدید بدونید که میحط کدنویسی پایتون آماده هست و منتظر شماست برای کد پایتون نوشتن . حالا با خیال راحت در این پنجره کد پرینتی که به شما آموزش دادم رو بنویسید و اینتر بزنید . خواهید دید که جمله شما به زیبایی پرینت گرفته خواهد شد . ما برای ابتدای کار بیشتر در میحط IDLE کد نویسی خواهیم کرد و از هیج کدوم از ۲ روش فوق کار نخواهیم کرد . استفاده از محیط IDLE در پایتون رو در جلسه بعدی آموزش به شما عزیزان خواهم گفت . امیدوارم استفاده کافی رو برده باشید از این آموزش . خسته نباشید . امیدوارم که از جلسه ششم آموزش استفاده کامل رو برده باشید . تمامی حقوق برای انجمن پایتونی ها محفوظ می باشد . پایتونی ها
  9. این تاپیک پشتیبانی برای آموزش است شروع کار با حالت اسکریپتی و تعاملی مفسر زبان پایتون ( جلسه ششم ) 31/02/96 13:05 31/02/96 14:47 لطفا اگرهر سوال یا بازخوردی دارید اینجا ارسال کنید.