آموزش جنگو : جلسه سی و هفت | بررسی Field API در جنگو

در این جلسه در رابطه با api مربوط به فیلد ها در جنگو صحبت خواهیم کرد و چگونگی عملکرد فیلد ها در جنگو را بررسی می کنیم . با ما همراه باشید . آموزش جنگو : جلسه سی و هفت | بررسی Field API در جنگوبررسی API فیلداین بخش درباره API مربوط به فیلد ها است . یعنی قرار است متد های داخلی و فرایند عملکرد یک فیلد را با هم بررسی کنیم . همچنین بررسی می کنیم که یک فیلد دقیقا چیست . این مباحث مربوط به امور پیشرفته جنگو است . پس اگر هنوز مرحله مقدماتی هستید ,نیازی به بررسی این بخش نخواهید داشت .در بخش های پیشین انواع فیلد ها را بررسی کرده بودیم . فیلد یک کلاس نوع abstract است که ستون های جدول دیتابیس را نشان می دهد . جنگو از فیلد ها (متد های درون کلاس آنها) برای ایجاد ساختار جدول دیتابیس (متد db_type) ,برای تبدیل نوع داده ای پایتون به نوع های درون دیتابیس (متد get_prep_value) و بالعکس (متد from_db_value) استفاده می کند .بنابراین فیلد یک قطعه اساسی است که از API های مختلف جنگو بهره برده است .در مدل ها یک فیلد به عنوان یک attribute یا ویژگی در کلاس تعریف می شود و در دیتابیس یک ستون خاص را نشون میدهد . همچنین مقادیری مانند null یا unique یا متد هایی را قبول می کند که باعث خاص شدن رفتار های فیلد (مثلا بتواند مقادیر خالی را بپذیرد) می شوند .یک فیلد یک زیر کلاس از کلاس RegisterLookupMixin است . این علتی است که شما می توانید Lookup و Transform را روی آن پیاده سازی کنید (برای مثال field_name__exact="foo") .همچنین علاوه بر فیلد های پیش فرض جنگو (مثلا JSONField یا CharField) می توانید بر اساس نیازتان فیلد های جدیدی را بسازید و از آنها استفاده کنید . بعدا درباره این کار توضیحاتی را ارائه خواهیم کرد . فعلا به بررسی کلاس ها و متد های درون یک فیلد خواهیم پرداخت . (از اینها بعدا در ساخت فیلد های custom استفاده می توانید کنید)1-آرگومان description :یک توضیح مفصل درباره فیلد را می توانید در آن تعریف کنید . برای مثال در django.contrib.admindocs استفاده می شود .یک Description می تواند به شکل زیر تعریف شود :description = _(&quotString (up to %(max_length)s)&quot)آرگومان های کد بالا نیز از __dict__ در فیلد پیدا و جایگذاری خواهند شد (مثل ویژگی max_length) .2-آرگومان descriptor_class :کلاسی که descriptor protocol(از مباحث پایتون است) را برای کلاس شما تنظیم می کند . این کلاس نمونه سازی (instantiated) می شود و به ویژگی های شی افزوده می شود . البته سازنده یک آرگومان که شی Field است را باید قبول کند . بازنویسی این ویژگی می تواند به بازنویسی رفتار های get و set کلاس کمک کند .جنگو برای تبدیل نوع های داده ای میان پایتون و دیتابیس چندین متد را ارائه می کند :3-متد get_internal_type :این متد رشته ای را می سازد که فیلد شما را برای عملکرد های پشت صحنه (داخلی) جنگو نامگذاری کرده است . به طور پیش فرض نام کلاس را بازمی گرداند . (در مبحث شبیه سازی فیلد های پیش فرض برای استفاده در فیلد های سفارشی این مورد را استفاده می کنیم)4-متد db_type(connection) :این متد با در نظر گرفتن connection یا بهتر بگوییم وابسته به دیتابیسی که استفاده می کنید , نوع داده ای ستون دیتابیس (فیلد) را بازمیگرداند . (در مبحث انواع داده های خاص برای فیلد های سفارشی این مورد را استفاده می کنیم)5-متد rel_db_type(connection) : این متد با در نظر گرفتن connection یا بهتر بگوییم وابسته به دیتابیسی که استفاده می کنید , نوع داده ای فیلد را (فیلدهایی مانند OneToOneField یا ForeignKey) بازمیگرداند .(در مبحث انواع داده های خاص برای فیلد های سفارشی این مورد را استفاده می کنیم) .در اصل سه موقعیت اصلی وجود دارد که جنگو نیاز دارد تا ارتباطی را میان فیلد ها و دیتابیس برقرار کند . یعنی داده ها را میان آنها جا به جا کند تا اتفاقی رخ دهد . این سه موقعیت عبارتند از :هنگامی که یک Query اجرا می کند (داده ها از پایتون به دیتابیس ارسال می شوند)هنگامی که از دیتابیس داده ای را بازمیگرداند (داده ها از دیتابیس به پایتون ارسال می شوند)هنگامی که چیزی را در دیتابیس ذخیره می کند (داده ها از پایتون به دیتابیس ارسال می شوند)در هنگام اجرای Query دو متد get_db_prep_value و get_prep_value استفاده می شوند .6-متد get_prep_value(value) :تعریف value در اینجا مقدار کنونی آن ویژگی مدل (فیلد) است و این متد داده ها را در قالبی که برای استفاده در Query (به عنوان پارامتر) آماده شده اند ,بازمیگرداند . (در مبحث تبدیل اشیا پایتونی به مقادیر Query این مورد را استفاده می کنیم) .نکته : همگی مباحث جلوتر توضیح استفاده خواهند شد و از این متد ها برای ساخت فیلد های شخصی سازی شده یا custom استفاده می کنیم .7-متد get_db_prep_value(value , connection , prepared=False) :نوع مقادیر یک Query با نوع مقادیر درون دیتابیس ها تفاوت دارند . این در صورتی است که مقدار های آنها کاملا یکسان است ! این متد نوع مقدار یک Query را به نوع مقداری که در دیتابیس وجود دارد تبدیل می کند . به طور پیش فرض اگر prepared=True باشد ,خود value یا مقدار را بازمیگرداند و در غیر این صورت متد get_prep_value را بازمیگرداند . (در مبحث تبدیل مقدار Query به مقادیر دیتابیس این مورد را استفاده می کنیم) .هنگام لود کردن داده ها از دیتابیس متد from_db_value استفاده می شود .8-متد from_db_value(value, expression, connection) :این متد مقداری که از دیتابیس لود شده است را تبدیل به یک شی پایتون می کند . دقیقا برعکس کاری که get_prep_value انجام می دهد . درباره چندی از این متدها قبلتر صحبت کردیم . (در مبحث تبدیل مقادیر دیتابیس به مقادیر پایتون این مورد را استفاده می کنیم) .البته این متد در بیشتر فیلد های داخلی (فیلد هایی که خود جنگو دارد) استفاده نمی شود زیرا خود موتور دیتابیس نوع صحیح داده ای برای پایتون را بازمیگرداند .و اینکه آرگومان expression در واقع همان self است .نکته : به دلایل عملکردی ، from_db_value در فیلدهایی که به آن نیاز ندارند (همه فیلدهای جنگو) استفاده نشده است . در نتیجه شما ممکن است در تعریف خود super را فراخوانی نکنید . در ذخیره شدن اشیا یا رکورد ها در دیتابیس نیز متد های pre_save و get_db_prep_save استفاده می شوند .9-متد get_db_prep_save(value, connection) : این متد مانند get_db_prep_value است ,اما فقط زمانی فراخوانی می شود که داده ها نیاز به سیو شدن در دیتابیس دارند (اگر یادتان باشد سیو و ایجاد در جنگو با یک روش انجام می شوند) . به طور پیش فرض get_db_prep_value را بازمیگرداند .10-متد pre_save(model_instance, add) :در این قسمت درباره متد pre_save صحبت خواهیم کرد و باید مراقب باشید که متد را با با سیگنال آن اشتباه نگیرید . این متد قبل از get_db_prep_save فراخوانی می شود تا مقدار یا value را برای ذخیره شدن آماده کند (برای مثال زمان اتوماتیک در جنگو که با DateField.auto_now تعریف می شود با این متد مقداردهی می شود) .آرگومان model_instance در واقع شی ای را می پذیرد که فیلدی که باید مقداردهی شود , در آن قرار گرفته است. آرگومان add نیز نشان می دهد که آیا این شی برای اولین بار در دیتابیس قرار است ذخیره شود یا خیر .این متد باید مقدار مناسب را با توجه به ویژگی های شی و مقدار model_instance برای فیلد بازگرداند . نام ویژگی به طور خودکار توسط Field اضافه خواهد شد و در self.attname قابل دسترسی است . (در مبحث پردازش داده قبل از ذخیره شدن این متد را استفاده می کنیم)فیلد ها گاهی اوقات مقادیر خود را به نوع های متفاوتی دریافت می کنند . برای مثال از طریق فرم ها یا serialization (از serialization در یکی از فریمورک های مربوط به جنگو استفاده می شود) . حال بیایید متد های مربوط به این مباحث را نیز بررسی کنیم .11-متد to_python(value) :یک value را به یک شی پایتونی تبدیل می کند . این دقیقا برعکس عملکرد متد value_to_string است و همچنین در تابع clean نیز از آن استفاده شده است . (در مبحث تبدیل مقادیر به اشیا پایتون از این متد استفاده می کنیم)علاوه بر فرم ها و نحوه ذخیره سازی داده ,یک فیلد باید بداند که چگونه داده ها را serialize کند .نکته : serialize مبحثی مربوط به فریمورک rest جنگو است . اگر هنوز آشنایی با این مباحث ندارید ,از این بخش رد شوید .12-متد value_from_object(obj) :مقدار فیلد را با توجه به شی دریافت شده (آرگومان obj) بازمیگرداند . این متد اغلب توسط value_to_string استفاده می شود .13-متد value_to_string : شی دریافت شده را به رشته تبدیل می کند . این فرایند برای serialization بسیار کاربردی است . (در مبحث تبدیل داده های فیلد برای serialization این مورد را استفاده خواهیم کرد)هنگام استفاده از مدل فرم ها ,باید فیلد بداند که از کدام form field استفاده کند . برای این کار یک متد وجود دارد :14- متد formfield(form_class=None, choices_form_class=None, **kwargs) : فیلد پیش فرض مناسب برای ModelForm را از django.forms.Field بازمیگرداند .به طور پیش فرض اگر form_class و choices_form_class برابر با None باشد ,فیلد CharField را بازمیگرداند.اگر هم فیلد دارای choices و choices_form_class باشد که مقداردهی نشده ,از یک فیلد TypedChoiceField استفاده می کند . (در مبحث تعیین فرم فیلد برای یک مدل فرم این مورد را استفاده خواهیم کرد)15-متد deconstruct :یک تاپل حاوی 4 اطلاعات مهم برای ساختن دوباره فیلد را بازمیگرداند :نام فیلد در مدلمسیری که نوع فیلد در آن قرار دارد (برای مثال django.db.models.IntegerField)یک لیست حاوی آرگومان های positionalیک دیکشنری از آرگومان های keywordاین متد باید به فیلد های قبل از 1.7 اضافه شود تا داده های آن با استفاده از Migrations منتقل شود .ویژگی های فیلد (Field attributes)هر فیلد علاوه بر متد هایی که دارد ,دارای یک سری از ویژگی های خاص نیز می باشد . این ویژگی ها امکان بررسی درونی رفتار آن را فراهم می کنند . زمانی که نیاز به نوشتن کدی دارید که به عملکرد یک فیلد بستگی دارد ، به جای بررسی شی از این ویژگی ها استفاده کنید . این ویژگی ها را می توان همراه با Model._meta API برای محدود کردن فیلد ها و یا گسترش آنها استفاده کرد . (یعنی فیلد های سفارشی جدید ایجاد کرد)1-ویژگی Field.auto_created : یک Boolean که نشان می دهد آیا فیلد به طور خودکار ایجاد شده است یا خیر. فیلدهایی مانند OneToOneField ایجاد شده توسط وراثت مدل مقدار True را برای این ویژگی دارند .2-ویژگی Field.concrete :یک Boolean که نشان می دهد آیا ستونی در جدول دیتابیس با این فیلد مرتبط است (رابطه ایجاد شده است ,برای مثال رابطه OneToOne) یا خیر .3-ویژگی Field.hidden :یک Boolean که نشان می دهد آیا از یک فیلد در عملکرد یک فیلد دیگر (که non-hidden است) استفاده می شود یا خیر . برای مثال ,فیلد های content_type و object_id که یک GenericForeignKey را تشکیل می دهند . این ویژگی برای تشخیص زیرمجموعه ای از فیلدها نیز به کار می رود.نکته : متد Options.get_fields به طور پیش فرض فیلدهای hidden را exclude می کند . برای اینکه بتوانید فیلد های hidden را نیز در این متد استفاده کنید , include_hidden=True را درون متد استفاده کنید .4-ویژگی Field.is_relation :یک Boolean است که نشان می دهد آیا یک فیلد حاوی ارجاعات روابطی به فیلد یا مدل های دیگر است یا خیر . برای مثال حاوی ForeignKey یا ManyToManyField یا OneToOneField یا …5-ویژگی Field.model :مدلی را بازمیگرداند که حاوی فیلد شماست . اگر فیلد در یک superclass از مدل ساخته شده باشد,این ویژگی به superclass اشاره خواهد کرد و نه به کلاسی که شی دارد .علاوه بر تمام اینها هر فیلد ویژگی هایی را نیز برای روابط خود دارد . این ویژگی ها برای ذخیره جزییات یک رابطه وجود دارند . این ویژگی ها در تمام فیلد ها نیز وجود دارد . اگر فیلد از نوع رابطه ای باشد (مانند OneToOneField) آنها فقط مقادیر Boolean را بجای None خواهند داشت .1-ویژگی Field.many_to_many :اگر فیلد دارای یک رابطه چند به چند (many to many) باشد ,برابر با True خواهد بود . در غیر این صورت برابر با False خواهد بود . تنها فیلد موجود در جنگو که در آن این ویژگی برابر با True است ManyToManyField است .2-ویژگی Field.many_to_one : اگر فیلد دارای یک رابطه چند به یک (many to one) باشد ,برابر با Trueخواهد بود . در غیر این صورت برابر با False خواهد بود . تنها فیلد موجود در جنگو که در آن این ویژگی برابر با True است ForeignKey است.3-ویژگی Field.one_to_many :اگر فیلد دارای یک رابطه یک به چند (one to many) باشد ,برابر با True خواهد بود . در غیر این صورت برابر با False خواهد بود . تنها فیلدهای موجود در جنگو که در آن این ویژگی برابر با True است ForeignKey معکوس یا GenericRelation است.4-ویژگی Field.one_to_one : اگر فیلد دارای یک رابطه یک به یک (one to one) باشد ,برابر با True خواهد بود. در غیر این صورت برابر با False خواهد بود . تنها فیلد موجود در جنگو که در آن این ویژگی برابر با True است OneToOneField است .5-ویژگی Field.related_model :به مدلی اشاره می کند که فیلد به آن رابطه ای ایجاد کرده است . برای مثال مدل Author در ForeignKey(Author, on_delete=models.CASCADE) . همچنین همیشه برای یک GenericForeignKey ,مقدار related_model برابر با None است .6-ویژگی Field.is_relation :این ویژگی نشان می دهد که آیا یک فیلد از نوع رابطه ای است یا خیر . فیلد های رابطه ای شامل ForeignKey , ManyToManyFieldو OneToOneField هستند . اگر فیلد از نوع رابطه ای باشد برابر با Trueقرار داده می شود .در این جلسه نحوه عملکرد و مدیریت یک فیلد در جنگو را بررسی کردیم و تمامی ویژگی های یک فیلد در بک اند جنگو را دیدیم . در جلسه بعدی به بررسی api لوکاپ ها خواهیم پرداخت .