آموزش جنگو (Basic) : جلسه پنج | ترمینال جنگو

در این جلسه نحوه کار کردن با ترمینال یا شل (shell) جنگو را بررسی می کنیم . با ما همراه باشید .آموزش جنگو : جلسه پنج | ترمینال جنگوترمینال و API جنگودر بعضی از مواقع شما ممکن است نیاز داشته باشید که به API جنگو که در shell پایتون وجود دارد دسترسی بگیرید . این کار را میتوانید از طریق shell جنگو انجام دهید .ترمینال یا Shell در جنگو ,بخشی از ترمینال پایتون است که در آن فایل settings.py که در مسیر روت پروژه شما قرار دارد , import شده است و متغییر های داخلی آن در ترمینال اعمال شده اند . مانند پایتون , هر کاری که در جنگو انجام می شود , از API های مربوط به همین ترمینال استفاده می کند (مانند ترمینال ویندوز یا لینوکس) .برای درک بهتر ابتدا بیایید وارد shell جنگو بشویم . از دستور زیر برای ورود به ترمینال یا شل استفاده کنید : (به یاد داشته باشید که فرض ما این است که کد های جلسات قبل را به طور کامل نوشتید)python manage.py shellحال شما می توانید کد هایی که در جنگو مینویسید را مانند کد های عادی پایتون و به صورت خط به خط وارد کنید تا نتیجه هر کدام را مشاهده کنید :>>> from polls.models import Choice, Question # Import the model classes we just wrote.در کد بالا مدل هایی که در فایل models.py در اپ polls ایجاد کردیم را import کردیم و قرار است ابتدا شی ای را از کلاس Question ایجاد کنیم . این شی (object) همان رکوردی از دیتابیس ماست و اگر شل بسته شود یا سرور خاموش شود باز هم رکورد ما در دیتابیس خواهد ماند و پاک نخواهد شد .برای ساخت یک رکورد در دیتابیس در جنگو کافی است مدل یا کلاس را فراخوانی کرده و مقادیر فیلد های آن را به آن ارسال کنیم . به کد زیر نگاه کنید :>>> from django.utils import timezone >>> q = Question(question_text=&quotWhat's new?&quot, pub_date=timezone.now())در کد بالا از Django.utils متد timezone را import کردیم و کاری که متد timezone.now() برای ما انجام می دهد این است که زمان هم اکنون کشور ما را برای ما باز میگرداند .در خط دوم متغییری با نام q ایجاد کردیم که در واقع شی یا همان رکوردی از دیتابیس ماست که هنوز ساخته نشده است . با فراخوانی کلاس Question و ارسال مقادیر what’s new? و timezone.now() برای هر کدام از فیلد ها شی ای را ایجاد میکنیم و آن را در کلاس q میریزیم . توجه داشته باشید که رکورد ما در دیتابیس هنوز ساخته نشده است و صرفا ما فقط متغییری با یک شی از کلاس Question ایجاد کردیم .جنگو میتواند شی ها را ایجاد کرده و درون متغییرهایی بریزد . اما تا زمانی که آن ها را سیو نکنید جنگو رکورد آنها را در دیتابیس ایجاد نمیکند . برای سیو کردن یک شی کافی است به روش زیر اقدام کنید .>>> q.save() # saves the object and create a record in databaseنکته : در جنگو به صورت اتوماتیک به هر شی ایجاد شده یک id تعلق میگیرد . این id صرفا از 1 تا n است و برای مرتب سازی شی ها به کار می رود . به یاد داشته باشید که این id ها به صورت اتوماتیک برای شی ایجاد میشود و نیازی نیست شما کار خاصی انجام بدهید . هم اکنون میتوانید به id شی جدیدی که ایجاد کردید و اکنون رکوردی در دیتابیس شده است دسترسی داشته باشیدبرای دسترسی به id اختصاص داده شده به این شی جدید , مانند زیر آن را از شی فراخوانی کنید : (id در واقع یک فیلد است که اتوماتیک ایجاد می شود)>>> q.id #retruns 1همچنین id در واقع هم اکنون یکی از فیلد های مدل شماست که اتوماتیک ایجاد شده است و شما دخالتی در ایجاد آن نداشته اید . پس به همین صورت نیز میتوانید به مقادیر دیگر فیلد های پروژه دسترسی داشته باشید .>>> q.question_text &quotWhat's new?&quot >>> q.pub_date datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)همچنین شما میتوانید با کد زیر تمامی اشیا کلاس Question را ببینید . به یاد داشته باشید که تمامی اشیا که در این کلاس وجود دارند به این معنی هستند که سیو شده اند و رکورد هایی در دیتابیس را ایجاد کرده اند .>>> Question.objects.all() #<QuerySet [<Question: Question object (1)>]>نکته : تمامی اشیا و رکورد های دیتابیس در جنگو به صورت model object number ذخیره میشوند . این یعنی به هرکدام از آنها یک شماره تعلق میگیرد و دیدن این اطلاعات و اعداد کمک چندانی به شما نمیکند , شما باید متد های _str_ را بازنویسی کنید . گرچه شما فقط در شل جنگو این شی ها را نمیبینید , در جلوتر با ادمین جنگو آشنا خواهید شد که این نکته در آنجا بدرد شما خواهد خورد .برای عوض کردن اسم شی (در ادمین پنل نشان داده می شود) کافی است متد ()__str__ را در مدل خود بازنویسی کنیم . مدل خود را به صورت زیر تغییر دهید :from django.db import models class Question(models.Model): # ... def __str__(self): return self.question_text class Choice(models.Model): # ... def __str__(self): return self.choice_textتوجه داشته باشید که لازم نیست در این مورد دستور های migrate را اجرا کنیم . زیرا فقط تابعی را در کلاس خود تغییر داده ایم و تغییر ربطی به دیتابیس ندارد . حال دوباره شل جنگو را اجرا کنید و کد زیر را وارد کنید .>>> from polls.models import Choice, Question >>> Question.objects.all() #<QuerySet [<Question: what’s new?>]>متد های اشیاحال فرض کنید تعداد رکورد های زیادی در دیتابیس شما وجود دارد . به بیانی دیگر تعداد اشیا زیادی را در کلاس خود ایجاد کردید . گرچه در حال حاضر فقط یک رکورد و شی داریم ,اما شما بالعکس آن را فرض کنید .حال چگونه میتوانید آنها را جدا کنید و به یکی از آنها دسترسی پیدا کنید . منظور این است که فرض کنید شی ای از کلاس Question را لازم دارید که Question text آن برابر با “ what’s up? ” باشد . چگونه میتوانید این شی را پیدا کنید و به دیگر فیلد های آن مانند pub_date دسترسی پیدا کنید .در جنگو این کار به کمک متد هایی که برای هر کلاس در نظر گرفته شده است صورت میگیرد .شما چند دقیقه پیش با یکی از این متد ها آشنا شدید . متد ()model.objects.all تمامی اشیا یک کلاس را که در دیتابیس وجود دارند ,برای شما پیدا میکند .اما متد های دیگری نیز وجود دارند که اکنون قرار است به دو تا از مهمترین آنها , متد get و filter بپردازیم .در شل جنگو کد های زیر را وارد کنید و نتیجه آنها را ببینید . (خروجی هر کد را به صورت کامنت در زیر هر خط از کد نوشته ایم)>>> Question.objects.filter(id=1) #<QuerySet [<Question: What's new?>]>نکته : به جست و جوی جنگو در دیتابیس خود Query گفته میشود . Query یعنی جست و جو در دیتابیس و یافتن رکورد هایی مناسب با درخواست شما .در کد بالا ما کلاس Question را فراخوانی کردیم و با "obejcts." به اشیا درون آن که همان رکورد های درون دیتابیس هستند دسترسی پیدا کردیم . سپس با تابع filter شی هایی که مقدار id آنها برابر با 1 باشد را پیدا کردیم.همچنین میتوانیم اشیایی را پیدا کنیم که مشخصات دیگری داشته باشند . برای مثال :>>> Question.objects.filter(question_text=“what’s new?”) #<QuerySet [<Question: What's new?>]>ما تابع دیگری نیز تحت عنوان get داریم که همان کار تابع filter را انجام میدهد اما تفاوت اصلی ان با تابع filter در خصوص تعداد اشیایی است که در Query ما پیدا شده اند .تابع get را در صورتی باید استفاده کنیم که فقط یک شی با ویژگی مورد درخواست وجود دارد .تابع filter را باید زمانی استفاده کنیم که چند شی را لازم داریم یا چند شی با مشخصه ما در دیتابیس وجود دارد . برای مثال هنگامی که شما میخواهید شی ای را پیدا کنید که id آن برابر با 1 باشد ,باید از تابع get استفاده کنید . زیرا فقط و فقط یک شی میتواند با id برابر با 1 وجود داشته باشد .اما هنگامی که بخواهید شی ای را پیدا کنید که question_text آن برابر با what’s new باشد باید از تابع filter استفاده کنید . زیرا ممکن است چند شی یا رکورد در دیتابیس شما وجود داشته باشند که مقدار question_text آنها برابر با مقدار درخواست شده باشد .دقت داشته باشید که استفاده از تابع get در زمانی که چند شی در دیتابیس وجود دارد باعث ایجاد ارور خواهد شد .شما همچنین میتوانید با استفاده از این دو تابع مقادیر فیلد های هر شی را تغییر دهید .>>> t = Question.objects.filter(question_text=“what’s new?”) #<QuerySet [<Question: What's new?>]> >>> t.question_text = “what’s up?” #<QuerySet [<Question: What's up?>]>و با استفاده از تابع get :>>> t = Question.objects.get(id=1) #<QuerySet [<Question: What's new?>]> >>> t.question_text = “what’s up?” #<QuerySet [<Question: What's up?>]>همچنین به یاد داشته باشید که در صورتی که جنگو در دیتابیس نتیجه ای مناسب پیدا نکند به شما ارور خواهد داد . برای مثال اگر بخواهید شی ای از کلاس Question را پیدا کنید که id برابر با 2 داشته باشد ,زیرا هیچ شی ای در Question با id برابر با 2 نداریم , ارور زیر را دریافت می کنیم : (در دو متد get و filter هر دو باعث ایجاد ارور خواهد شد)>>> Question.objects.get(id=2) …DoesNotExist: Question matching query does not exist.هم اکنون شما کار با متد های filter , get , all را یاد گرفتید . اما ما متد دیگری نیز داریم .متدی که قرار است مورد بررسی قرار دهیم , متد create است . این متد همانطور که از اسمش پیداست ,کار ساخت یک شی یا رکورد جدید در دیتابیس را انجام می دهد . ما این کار را قبلا با فراخوانی نام کلاس و ایجاد متغییر و سیو کردن متغییر انجام داده بودیم , اما این بار با متد create انجام خواهیم داد . تفاوت این متد با روش قبلی در این است که این متد به صورت اتوماتیک شی را برای شما سیو خواهد کرد و تعداد خط کد کمتری برای ایجاد یک رکورد در دیتابیس لازم است .>>> Question.objects.create(question_text=“what else?” , pub_date=datetime.now()) #<Question: what else?>شما همچنین می توانید همانطور که اشیا و رکورد ها را می سازید , آنها را حذف نیز کنید . برای حذف کافی است مقدار query خود را درون یک متغییر بریزید و سپس متد delete را برای آن فراخوانی کنید .>>> c = Question.objects.filter(question_text=“what else?”) #<Question: what else?> >>> c.delete()بسیار خب ,اکنون شما میتوانید به کمک شل رکورد های دیتابیس را ایجاد کنید ,مقادیر فیلد های هر رکورد را تغییر دهید ,رکورد های دیتابیس را حذف کنید و یا رکورد ها را پیدا کنید و query ایجاد کنید . (از این پس ,به گشتن جنگو و پیدا کردن رکورد ها به کمک متد filter و get نام Query را اختصاص خواهیم داد)در این مقاله شما با شل ها و API جنگو آشنا شدید . در قسمت بعدی به بررسی ادمین پنل جنگو می پردازیم .