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

در این جلسه به بررسی آرگومان ها یا ورودی های یک فیلد (برای اعمال یک سری از تنظیمات روی فیلد) خواهیم پرداخت . با ما همراه باشید .آموزش جنگو : جلسه بیست و یک | ارث بری مدل هامدل ها :سازماندهی مدل ها در پکیج هاقبل از اینکه به سراغ بررسی فیلد ها برویم بهتر است آخرین نکته درباره مدل ها را بگوییم . دستور python3 manage.py startapp یک ساختار اپ را برای شما ایجاد میکند که هر اپ در آن دارای فایل models.py است . اگر مدل های زیادی دارید بهتر است آنها را در فایل های جداگانه سازماندهی کنید .برای اینکار باید یک بسته مدل ایجاد کنید . ابتدا فایل models.py را از اپ خود حذف کنید و بجای آن /myapp/models را ایجاد کنید . درون آن باید یک فایل init__.py__ و فایل هایی جهت ایجاد مدل ها باشد . شما باید مدل های خود را در فایل init__.py__ وارد کنید .برای مثال اگر مدل های شما درون دو فایل organic.py و synthetic.py قرار داشت و آنها را درون پوشه models قرار داده بودید :(myapp/models/__init__.py)from .organic import Person from .synthetic import Robotبهتر است تا به طور صریح نام مدل را import کنید . این بجای * from .models import استفاده می شود . این کار باعث خوانایی بهتر کد و تجزیه و تحلیل راحت تر آن است .فیلد ها : ورودی های یک فیلددر صفحات بعدی این کتاب به صورت مفصل درباره آپشن هایی که در فیلد های مختلف میتوان تنظیم نمود , صحبت کرده ایم . مقادیر زیر به عنوان یک آرگومان به فیلد ارسال می شوند و تنظیمات مختلفی را بر روی آن انجام می دهند . درباره چندی از آنها از قبل صحبت کرده بودیم .آرگومان Field.Null / Null :اگر برابر با True قرار داده شود (null=True) جنگو مقادیر خالی و وارد نشده را به عنوان نوع داده ای null در دیتابیس ذخیره می کند .گرچه به یاد داشته باشید که از قرار دادن null در فیلد های بر پایه str (مانند CharField و TextField) باید بپرهیزید. اگر یک فیلد مبتنی بر رشته دارای مقدار null باشد ,یعنی دو مقدار را میتواند برای مقادیر خالی قبول کند :مقدار رشته خالی و مقدار null . در بیشتر موارد داشتن دو نوع مقدار ممکن برای یک فیلد در جنگو اضافی است . قرارداد جنگو بر پایه استفاده از رشته خالی است و نه null . یک استثنا زمانی است که یک فیلد مبتنی بر str دارای blank=True و unique=True باشد . در این شرایط استفاده از null=True موردنیاز است .نکته :برای همه فیلد ها واجب است که اگر می خواهید مقدار های خالی را نیز بپذیرند (در هنگام ایجاد شی) ,باید blank=True را نیز در آنها قرار دهید . زیرا null فقط بر ذخیره سازی آنها در دیتابیس تاثیر می گذارد .نکته :در دیتابیس oracle مقدار null بر ای نشان دادن رشته خالی , بدون توجه به آپشن null ذخیره خواهد شد.آرگومان Field.blank / blank :اگر برابر با Trueباشد ,فیلد شما اجازه دارد تا مقدار های خالی را قبول کند . به صورت پیش فرض False در نظر گرفته می شود . تفاوت بین null و blank این است که null در نوع ذخیره سازی مقدار در دیتابیس تاثیر می گذارد و blank بر روی اینکه واجب است تا فیلد پر شود یا نه ,تاثیر می گذارد .آرگومان Field.choices / choices :این یک مقدار از تاپل ها را قبول خواهد کرد که در یک متغییر جا گرفته اند . شما آن را استفاده می کنید تا مقادیری که میتوانند در یک فیلد استفاده کنند را تعیین کنید . این یعنی در هنگامی که می خواهید فیلد را استفاده کنید , یک لیست کشویی باز می شود و مقادیر تعیین شده در متغییر را برای انتخاب به شما نشان می دهد . (شما در آن فیلد فقط میتوانید مقادیر تعیین شده در متغییر حاوی تاپل ها را انتخاب کنید) متغییر شما باید حاوی لیستی از تاپل ها باشد . هر تاپل یک گزینه برای انتخاب است .اولین مقدار جای گرفته در هر کدام از تاپل ها مقداری است که در صورت انتخاب آن گزینه در دیتابیس ذخیره خواهد شد و مقدار دوم نام قابل خواندن (نام نمایش داده شده) برای کاربر است . به مثال زیر نگاه کنید . (همه ی آنها در یک لیست به ترتیب قرار می گیرند)YEAR_IN_SCHOOL_CHOICES = [ ('FR', 'Freshman'), ('SO', 'Sophomore'), ('JR', 'Junior'), ('SR', 'Senior'), ('GR', 'Graduate'), ]گرچه بهتر است تا انتخاب های خود را در داخل خود مدل تعریف کنید و برای هر کدام از مقدار های اولیه یک متغییر تعریف کنید . به مثال صفحه بعد نگاهی بیندازید !from django.db import models class Student(models.Model): FRESHMAN = 'FR' SOPHOMORE = 'SO' JUNIOR = 'JR' SENIOR = 'SR' GRADUATE = 'GR‘ YEAR_IN_SCHOOL_CHOICES =[ (FRESHMAN, 'Freshman'), (SOPHOMORE, 'Sophomore'), (JUNIOR, 'Junior'), (SENIOR, 'Senior'), (GRADUATE, 'Graduate'), ] year_in_school = models.CharField( max_length=2, choices=YEAR_IN_SCHOOL_CHOICES, default=FRESHMAN, ) def is_upperclass(self): return self.year_in_school in {self.JUNIOR, self.SENIOR}اگر چه میتوانید لیست حاوی گزینه ها را خارج از یک کلاس تعریف کنید و سپس درون کلاس از آن استفاده کنید ,ولی توصیه جنگو این است که بهترین روش همان تعریف لیست در داخل کلاس است . این به ارجاع دادن گزینه های شما و سادگی آن کمک می کند . برای مثال Student.SOPHOMORE در هر جایی که مدل Student وجود داشته باشد ,کار خواهد کرد .شما همچنین می توانید برای اهداف سازمانی ,مقدار متغییر های خود را به صورت گروهی تعریف کنید . به این مثال نگاه کنید تا بهتر متوجه شوید .MEDIA_CHOICES =[ ('Audio', ( ('vinyl', 'Vinyl'), ('cd', 'CD'), ) ), ('Video', ( ('vhs', 'VHS Tape'), ('dvd', 'DVD'), ) ), ('unknown', 'Unknown'), ]اولین عنصر در هر تاپل , نامی است که برای هر گروه اعمال می شود (منظور از گروه در واقع مجموعه گزینه ها است که در یک گزینه جاسازی شده اند) . عنصر دوم هر تاپل , یک تکرار از دو تاپل است که هر کدام از آنها یک گزینه برای همان گروه هستند (برای مثال cd گزینه ای برای Audio است) . عنصر اول آنها نامی است که در دیتابیس ثبت می شود و دومی مقدار قابل خواندن برای انسان است . همچنین به یاد داشته باشید که می توانید لیست هایی حاوی تاپل های گروهی یا غیر گروهی داشته باشید که در کنار هم قرار دارند . برای مثال گزینه unknown در اینجا یک تاپل غیر گروهی است که در کنار بقیه قرار گرفته است .علاوه بر این ها برای هر فیلدی از مدل که دارای choices باشد ,جنگو یک متود به صورت اتوماتیک در نظر میگیرد تا مقدار نام قابل خواندن برای انسان را در ازای هر مقدار ثبت شده در فیلدهای دیتابیس دریافت کنید . بعدا به این مبحث خواهیم رسید . (()get_FOO_display)نکته : گزینه های choices داینامیک نیستند و امکان اینکه به آنها گزینه های بیشتری اضافه شود وجود ندارد , مگر اینکه کد ها را دستکاری کنید که این نیازمند یک برنامه نویس است . اکثر وبسایت ها پنل مدیریتی را برای خود در نظر می گیرند و جنگو نیز از این قائده مستثنی نیست . پس شما برای اینکه بتوانید گزینه های یک فیلد را داینامیک کنید تا به آن بعدا بتوانید گزینه های بیشتری اضافه کنید ,باید کاری کنید تا از پنل مدیریت گزینه ها را بتوان اضافه نمود . برای ان کار کافیست بجای تعیین choices , رابطه ForeginKey را به یک مدل که حاوی گزینه های شماست ایجاد کنید ,و سپس از آن گزینه ها را انتخاب کنید . (اجرای دستور migrate پس از هر تغییر choice اجباری است)آرگومان Field.db_column / db_column :نام ستون پایگاه داده برای استفاده از این فیلد است . (نامی که برای ستون آن فیلد در نظر گرفته میشود) اگر این استفاده نشود ,جنگو مقدار نام متغییر حاوی فیلد را استفاده خواهد کرد .اگر نام ستون شما حاوی کلمات رزرو شده پایتون یا sql است یا حاوی –است ,اشکالی ندارد . جنگو این نام ها را در پشت صحنه نقل قول می کند .آرگومان Field.db_index / db_index :اگر برابر با True باشد یک database index برای این فیلد ساخته خواهد شد . (درباره index گذاری یا اندیس گذاری در پایگاه های داده کمی تحقیق کنید)آرگومان Field.tablespace / tablespace :این گزینه نیز مربوط به فرایند ایندکس گذاری در دیتابیس ها است . فرایند ایندکس گذاری دیتابیس به شما کمک می کند تا بتوانید سریعتر در داده های خود جستجو کنید . اگر شما db_index را برابر با True قرار داده باشید ,باید مقدار این را نیز در فیلد خود تعیین کنید . این در واقع نام tablespace دیتابیس شماست که برای ایندکس کردن به کار خواهد رفت . آن را یا در خود فیلد باید تعیین کنید یا باید در فایل settings.py مقدار متغییر DEFAULT_INDEX_TABLESPACE را تعیین کنید .اگر دیتابیس شما از tablespace پشتیبانی نکند ,این گزینه نادیده گرفته می شود .آرگومان Field.default / default :این مقدار پیش فرض آن فیلد را تعیین می کند . می تواند یک مقدار int یا str(وابسته به نوع فیلد) و یا یک شی بازگردانده شده باشد . اگر دومی باشد , هر بار یک شی جدید ایجاد می شود ,متد یا شی شما فراخوانی می شود .علاوه بر این default ,نمی تواند یک مقدار یا شی قابل تغییر باشد (مدل ,لیست ,ست و غیره) . زیرا ارجاع به آن نمونه از آن شی به عنوان مقدار پیش فرض در تمام نمونه های جدید نیز استفاده خواهد شد . در عوض یک شی قابل فراخوانی را در default قرار دهید . برای مثال از یک تابع می توان برای این امر استفاده نمود . به مثال زیر نگاه کنید :def contact_default(): return {&quotemail&quot: &quotto1@example.com&quot} contact_info = JSONField(&quotContactInfo&quot, default=contact_default)در مثال بالا ما به وسیله یک تابع (قابل فراخوانی) توانسته ایم یک دیکشنری را در به یک JSONField بدهیم .توجه داشته باشید که توابع لامبدا بخاطر نوع فراخوانی و مصرف آنها نمی توانند در یک فیلد به عنوان default به کار بروند .این را نیز بخاطر بسپارید که مقدار پیش فرض زمانی استفاده می شود که فیلد شما مقداردهی نشود . اگر فیلد شما primary_key باشد ,مقدار پیش فرض در زمانی که شما این فیلد را خالی بگذارید دوباره اعمال می شوند .آرگومان Field.editable / editable :مقدار پیش فرض آن True است . اگر برابر با False قرار داده شود , فیلد شما در ادمین پنل یا ModelForm نمایش داده نخواهد شد و در طول اعتبار سنجی نیز نادیده گرفته خواهد شد . (معنای اصلی آن “قابل تغییر” است)آرگومان Field.error_message / error_message :آرگومان error_messages به شما امکان می‌دهد ارور ‌های پیش ‌فرض را که فیلد ایجاد می‌کند بازنویسی کنید. آنها را در یک دیکشنری با کلید های (key) مطابق با پیام‌های خطایی که می‌خواهید بازنویسی شود، وارد کنید . پیام های خطاهای بازنویسی شده در دیکشنری در ادمین پنل هنگام وجود داشتن ارور به شما نمایش داده خواهند شد .کلید های پیام های خطا یا ارور ها عبارتند از : null , blank , invalid , invalid_choice , unique , unique_for_date. گرچه بیشتر از این برای نوع های فیلد مختلف وجود دارد که در بخش های بعدی به آنها خواهیم پرداخت .آرگومان Field.help_text / help_text :مقدار متن راهنمای نشان داده شده در زیر فیلد است . در ادمین پنل و به عنوان متن راهنما نشان داده خواهد شد .به یاد داشته باشید مقدار این گزینه ,صرفا می تواند شامل کد های HTML نیز باشد و ایرادی ندارد . برای مثال :help_text=&quotPlease use the following format: <em>YYYY-MM-DD</em>.&quotهمچنین جنگو قابلیتی دارد تا بتوانید فرم ها را از یک مدل ایجاد کنید و آن را به صورت اتوماتیک برای شما ایجاد کند . این باعث می شود تا help_text نیز در فرم وبسایت به کاربر نمایش داده شود . این ممکن است باعث شود تا بعضی از کد های HTML شما دارای باگ XSS شود . پس بهتر است تا حد ممکن کد ها را ساده نگه دارد و در صورت نیاز از تابع ()escape برای در نظر نگرفتن هر گونه کد HTML در متن ,استفاده کنید . (از مسیر ()django.utils.html.escape آن را import کنید!)آرگومان Field.priamry_key / primary_key :اگر برابر با Ture قرار داده شود ,آن فیلد به عنوان priamry_key مدل شما در نظر گرفته می شود . (در مورد primary_key در صورت ندانستن ,کمی جستجو کنید . این مبحثی از sql است و به جنگو مربوط نیست)اگر برای هیچکدام از فیلد های مدل خود primary_key = True قرار ندهید . جنگو آن را به صورت اتوماتیک تولید خواهد کرد (فیلد id) . بنابراین شما نیازی به قرار دادن primary_key برابر با True ندارید ,مگر اینکه بخواهید ویژگی اصلی جنگو را برای ایجاد primary_key لغو و بازنویسی کنید . در صورت نیاز می توانید رفتار خود جنگو برای تولید این نوع فیلد ها را در AppConfig.defualt_auto_field یا به صورت سراسری و در فایل settings.py تغییر دهید . (منظور این است که به جنگو بگویید تا فیلد دیگری غیر از id بتواند تولید کند و آن را primary_key قرار دهد)بعدا در مورد چگونگی انجام این کار خواهید خواند !به یاد داشته باشید primary_key = True به معنای null = False و unique = True است و فقط یک primary_key برای هر مدل مجاز است .و اینکه primary_key در هر فیلدی که باشد ,فیلد شما read only خواهد بود و اگر تلاش کنید تا در یک شی یا رکوردی که از قبل وجود دارد ,فیلد priamry_key را تغییر دهید ,یک شی جدید در کنار شی قبلی تولید خواهد شد.آرگومان Field.unique / unique :اگر برابر با True قرار داده شود ,شما یک مقدار را فقط یکبار در هر جدول میتوانید داشته باشید . برای مثال امکان داشتن دو مقدار یکسان برای این فیلد در دو رکورد مختلف وجود ندارد . (یکتا بودن مقدار در طی جدول)اگر شما تلاش کنید تا یک مقدار یکسان را در فیلد دو رکورد مختلف قرار دهید , جنگو ارور django.db.IntegrityError را به شما بازخواهد گرداند . این ارور از متد ()save ایجاد می شود .این گزینه برای همگی فیلد ها به جز OneToOneField و ManyToManyField معتبر است و می تواند استفاده شود .نکته :هنگامی که شما unique=True را قرار دهید ,نیازی به تعیین db_index ندارید . Unique خودش شاخص و index را برای شما ایجاد خواهد کرد .آرگومان Field.unique_for_date / unique_for_date :این فقط بر روی DateField و DateTimeField اعمال می شود تا تاریخ برای شما در طول آن جدول یکتا باشد (کسی نتواند یک تاریخ را دوبار استفاده کند) .توجه داشته باشید که اگر این را به یک DateTimeField بدهید ,فقط قسمت تاریخ آن unique خواهد بود (ساعت اینگونه نخواهد بود) . علاوه بر این اگر USE_TZ در settings.py برابر با True باشد ,بررسی جنگو در منطقه زمانی فعلی انجام خواهد شد . (در زمانی که شی ذخیره می شود ,بررسی اتفاق میافتد)علاوه بر این ,اعتبار سنجی مدل وظیفه بررسی unique_for_date را دارد و در دیتابیس این محدودیت وجود نخواهد داشت . این به این معنی است که اگر فیلد شما یک ModelForm نباشد (در فرم به کار نرود) یا editable=False باشد ,جنگو آن را اعتبارسنجی نخواهد کرد . (برای این نوع از فیلد ها کار نمی کند)آرگومان Field.unique_for_month / unique_for_month :مانند ویژگی بالا است ,اما برای قسمت ماه اعتبارسنجی و یکتا بودن را اعمال می کند . (رکورد ها نمی توانند ماه های یکسان داشته باشند)آرگومان Field.unique_for_year / unique_for_year :مانند ویژگی بالا با تفاوت اینکه یکتا بودن برای قسمت سال اعتبارسنجی می شود . (رکورد های نمی توانند یک سال یکسان داشته باشند)آرگومان Field.verbose_name / verbsoe_name :قسمت نام فیلد که به کاربر نشان داده می شود است و یک رشته را به عنوان مقدار قبول میکند و به جای نام فیلد به شما نمایش می دهد . (فقط برای نمایش است) اگر شما هیچ verbose_name را تعریف نکنید ,به صورت اتوماتیک جنگو نام متغییر حاوی فیلد را در نظر خواهد گرفت و آن را در ادمین پنل به شما نمایش خواهد داد .این ویژگی صرفا می تواند به فارسی سازی فرم ها و ادمین پنل کمک کند .آرگومان Field.validators / validators :برای تعیین یک اعتبارسنج یا validator برای فیلد به کار می رود . اعتبارسنج مقدار فیلد را می تواند کنترل کند . (برای مثال می توانید تعیین کنید مقدار نباید دارای – باشد !) . بعدا در مورد چگونگی ساخت آنها بحث خواهیم کرد .در این جلسه تمامی آرگومان های ورودی برای فیلد های مختلف را بررسی کردیم . در جلسه بعدی انواع فیلد ها را بررسی خواهیم کرد .