هنگامی که کارفرمایان به دنبال کسی برای پر کردن یک جایگاه شغل خالی در شرکت خود می گردند، معمولا به دنبال فردی کار بلد هستند که با اطلاعات و مفاهیم مرتبط با موقعیت شغلی مطابقت داشته باشد. آنها کسی را میخواهند که نه تنها مناسب باشد، بلکه بتواند نیازهای شرکت را در یک زمینه خاص برطرف بکند و دست راست شرکت در این زمینه باشد.
شما بهعنوان متقاضی، باید موقعیت خود را با اطمینان از اینکه میتوانید هر سوال مصاحبهکننده را پاسخ دهید، تقویت کنید. برای کمک به شما در انجام این کار، ما 56 سوال مصاحبه فنی جنگو را در سه سطح ساده، متوسط و پیشرفته برای شما گردآوری کرده ایم که در آن ها سعی شده است طیف وسیعی از مفاهیم جنگو پوشش داده شود.
بیایید به این سوالات جنگو را با هم بخوانیم و برای مصاحبه شغلی سرنوشت ساز خود آماده شویم.
جنگو یک فریم ورک برنامه نویسی مخصوص توسعه وب و منبع باز است که به زبان پایتون نوشته شده است. با فریم ورک جنگو می توان وب اپلیکیشن هایی تولید کرد که سرعت توسعه آنها بسیار بالا بوده و به راحتی قابل نگهداری و باشند.
نه، Django به افتخار جنگو راینهارت، یک گیتاریست جاز که از 1930 تا اوایل دهه 1950 فعالیت میکرد و که یکی از بهترین گیتاریست های تمام دوران ها به حساب می آید، نامگذاری شده است :) .
برنامه نویسان جنگو را بیشتر به دلیل ویژگی های شگفت انگیز زیر انتخاب میکنند:
برخی از شرکتهای معروفتر که از جنگو استفاده میکنند عبارتند از:
توسعه دهندگان وب از جنگو استفاده می کنند زیرا:
CRUD مخفف CREATE، READ، UPDATE و DELETE است. CRUD در واقع به توسعهدهندگان در مورد نحوه ساخت مدلهای قابل استفاده در هنگام ساخت API ها کمک میکند.
بله، جنگو هم مثل هر فریمورک دیگری معایبی دارد:
جنگو از الگوی MVT (تمپلیت ویو مدل) پیروی می کند که بر اساس معماری مدل ویو کنترلر است. MVT کمی با الگوی MVC متفاوت است زیرا قراردادهای خود را حفظ می کند، بنابراین کنترلر توسط خود فریم ورک کنترل می شود.
تمپلیت یک لایه برای نمایش به کاربران بوده که علاوه بر فرمت HTML ای که دارد زبان تمپلیت جنگو (DTL) ترکیب شده است. توسعه دهنده مدل، ویو و تمپلیت را کدنویسی کرده و سپس آن را به یک URL اختصاص میدهد و در نهایت، جنگو آن را به کاربر ارائه می دهد. معماری جنگو شامل موارد زیر است:
جنگو با ایجاد یک پروژه و یک پوشه app، بخش های مختلف برنامه وب را با استفاده از یک ساختار دایرکتوری سازماندهی می کند. ایجاد و تنظیم یک پروژه مناسب به DRY نگه داشتن پروژه (don’t repeat yourself یا تکراری کد نزن) کمک می کند. هنگامی که یک پروژه جنگو ایجاد می کنید، جنگو با استفاده از نام پروژه ای که انتخاب می کنید، یک دایرکتوری root (ریشه) برای پروژه ایجاد می کند. این دایرکتوری شامل فایل های مورد نیاز برای ایجاد عملکرد اولیه برای برنامه های وب شما است.
مدل جنگو یک ویژگی مربوط به جنگو است که به شما امکان می دهد جداول، فیلدها و محدودیت ها را بسازید. SQL (زبان کوئری ساختاریافته) یک زبان پیچیده است که شامل کوئری های مختلف زیادی برای ایجاد و ساخت، حذف، به روز رسانی و سایر وظایف مرتبط با پایگاه داده است.
مدل در جنگو به کلاسی اشاره دارد که به جدول پایگاه داده یا مجموعه پایگاه داده متصل می شود. هر Property کلاس مدل جنگو یک فیلد پایگاه داده را نشان می دهد. آنها در app/models.py تعریف شده اند
مثال:
from django.db import models class SampleModel(models.Model): field1 = models.CharField(max_length = 50) field2 = models.IntegerField() class Meta: db_table = “sample_model”
هر مدلی در جنگو از django.db.models.Model ارث می برد. مثال ما دارای 2 ویژگی (1 کاراکتر و 1 فیلد عدد صحیح) است که در فیلدهای جدول خواهند بود. کلاس Meta به شما کمک می کند مواردی مانند مجوزهای موجود، نسخه های مفرد و جمع name، نام جدول دیتابیس مرتبط، انتزاعی بودن یا نبودن مدل و غیره را مشخص کنید. برای دریافت اطلاعات بیشتر در مورد مدل ها می توانید به اینجا مراجعه کنید.
ویو جنگو توابع پایتون مشابه اسناد HTML هستند و درخواستهای HTTP را میپذیرند و پاسخهای HTTP را برمیگردانند.
تابع view یا به اختصار "view" به سادگی یک تابع پایتون است که یک درخواست وب را می گیرد و یک پاسخ وب را برمی گرداند. این پاسخ می تواند محتویات HTML یک صفحه وب، یا تغییر مسیر، یا خطای 404، یا یک سند XML، یا یک تصویر و غیره باشد.
مثال:
from django.http import HttpResponse def sample_function(request): return HttpResponse(“Welcome to Django”)
دو نوع ویو وجود دارد:
ORM (مخفف Object Relational Mapper) ما را قادر میسازد تا با پایگاههای داده تعامل داشته باشیم، به گونهای که میتوانیم از نوشتن کوئری های خام خودداری کنیم، امکان بازیابی، ذخیره، حذف و انجام سایر عملیات روی پایگاه داده بدون نوشتن هیچ کوئری SQL وجود دارد. ORM به عنوان یک لایه انتزاعی بین مدل ها و پایگاه داده کار می کند.
ORM یک API انتزاعی پایگاه داده است که با استفاده از آن میتوانیم با مدلهای پایگاه داده آن تعامل داشته باشیم، بهعنوان مثال، اقداماتی مانند ساختن، حذف، ویرایش و جستجوی آیتم ها را انجام دهیم.
وب سایت ها به طور کلی نیاز به ارائه فایل های اضافی مانند تصاویر دارند. جاوا اسکریپت یا CSS. در جنگو، به این فایلها "فایلهای استاتیک" گفته میشود، جدای از آن، جنگو فایلهای django.contrib.static را برای مدیریت این فایلهای استاتیک فراهم میکند.
"Django-admin" ابزار خط فرمان جنگو برای انجام وظایف گوناگون است و manager.py به طور خودکار در هر پروژه جنگو ایجاد می شود. عملکردهای مشابه Django-admin را انجام می دهد، اما متغیر محیطی DJANGO SETTINGS MODULE را نیز تغییر می دهد تا به فایل settings.py پروژه شما اشاره کند.
Jinja یک زبان تمپلیت ساز مدرن پایتون است که از تمپلیت های جنگو الهام گرفته شده است و معمولا برای اجرا استفاده میشود.
در جنگو، URL ها به عنوان درگاه ورودی برنامه شما عمل می کنند. در urls.py، میتوانید نحوه عملکرد مسیریابی جنگو را پیکربندی کنید.
URL ها یکی از مهم ترین بخش های یک برنامه وب هستند و جنگو با کمک ماژول خود به نام URLconf (پیکربندی URL) راهی برای طراحی URL های ویژه در اختیار شما می گذارد. عملکرد اصلی این ماژول پایتون این است که می توانید URL های خود را در جنگو به روشی که دوست دارید طراحی کنید و سپس آنها را به تابع پایتون (تابع View) نگاشت کنید. این URL ها می توانند ثابت و پویا باشند. این نشانیهای اینترنتی در urls.py وجود دارند، جایی که با تابع view مطابقت دارند.
سینتکس پایه:
from django.urls import path from . import views urlpatterns = [ path('data/2020/', views.data_2020), path('data/<int:year>/', views.data_year) ]
در جنگو چندین روش برای وراثت مدلها وجود دارد:
وراثت از کلاس پایه مدل (Model):
میتوان یک مدل جدید را از کلاس پایه Model ارث بری کرد. این روش مناسب است وقتی میخواهیم یک مدل کاملاً جدید ایجاد کنیم.
وراثت چندگانه (Multi-table inheritance):
یک مدل میتواند از چند مدل دیگر ارث بری کند. در این حالت هر مدل والد دارای یک جدول جداگانه در دیتابیس خواهد بود.
وراثت تک جدولی (Abstract base models):
مدل پایه انتزاعی تعریف میشود و مدلهای فرزند از آن ارث میبرند. همه مدلها در یک جدول ذخیره میشوند.
وراثت جعبه ابزاری (Proxy models):
مدل پروکسی تعریف میشود تا ویژگیهای اضافی به مدلی دیگر اضافه کند. هر دو مدل در یک جدول قرار میگیرند.
انتخاب نوع وراثت بستگی به نیازهای پروژه دارد. وراثت چندگانه برای تفکیک منطقی دادهها و وراثت تک جدولی برای تفکیک فیزیکی دادهها مناسب است.
پس از خواندن سوال های بالا، زمان آن رسیده است که سطح دشواری این سوال ها را با پرسش های سطح متوسط افزایش دهیم.
project کل برنامه را پوشش می دهد، در حالی که یک app یک ماژول یا برنامه کاربردی در project است که با یک نیاز مخصوص سروکار دارد. بنابراین، یک project از چندین app تشکیل شده است، در حالی که یک app در چندین project حضور دارد.
تمپلیتها در جنگو برای نمایش دادهها به کاربران استفاده میشوند. تمپلیتها فایلهایی هستند که حاوی کدهای HTML، CSS، JavaScript و متغیرها و تگهای زبان الگوی جنگو (DTL) میباشند.
ویژگیهای تمپلیتها در جنگو:
به طور کلی تمپلیتهای جنگو باعث تفکیک منطق و افزایش قابلیت نگهداری کد میشوند.
با شروع فرآیند، سرور جنگو یک request (درخواست) دریافت می کند. سپس سرور به دنبال URL منطبق در الگوهای URL تعریف شده برای پروژه می گردد. اگر سرور نتواند URL منطبق را پیدا کند، یک کد 404 تولید کرده و به صورت response 404 بر می گرداند. اگر URL مطابقت داشته باشد، کد مربوطه را در فایل view مرتبط با URL اجرا می کند و یک response 200 ارسال می کند.
جنگو به یک رابط مدیریت کاملا قابل تنظیم و داخلی مجهز شده است. این پورتال به توسعه دهندگان این امکان را می دهد که تمام داده های موجود در پایگاه داده ای را که شامل برنامه ها و مدل های ثبت شده است، ببینند و تغییراتی در آنها ایجاد کنند. مدل باید در فایل admin.py ثبت شود تا بتوانید از جدول پایگاه داده با رابط مدیریت استفاده کنید.
کاربران پایتون را بر اساس سیستم عامل مورد استفاده که توسط سرورها ارائه میشود، نصب می کنند. سپس دستور "pip install django>=2.2,<3" را در ترمینال اجرا و منتظر نصب آن میشوند. همچنین یک روش بهتر برای نصب پایتون و جنگو استفاده از docker است که امکان ایزوله سازی پروژه را فراهم میکند.
با باز کردن خط فرمان و وارد کردن دستور زیر می توانید نسخه جنگو را بررسی کنید:
Python-m Django–version
سیگنالها قطعههایی از کد هستند که حاوی اطلاعاتی در مورد آنچه در حال حاضر در حال انجام است، می باشند. یک دیسپچر هم برای ارسال و هم برای گوش دادن به سیگنال ها استفاده می شود.
هر زمان که تغییری در یک مدل وجود داشته باشد، ممکن است لازم باشد برخی از اقدامات لازم را انجام دهیم.
جنگو روشی زیبا برای کنترل این موارد در تمپلیت سیگنال ارائه می دهد. سیگنال ها ابزارهایی هستند که به ما امکان می دهند رویدادها را با اقدامات مرتبط کنیم. ما میتوانیم این کارها را با توسعه تابعی اجرا کنیم که با فراخوانی سیگنال اجرا شود.
لیست سیگنال های داخلی در مدل ها:
Signals | Description |
django.db.models.pre_init & django.db.models.post_init |
Sent before or after a models’s _init_() method is called |
django.db.models.signals.pre_save & django.db.models.signals.post_save | Sent before or after a model’s save() method is called |
django.db.models.signals.pre_delete & django.db.models.signals.post_delete |
Sent before or after a models’ delete() method or queryset delete() method is called |
django.db.models.signals.m2m_changed | Sent when a ManyToManyField is changed |
django.core.signals.request_started & django.core.signals.request_finished |
Sent when an HTTP request is started or finished |
جنگو شامل یک سیستم احراز هویت کاربر است که Objectهایی مانند کاربران، گروهها، مجوزهای کاربر و برخی از sessionهای کاربر مبتنی بر Cookie را کنترل میکند.
این سیستم شامل Objectهای زیر است و بر روی آنها کار می کند:
دیتابیس های زیر به طور رسمی توسط جنگو پشتیبانی میشوند:
ساختار session امکان ذخیره سازی و بازیابی هر نوع داده را برای هر بازدیدکننده سایت فراهم می کند. ارسال و دریافت کوکی ها را خلاصه می کند و داده ها را در سمت سرور نگه می دارد.
در جنگو، context یک دیکشنری است که در آن کلیدها نام متغیرها و مقدارها، مقادیر آن متغیرها هستند. تمپلیت این دیکشنری (context) را دریافت کرده و از آن به همراه متغیرها برای خروجی محتوای پویا استفاده می کند.
تابع render یک تابع میانبر است که به توسعه دهنده اجازه می دهد تا به سرعت دیکشنری را بفرستد. سپس با استفاده از موتور تمپلیت در این تابع، تمپلیت با دیکشنری داده ترکیب می شود. در نهایت، تابع render یک HttpResponse حاوی متن رندر شده ارائه میکند، که دادههای برگردانده شده توسط مدلها است. در نتیجه، render() در زمان توسعه دهنده صرفه جویی کرده و به او اجازه می دهد تا از چندین موتور تمپلیت استفاده کند.
فایل settings.py یکی از مهمترین فایلهای پروژههای جنگو است و نقش مهمی در پیکربندی پروژه دارد. اهمیت این فایل به شرح زیر است:
به طور کلی فایل settings.py مغز مرکزی پروژه جنگو به حساب میآید و تمام تنظیمات اصلی در آن قرار دارد.
تابع '()all
' در پوسته شما می تواند برای نمایش هر آیتم در پایگاه داده شما استفاده شود.
در جنگو راههای مختلفی برای فیلتر کردن آیتمهای یک مدل وجود دارد:
1. فیلتر در متد مدل
میتوانیم در متد مدل، فیلتر را اعمال کنیم. برای مثال:
class Book(models.Model): ... def latest_books(self): return self.objects.filter(publish_date__year=2023)[:10]
2. فیلتر در متد منیجر مدل
Book.objects.filter(is_published=True)
3. فیلتر در ابتدای لیست
latest_books = Book.objects.filter(publish_date__year=2023)[:10]
4. فیلتر در متد get_queryset کلاس مشاهده
class BookListView(ListView): def get_queryset(self): return Book.objects.filter(is_published=True)
5. فیلتر با استفاده از Q object برای فیلترهای پیچیدهتر
from django.db.models import Q Books.objects.filter(Q(publish_date__year=2023) & Q(price__gt=10000))
انتخاب روش بستگی به نیاز دارد. اما اغلب گزینههای اول و دوم رایجتر هستند.
ما سوالات آسان و متوسط مصاحبه جنگو را پوشش داده ایم، اکنون بیایید به سطح پیشرفته سوالات و پاسخ های مصاحبه جنگو نگاه کنیم.
Django Rest Framework (DRF) چارچوبی است که به شما کمک می کند API های RESTful را به سرعت ایجاد کنید. آنها به دلیل استفاده از پهنای باند کم برای برنامه های وب ایده آل هستند.
شما از middleware برای چهار عملکرد مختلف استفاده می کنید:
فایل urls.py در جنگو نقش مهمی در مسیریابی و اتصال URLها به views دارد.
وظایف اصلی این فایل عبارتند از:
به طور کلی فایل urls.py باعث میشود مسیریابی در جنگو سازمانیافته و قابل مدیریت باشد.
جنگو به طور مستقیم از کلیدهای اصلی چند ستونی پشتیبانی نمیکند.
دلیل این موضوع این است که جنگو از ORM استفاده میکند و در سطح ORM، کلید اصلی همیشه یک فیلد واحد است.
البته راهحلهایی وجود دارد:
بنابراین بهتر است به جای کلید اصلی چندستونی، از روشهای بالا در جنگو استفاده کرد.
برای شروع، مطمئن شوید که تنظیمات DEBUG با True تنظیم شده است. اگر این طور نبود، دستورات زیر را بنویسید:
from Django.db import connection connection.queries
جنگو از این استراتژی های کش پشتیبانی می کند:
QuerySet مجموعه ای از کوئری های SQL است. دستور print(b.query) کوئری SQL ایجاد شده از فراخوانی filter را به شما نشان می دهد.
کلاس Client در ماژول تست جنگو، یکی از مفیدترین ابزارها برای Unit Testing و تست پذیرش در جنگو است.
دلایل اصلی استفاده از این کلاس:
به طور کلی این کلاس باعث میشود بتوان به راحتی تستهای اندازهگیری و جامعی برای جنگو نوشت.
برای استفاده از یک جلسه مبتنی بر فایل، باید تنظیمات SESSION_ENGINE را روی "Djangoo.contrib.sessions.backends.file" تنظیم کنید.
در جنگو، یک mixin یک کلاس پایتون است که توسط کلاس دیگری به ارث برده می شود تا عملکردهای اضافی را برای برنامه انجام دهد. کلاس هایی که می توانند دوباره استفاده شوند و مقیاس شوند، mixin هستند. یک شکل منحصر به فرد از وراثت های چندگانه یک mixin است. mixin ها معمولا در دو زمینه به کار می روند:
به طور کلی، "Field" یک کلاس انتزاعی است که یک ستون جدول پایگاه داده را نشان می دهد. RegisterLookupMixin یک زیر کلاس از کلاس Field است. این فیلدها توسط متد value برای ساخت جداول پایگاه داده بکار گرفته شده و سپس برای انتقال انواع داده ای پایتون به دیتابیس استفاده می شود. در نتیجه، فیلدها اجزای ضروری جنگو مانند مدلها و کوئری ست ها هستند.
تغییر مسیر دائمی تنها در صورتی استفاده می شود که نیازی به نمایش URL های قدیمی نداشته باشیم. مرورگر پاسخ تغییر مسیرهای دائمی را در کش نگه می دارد، بنابراین تلاش برای تغییر مسیر به جایی دیگر باعث ایجاد مشکلاتی می شود. از آنجا که این یک فرآیند در سمت مرورگر است، اگر کاربر شما به صفحه دیگری هدایت شود، همان صفحه را بارگیری می کند.
هر دو یکی از رایج ترین انواع فیلدها در جنگو هستند. تنها تفاوت این دو در این است که فیلد ForeignKey علاوه بر کلاس مدل، گزینه on_delete را نیز شامل می شود، زیرا برای روابط چند به یک استفاده می شود، در حالی که فیلد OneToOne فقط روابط یک به یک را مدیریت می کند و فقط به کلاس مدل نیاز دارد.
QuerySet ها را می توان در QuerySet دیگری ترکیب کرد و لازم نیست آنها از یک مدل باشند. برای ادغام QuerySets از همان مدل، از عملگر union پایتون استفاده میکنیم. عملگر union می تواند برای ترکیب دو یا چند QuerySet با سینتکس زیر استفاده شود:
model_combination = model_set1 | model_set2 | model_set3
علاوه بر این، می توانید با استفاده از متد chain()
از پکیج Itertools، دو یا چند QuerySet را از مدل های دیگر به هم متصل کنید.
from itertools import chain model_combination = list(chain(model_set1, model_set2))
به عنوان یک جایگزین، میتوانید دو یا چند QuerySet را از مدلهای دیگر با استفاده از union ادغام کنید تا all=TRUE را ارسال کنید تا امکان تکرار وجود داشته باشد.
model_combination = model_set1.union(model_set2, all=TRUE)
راه های مختلفی برای ویژه سازی و شخصی سازی رابط مدیریت جنگو وجود دارد:
با استفاده از این تکنیکها میتوان رابط کاربری مدیریت را مطابق با نیازها شخصیسازی کرد.
هنگام نوشتن کوئریهای پیچیده، اشیا Q استفاده می شوند زیرا filter فقط به شما اجازه می دهند شرایط را "AND" کنید. در حالی که اشیا Q به شما اجازه می دهند که شرایط را "OR" کنید.
یک استثنا یا Exception یک رویداد غیرعادی است که باعث از کار افتادن یک برنامه می شود. جنگو کلاس های Exception خود را برای مقابله با این شرایط دارد و همچنین از تمام Exception پایتون پشتیبانی می کند.
تمپلیت ها بخشی جدایی ناپذیر از معماری MVT هستند. آنها به طور کلی شامل HTML، CSS و js هستند که در آنها متغیرهای پویا و اطلاعات با کمک view ها تعبیه شده اند. برخی از ساختارها توسط موتور تمپلیت شناسایی و تفسیر می شوند. اصلی ترین آنها متغیرها و تگ ها هستند.
یک تمپلیت با یک context ارائه می شود. رندر فقط متغیرها را با مقادیرشان جایگزین میکند که در متن موجود هستند و تگها را پردازش میکند. همه چیز دیگر همان طور که هست باقی می ماند.
سینتکس زبان تمپلیت جنگو شامل چهار ساختار زیر است:
برای مطالعه بیشتر در مورد تمپلیت ها می توانید به این آدرس مراجعه کنید.
مطمئن شوید که django.contrib.staticfiles به INSTALLED_APPS شما اضافه شده است
در فایل settings مقدار STATIC_URL را به عنوان مثال تعریف می کنیم.
STATIC_URL = '/static/'
در تمپلیتهای جنگو، از تگ تمپلیت ثابت برای ایجاد URL برای مسیر نسبی داده شده STATICFILES_STORAGE استفاده می کنیم.
{% load static %} <img src="{% static 'my_sample/abcxy.jpg' %}" alt="ABC image">
طبق مثال بالا فایلهای استاتیک در پوشهای به نام static در برنامه ذخیره میشوند. به عنوان مثال my_sample/static/my_sample/abcxy.jpg
هر زمان که درخواستی یا request ای به یک صفحه وب ارسال می شود، جنگو یک شی HttpRequest ایجاد می کند که حاوی یک متا دیتا در مورد آن درخواست یا request است. پس از آن جنگو ویوی خاصی را بارگذاری کرده و HttpRequest را به عنوان اولین آرگومان به تابع view ارسال می کند. هر ویو یک شی HttpResponse را برمی گرداند.
مراحل زیر زمانی اتفاق میافتد که درخواستی توسط جنگو دریافت میشود:
ModelName.objects.filter(field_name=”term”)
print(queryset.query)
تفاوت اصلی بین select_related و prefetch_related در جنگو به شرح زیر است:
select_related
prefetch_related
بنابراین بسته به نوع رابطه بین مدلها از هر کدام استفاده میشود.
جنگو یک فریمورک قدرتمند و کامل برای توسعه وب است که امروزه بسیار محبوب شده است. در این مقاله سعی کردم در سه سطح ساده، متوسط و پیشرفته سوالات مصاحبه جنگو را بررسی و شما را برای یک مصاحبه جذاب آماده کنیم.
اما نکتهی پایانی و کلام آخر این بخش یک جمله است: مصاحبههای زیادی انجام بدید تا ضعفهای شما بیشتر و بهتر دیده شود و برای برطرف کردن آنها منابع یادگیری بهتری را مطالعه کنید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.