با عرض سلام و وقت بخیر خدمت کاربران محترم سایت ویرگول، در این مقاله آموزشی که چکیده آموزش جنگو از سایت tutorialspoint بهمراه مطالب تکمیلی تر , سعی شده یک آموزش کاربردی و پروژه محور از جنگو ارایه گردد.ایده این سری مقاله های آموزشی از این موضوع سرچشمه می گیرد که بخشی از خوانندگان وجود دارد که به محتوای نوشتاری آنلاین بهتر پاسخ می دهند و ترجیج می دهند مهارت های جدید را به سرعت از طریق خواندن افزایش دهند.این سری اموزش ها با ارایه اولین پکیج آموزشی در خصوص مانگودبی آغاز می شود که انتظار می رود با واکنش مثبت کاربران همراه شود.
توجه: این مقاله به مرور زمان، ویرایش و یا تکمیل میشود!
تقاضا: در صورتی که با مشکل تایپی، دستوری و یا مفهومی در این مقاله برخورد کردید، از شما دوست عزیز و گرامی، صمیمانه تقاضا میکنم که اینجانب را مطلع کرده، تا نسبت به تصحیح و یا تکمیل آن، در اسرع وقت، اقدام نمایم. با کمال تشکر جواد جهانگیری
شماره تلفن همراه: 09149431772
نشانی پست الکترونیکی: javad.jahangiri.niopdc@gmail.com
فیلمهای آموزشی در آپارات:جواد جهانگیری (CTO) - آپارات
فیلم آموزشی در یوتویب: javad jahangiri - YouTube
نسخه مقاله: ۱.۱ - تاریخ بروزرسانی: 1400/11/27
برای دیدن فیلم اموزشی مربوطه به کانال آپاراتی بنده به ادرس جواد جهانگیری (CTO) - آپارات مراجعه نمایید
Django - Home
جنگو یک چارچوب توسعه وب است که به ساخت و حفظ برنامه های کاربردی وب با کیفیت کمک می کند. جنگو به حذف کارهای تکراری کمک می کند و فرآیند توسعه را به تجربه ای آسان و صرفه جویی در زمان تبدیل می کند. این آموزش درک کاملی از جنگو می دهد.
Audience
این آموزش برای توسعه دهندگانی طراحی شده است که می خواهند یاد بگیرند که چگونه برنامه های کاربردی وب با کیفیت را با استفاده از تکنیک ها و ابزارهای هوشمند ارائه شده توسط جنگو توسعه دهند.
Prerequisites
قبل از ادامه، مطمئن شوید که اصول برنامه نویسی رویه ای و شی گرا را درک کرده اید: ساختارهای کنترل، ساختارهای داده و متغیرها، کلاس ها، اشیاء و غیره.
جنگو یک چارچوب وب سطح بالا پایتون است که توسعه سریع و طراحی تمیز و عملی را تشویق می کند. جنگو ساخت برنامه های وب بهتر را به سرعت و با کد کمتر آسان تر می کند.
توجه - جنگو یک علامت تجاری ثبت شده بنیاد نرم افزار جنگو است و تحت مجوز BSD tفعالیت می کند.
جنگو با فلسفه های طراحی زیر ارائه می شود :
Loosely Coupled
هدف جنگو این است که هر عنصر Stack خود را مستقل از بقیه کند.
Less Coding
کد کمتر به نوبه خود توسعه سریع.
Don't Repeat Yourself (DRY)
- همه چیز باید دقیقاً در یک مکان توسعه داده شود به جای تکرار دوباره و دوباره.
Fast Development
فلسفه جنگو این است که تمام تلاش خود را برای تسهیل توسعه سریع انجام دهد.
Clean Design
جنگو به شدت یک طراحی تمیز را در سراسر کد خود حفظ می کند و پیروی از بهترین شیوه های توسعه وب را آسان می کند.
Object-Relational Mapping (ORM) Support
جنگو پلی بین مدل داده و موتور پایگاه داده فراهم می کند و از مجموعه بزرگی از سیستم های پایگاه داده از جمله MySQL، Oracle، Postgres و غیره پشتیبانی می کند. جنگو همچنین از پایگاه داده NoSQL از طریق فورک جنگو-nonrel پشتیبانی می کند. در حال حاضر، تنها پایگاه داده های NoSQL پشتیبانی شده MongoDB و google app هستند
Multilingual Support
جنگو از طریق سیستم بین المللی سازی داخلی خود از وب سایت های چند زبانه پشتیبانی می کند. بنابراین می توانید وب سایت خود را توسعه دهید که از چندین زبان پشتیبانی می کند
Framework Support
جنگو دارای پشتیبانی داخلی از Ajax، RSS، Caching و فریمورک های مختلف دیگر است.
Administration GUI
جنگو یک رابط کاربری خوب و آماده برای استفاده برای فعالیت های اداری ارائه می دهد.
Development Environment
جنگو دارای یک وب سرور سبک وزن است تا توسعه و آزمایش برنامه های کاربردی را تسهیل کند.
همانطور که می دانید جنگو یک چارچوب وب پایتون است. و مانند اکثر فریم ورک های مدرن، جنگو از الگوی MVC پشتیبانی می کند. ابتدا بیایید ببینیم الگوی Model-View-Controller (MVC) چیست و سپس به ویژگی جنگو برای الگوی Model-View-Template (MVT) خواهیم پرداخت.
وقتی در مورد برنامه هایی که رابط کاربری (وب یا دسکتاپ) را ارائه می دهند صحبت می کنیم، معمولاً در مورد معماری MVC صحبت می کنیم. و همانطور که از نام آن پیداست، الگوی MVC بر اساس سه جزء است: Model، View و Controller. برای کسب اطلاعات بیشتر، آموزش MVC ما را اینجا ببینید.
Model-View-Template (MVT) کمی با MVC متفاوت است. در واقع تفاوت اصلی بین این دو الگو این است که خود جنگو از بخش Controller (کد نرم افزاری که تعاملات بین Model و View را کنترل می کند) مراقبت می کند و الگو را به ما واگذار می کند. این قالب یک فایل HTML است که با زبان قالب جنگو (DTL) ترکیب شده است.
نمودار زیر نشان می دهد که چگونه هر یک از اجزای الگوی MVT با یکدیگر تعامل می کنند تا یک درخواست کاربر را ارائه دهند -
توسعهدهنده مدل، نمای و قالب را ارائه میکند و سپس آن را به یک URL نگاشت میکند و جنگو کارهای جادویی را برای ارائه آن به کاربر انجام میدهد.
محیط توسعه جنگو شامل نصب و راه اندازی پایتون، جنگو و یک سیستم پایگاه داده است. از آنجایی که جنگو با برنامه های کاربردی وب سر و کار دارد، لازم به ذکر است که شما به راه اندازی وب سرور نیز نیاز دارید.
جنگو با کد 100% خالص پایتون نوشته شده است، بنابراین باید پایتون را روی سیستم خود نصب کنید. آخرین نسخه جنگو به پایتون 2.6.5 یا بالاتر نیاز دارد
اگر از آخرین توزیعهای لینوکس یا Mac OS X استفاده میکنید، احتمالاً از قبل پایتون را نصب کردهاید. می توانید با تایپ دستور پایتون در خط فرمان آن را تأیید کنید. اگر چیزی شبیه به این مشاهده کردید، پس پایتون نصب شده است.
$ python Python 2.7.5 (default, Jun 17 2014, 18:11:42) [GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2
در غیر این صورت می توانید آخرین نسخه پایتون را از لینک http://www.python.org/download دانلود و نصب کنید.
نصب جنگو بسیار آسان است، اما مراحل لازم برای نصب آن به سیستم عامل شما بستگی دارد. از آنجایی که پایتون یک زبان مستقل از پلتفرم است، جنگو یک بسته دارد که بدون در نظر گرفتن سیستم عامل شما در همه جا کار می کند.
آخرین نسخه جنگو را می توانید از لینک http://www.djangoproject.com/download دانلود کنید.
اگر سیستم عامل لینوکس یا مک را اجرا می کنید، دو راه برای نصب جنگو دارید - می توانید از مدیر بسته سیستم عامل خود استفاده کنید یا در صورت نصب از easy_install یا pip استفاده کنید. با استفاده از آرشیو رسمی که قبلا دانلود کرده اید، آن را به صورت دستی نصب کنید. ما گزینه دوم را پوشش خواهیم داد زیرا اولین مورد به توزیع سیستم عامل شما بستگی دارد. اگر تصمیم گرفته اید گزینه اول را دنبال کنید، فقط مراقب نسخه جنگویی که نصب می کنید باشید.
فرض کنید بایگانی خود را از لینک بالا دریافت کرده اید، باید چیزی شبیه به Django-x.xx.tar.gz باشد
$ tar xzvf Django-x.xx.tar.gz $ cd Django-x.xx $ sudo python setup.py install
You can test your installation by running this command
$ django-admin.py --version
اگر نسخه فعلی جنگو را روی صفحه نمایش می بینید، همه چیز تنظیم شده است.
Windows Installation
ما فرض می کنیم که بایگانی جنگو و پایتون خود را روی رایانه خود نصب کرده اید.
First, PATH verification.
در برخی از نسخه های ویندوز (ویندوز 7) ممکن است لازم باشد مطمئن شوید که متغیر Path system مسیر زیر را دارد، البته C:\Python34\;C:\Python34\Lib\site-packages\django\bin\. بسته به نسخه پایتون شما
Then, extract and install Django.
c:\>cd c:\Django-x.xx
سپس، جنگو را با اجرای دستور زیر نصب کنید که برای آن به مجوزهای مدیریتی در پوسته ویندوز "cmd" نیاز دارید -
c:\Django-x.xx>python setup.py install
برای آزمایش نصب خود، یک خط فرمان باز کنید و دستور زیر را تایپ کنید -
c:\>python -c "import django; print(django.get_version())"
اگر نسخه فعلی جنگو را روی صفحه نمایش می بینید، همه چیز تنظیم شده است. یا یک دستور cmd را اجرا کنید و python را تایپ کنید و سپس −
c:\> python >>> import django >>> django.VERSION
Step 3 – Database Setup
جنگو از چندین موتور اصلی پایگاه داده پشتیبانی می کند و شما می توانید هر یک از آنها را بر اساس راحتی خود تنظیم کنید.
Step 4 – Web Server
جنگو با یک وب سرور سبک وزن برای توسعه و آزمایش برنامه ها ارائه می شود. این سرور برای کار با جنگو از قبل پیکربندی شده است و مهمتر از آن، هر زمان که کد را تغییر دهید دوباره راه اندازی می شود. با این حال، جنگو از آپاچی و سایر وب سرورهای محبوب مانند Lighttpd پشتیبانی می کند. ما هر دو رویکرد را در فصل های آینده در حین کار با مثال های مختلف مورد بحث قرار خواهیم داد.
حالا که جنگو را نصب کردیم، بیایید شروع به استفاده از آن کنیم. در جنگو، هر برنامه وب که می خواهید ایجاد کنید پروژه نامیده می شود. و یک پروژه مجموعه ای از برنامه های کاربردی است. اپلیکیشن مجموعه ای از فایل های کد است که بر الگوی MVT تکیه دارند. به عنوان مثال فرض کنید می خواهیم یک وب سایت بسازیم، وب سایت پروژه ما است و انجمن، اخبار، موتور تماس برنامه های کاربردی هستند. این ساختار جابجایی یک برنامه را بین پروژه ها آسان تر می کند زیرا هر برنامه مستقلی است.
Create a Project
چه در ویندوز یا لینوکس هستید، فقط یک ترمینال یا یک دستور cmd دریافت کنید و به مکانی که می خواهید پروژه شما ایجاد شود بروید، سپس از این کد استفاده کنید -
$ django-admin startproject myproject
این یک پوشه "myproject" با ساختار زیر ایجاد می کند:
myproject/ manage.py myproject/ __init__.py settings.py urls.py wsgi.py
The Project Structure
پوشه "myproject" فقط محفظه پروژه شماست، در واقع شامل دو عنصر - است
manage.py
این فایل نوعی django-admin محلی پروژه شما برای تعامل با پروژه شما از طریق خط فرمان (راه اندازی سرور توسعه، همگام سازی db...) است. برای دریافت لیست کامل دستورات قابل دسترسی از طریق manager.py می توانید از کد − استفاده کنید
$ python manage.py help
The “myproject” subfolder −
این پوشه بسته پایتون واقعی پروژه شما است. شامل چهار فایل:
__init__.py − فقط برای پایتون، این پوشه را به عنوان بسته در نظر بگیرید.
settings.py − همانطور که از نام آن مشخص است، تنظیمات پروژه شما.
urls.py − همه پیوندهای پروژه شما و عملکردی که باید فراخوانی کنید. نوعی ToC پروژه شما.
wsgi.py −اگر نیاز به استقرار پروژه خود بر روی WSGI دارید.
Setting Up Your Project
پروژه شما در زیر پوشه myproject/settings.py تنظیم شده است. در زیر چند گزینه مهم وجود دارد که ممکن است نیاز به تنظیم داشته باشید -
DEBUG = True
این گزینه به شما امکان می دهد تعیین کنید که آیا پروژه شما در حالت اشکال زدایی است یا خیر. حالت Debug به شما امکان می دهد اطلاعات بیشتری در مورد خطای پروژه خود دریافت کنید. هرگز آن را برای یک پروژه زنده روی "True" تنظیم نکنید. با این حال، اگر میخواهید سرور Django light فایلهای استاتیک را ارائه دهد، باید روی «درست» تنظیم شود. این کار را فقط در حالت توسعه انجام دهید.
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'database.sql', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } }
پایگاه داده در فرهنگ لغت "پایگاه داده" تنظیم شده است. مثال بالا برای موتور SQLite است. همانطور که قبلا گفته شد، جنگو از − نیز پشتیبانی می کند
قبل از تنظیم هر موتور جدید، مطمئن شوید که درایور صحیح db را نصب کرده اید.
همچنین می توانید گزینه های دیگری مانند:
TIME_ZONE, LANGUAGE_CODE, TEMPLATE…
اکنون که پروژه شما ایجاد و پیکربندی شده است، مطمئن شوید که کار می کند -
$ python manage.py runserver
با اجرای کد بالا چیزی شبیه به زیر دریافت خواهید کرد
Validating models... 0 errors found September 03, 2015 - 11:41:50 Django version 1.6.11, using settings 'myproject.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
یک پروژه مجموعه ای از برنامه های کاربردی زیاد است. هر برنامه یک هدف دارد و می تواند مجدداً در پروژه دیگری استفاده شود، مانند فرم تماس در یک وب سایت می تواند یک برنامه کاربردی باشد و می تواند برای دیگران استفاده مجدد شود. آن را به عنوان یک ماژول از پروژه خود ببینید.
ما فرض می کنیم که شما در پوشه پروژه خود هستید. در پوشه اصلی "myproject" ما، همان پوشه و سپس manager.py −
$ python manage.py startapp myapp
شما به تازگی برنامه myapp را ایجاد کرده اید و مانند پروژه، جنگو یک پوشه "myapp" با ساختار برنامه ایجاد می کند -
myapp/ __init__.py admin.py models.py tests.py views.py
در این مرحله ما برنامه "myapp" خود را داریم، اکنون باید آن را با پروژه جنگو "myproject" خود ثبت کنیم. برای انجام این کار، INSTALLED_APPS tuple را در فایل settings.py پروژه خود به روز کنید (نام برنامه خود را اضافه کنید) -
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', )
جنگو یک رابط کاربری آماده برای استفاده برای فعالیت های اداری ارائه می دهد. همه ما می دانیم که چگونه یک رابط مدیر برای یک پروژه وب مهم است. جنگو به طور خودکار رابط کاربری مدیریت را بر اساس مدل های پروژه شما ایجاد می کند.
رابط مدیریت به ماژول django.countrib بستگی دارد. برای اینکه کار کند، باید مطمئن شوید که برخی از ماژولها در INSTALLED_APPS و MIDDLEWARE_CLASSES فایل myproject/settings.py وارد شدهاند.
For INSTALLED_APPS make sure you have −
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', )
For MIDDLEWARE_CLASSES −
MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', )
قبل از راه اندازی سرور خود، برای دسترسی به رابط مدیریت خود، باید پایگاه داده را راه اندازی کنید -
$ python manage.py migrate
syncdb جداول یا مجموعه های لازم را بسته به نوع db شما ایجاد می کند، که برای اجرای رابط مدیریت لازم است. حتی اگر سوپرکاربر نداشته باشید، از شما خواسته می شود که یکی را ایجاد کنید.
اگر قبلاً یک ابرکاربر دارید یا آن را فراموش کردهاید، همیشه میتوانید با استفاده از کد زیر یکی ایجاد کنید
$ python manage.py createsuperuser
اکنون برای شروع رابط مدیریت، باید مطمئن شویم که یک URL برای رابط مدیریت خود پیکربندی کرده ایم. myproject را باز کنید
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', 'myproject.views.home', name = 'home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), )
Now just run the server.
$ python manage.py runserver
And your admin interface is accessible at: http://127.0.0.1:8000/admin/
Once connected with your superuser account, you will see the following screen −
این رابط به شما امکان می دهد گروه ها و کاربران جنگو و همه مدل های ثبت شده در برنامه خود را مدیریت کنید. این رابط به شما این توانایی را می دهد که حداقل عملیات CRUD (ایجاد، خواندن، به روز رسانی، حذف) را روی مدل های خود انجام دهید.
تابع view یا به اختصار "view" به سادگی یک تابع پایتون است که یک درخواست وب را می گیرد و یک پاسخ وب را برمی گرداند. این پاسخ می تواند محتویات HTML یک صفحه وب، یا تغییر مسیر، یا یک خطای 404، یا یک سند XML، یا یک تصویر و غیره باشد. مثال: شما از view برای ایجاد صفحات وب استفاده می کنید، توجه داشته باشید که باید یک نما را مرتبط کنید. به یک URL برای دیدن آن به عنوان یک صفحه وب. در جنگو، نماها باید در فایل views.py برنامه ایجاد شوند.
ما یک نمای ساده در myapp ایجاد می کنیم تا بگوییم "به برنامه من خوش آمدید!"
See the following view −
from django.http import HttpResponse def hello(request): text = """<h1>welcome to my app !</h1>""" return HttpResponse(text)
در این نما، ما از HttpResponse برای رندر HTML استفاده میکنیم (همانطور که احتمالاً متوجه شدهاید که HTML به صورت سخت در نما کدگذاری شده است). برای دیدن این نما به عنوان یک صفحه، فقط باید آن را به یک URL ترسیم کنیم (این مورد در فصل آینده مورد بحث قرار خواهد گرفت).
ما از HttpResponse برای رندر HTML در نمای قبلی استفاده کردیم. این بهترین راه برای رندر صفحات نیست. جنگو از الگوی MVT پشتیبانی می کند، بنابراین برای ایجاد نمای قبلی، مانند جنگو - MVT، به آن نیاز داریم -
A template: myapp/templates/hello.html
And now our view will look like −
from django.shortcuts import render def hello(request): return render(request, "myapp/template/hello.html", {})
Views can also accept parameters −
from django.http import HttpResponse def hello(request, number): text = "<h1>welcome to my app number %s!</h1>"% number return HttpResponse(text)
هنگامی که به یک URL پیوند داده می شود، صفحه شماره ارسال شده را به عنوان پارامتر نمایش می دهد. توجه داشته باشید که پارامترها از طریق URL ارسال می شوند (در فصل بعدی بحث شده است).
اکنون که یک نمای کاری داریم همانطور که در فصل های قبل توضیح داده شد. ما می خواهیم از طریق URL به آن نمای دسترسی پیدا کنیم. جنگو راه خاص خود را برای نقشه برداری URL دارد و با ویرایش فایل url.py پروژه شما (myproject) انجام می شود
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', #Examples #url(r'^$', 'myproject.view.home', name = 'home'), #url(r'^blog/', include('blog.urls')), url(r'^admin', include(admin.site.urls)), )
هنگامی که کاربر درخواستی برای صفحه ای در برنامه وب شما می کند، کنترلر جنگو وظیفه جستجوی نمای مربوطه را از طریق فایل url.py می کند و سپس پاسخ HTML یا خطای 404 not found را، در صورتی که پیدا نشد، برمی گرداند. در url.py، مهمترین چیز تاپل "urlpatterns" است. جایی است که شما نگاشت بین URL ها و نماها را تعریف می کنید. نقشه برداری یک تاپل در الگوهای URL مانند - است
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', #Examples #url(r'^$', 'myproject.view.home', name = 'home'), #url(r'^blog/', include('blog.urls')), url(r'^admin', include(admin.site.urls)), url(r'^hello/', 'myapp.views.hello', name = 'hello'), )
خط علامت گذاری شده نشانی اینترنتی را نشان می دهد
تا کنون URL ها را در فایل myprojects/url.py ایجاد کرده ایم، اما همانطور که قبلا در مورد جنگو و ایجاد یک برنامه گفته شد، بهترین نکته این بود که بتوانیم از برنامه ها در پروژه های مختلف استفاده مجدد کنیم. اگر همه URL های خود را در فایل "projecturl.py" ذخیره کنید، به راحتی می توانید ببینید مشکل چیست. بنابراین بهترین روش این است که یک "url.py" برای هر برنامه ایجاد کنید و آن را در فایل url.py پروژه های اصلی خود بگنجانید (ما قبلا URL های مدیریت را برای رابط مدیر قرار داده بودیم).
چگونه انجام می شود؟
ما باید با استفاده از کد زیر یک فایل url.py در myapp ایجاد کنیم
from django.conf.urls import patterns, include, url urlpatterns = patterns('', url(r'^hello/', 'myapp.views.hello', name = 'hello'),)
Then myproject/url.py will change to the following −
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', #Examples #url(r'^$', 'myproject.view.home', name = 'home'), #url(r'^blog/', include('blog.urls')), url(r'^admin', include(admin.site.urls)), url(r'^myapp/', include('myapp.urls')), )
ما همه URL ها را از برنامه myapp اضافه کرده ایم. home.html که از طریق «
حالا بیایید تصور کنیم که نمای دیگری در myapp "morning" داریم و میخواهیم آن را در myapp ترسیم کنیم
from django.conf.urls import patterns, include, url urlpatterns = patterns('', url(r'^hello/', 'myapp.views.hello', name = 'hello'), url(r'^morning/', 'myapp.views.morning', name = 'morning'), )
This can be re-factored to −
from django.conf.urls import patterns, include, url urlpatterns = patterns('myapp.views', url(r'^hello/', 'hello', name = 'hello'), url(r'^morning/', 'morning', name = 'morning'),)
همانطور که می بینید، ما اکنون از اولین عنصر تاپل urlpattern خود استفاده می کنیم. این می تواند زمانی مفید باشد که می خواهید نام برنامه خود را تغییر دهید.
Sending Parameters to Views
اکنون می دانیم که چگونه URL را نقشه برداری کنیم، چگونه آنها را سازماندهی کنیم، اکنون اجازه دهید نحوه ارسال پارامترها را به نماها ببینیم. یک نمونه کلاسیک نمونه مقاله است (شما می خواهید به مقاله از طریق " دسترسی داشته باشید
from django.shortcuts import render from django.http import HttpResponse def hello(request): return render(request, "hello.html", {}) def viewArticle(request, articleId): text = "Displaying article Number : %s"%articleId return HttpResponse(text)
ما می خواهیم آن را در myapp/url.py ترسیم کنیم تا بتوانیم از طریق "/myapp/article/articleId" به آن دسترسی داشته باشیم، در "myapp/url.py" به موارد زیر نیاز داریم -
from django.conf.urls import patterns, include, url urlpatterns = patterns('myapp.views', url(r'^hello/', 'hello', name = 'hello'), url(r'^morning/', 'morning', name = 'morning'), url(r'^article/(\d+)/', 'viewArticle', name = 'article'),)
وقتی جنگو url را ببیند: "/myapp/article/42" پارامترهای '42' را به viewArticle view منتقل می کند و در مرورگر خود باید نتیجه زیر را دریافت کنید -
from django.shortcuts import render from django.http import HttpResponse def hello(request): return render(request, "hello.html", {}) def viewArticle(request, articleId): text = "Displaying article Number : %s"%articleId return HttpResponse(text) def viewArticle(request, month, year): text = "Displaying articles of : %s/%s"%(year, month) return HttpResponse(text)
The corresponding url.py file will look like −
from django.conf.urls import patterns, include, url urlpatterns = patterns('myapp.views', url(r'^hello/', 'hello', name = 'hello'), url(r'^morning/', 'morning', name = 'morning'), url(r'^article/(\d+)/', 'viewArticle', name = 'article'), url(r'^articles/(\d{2})/(\d{4})', 'viewArticles', name = 'articles'),)
اکنون وقتی به "/myapp/articles/12/2006/" می روید، "نمایش مقالات: 2006/12" را دریافت می کنید، اما اگر پارامترها را معکوس کنید، نتیجه مشابهی دریافت نمی کنید.
برای جلوگیری از آن، می توان یک پارامتر URL را به پارامتر view پیوند داد. برای آن، url.py ما − خواهد شد
from django.conf.urls import patterns, include, url urlpatterns = patterns('myapp.views', url(r'^hello/', 'hello', name = 'hello'), url(r'^morning/', 'morning', name = 'morning'), url(r'^article/(\d+)/', 'viewArticle', name = 'article'), url(r'^articles/(?P\d{2})/(?P\d{4})', 'viewArticles', name = 'articles'),)
جنگو امکان جداسازی پایتون و HTML را فراهم می کند، پایتون در view ها و HTML در قالب ها قرار می گیرد. برای پیوند این دو، جنگو به تابع رندر و زبان قالب جنگو متکی است.
این تابع سه پارامتر می گیرد
Request −درخواست اولیه
موتور قالب جنگو یک زبان کوچک برای تعریف لایه رو به روی کاربر برنامه ارائه می دهد.
یک متغیر به این شکل است: {{متغیر}}. الگو با متغیر ارسال شده توسط view در پارامتر سوم تابع رندر جایگزین متغیر می شود. بیایید hello.html خود را برای نمایش تاریخ امروز تغییر دهیم -
hello.html
<html> <body> Hello World!!!<p>Today is {{today}}</p> </body> </html>
Then our view will change to −
def hello(request): today = datetime.datetime.now().date() return render(request, "hello.html", {"today" : today})
اکنون پس از دسترسی به URL خروجی زیر را دریافت خواهیم کرد
Hello World!!! Today is Sept. 11, 2015
همانطور که احتمالا متوجه شده اید، اگر متغیر یک رشته نباشد، جنگو از متد __str__ برای نمایش آن استفاده می کند. و با همان اصل می توانید به یک ویژگی شی دسترسی داشته باشید، درست مانند آنچه در پایتون انجام می دهید. به عنوان مثال: اگر بخواهیم تاریخ سال را نمایش دهیم، متغیر من این خواهد بود: {{today.year}}.
آنها به شما کمک می کنند تا متغیرها را در زمان نمایش تغییر دهید. ساختار فیلترها به شکل زیر است:
{{var|filters}}.
Some examples −
همچنین می توانید پیش فرض را برای یک متغیر تنظیم کنید.
برچسبها به شما امکان میدهند عملیات زیر را انجام دهید: if condition، برای حلقه، وراثت الگو و موارد دیگر.
برچسبها به شما امکان میدهند عملیات زیر را انجام دهید: if condition، برای حلقه، وراثت الگو و موارد دیگر.
<html> <body> Hello World!!!<p>Today is {{today}}</p> We are {% if today.day == 1 %} the first day of month. {% elif today.day == 30 %} the last day of month. {% else %} I don't know. {%endif%} </body> </html>
در این قالب جدید، بسته به تاریخ روز، قالب مقدار مشخصی را ارائه می دهد.
دقیقاً مانند «if»، تگ «for» را داریم که دقیقاً مانند پایتون کار می کند. بیایید نمای hello خود را تغییر دهیم تا لیستی را به الگوی خود منتقل کنیم -
def hello(request): today = datetime.datetime.now().date() daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] return render(request, "hello.html", {"today" : today, "days_of_week" : daysOfWeek})
The template to display that list using {{ for }} −
<html> <body> Hello World!!!<p>Today is {{today}}</p> We are {% if today.day == 1 %} the first day of month. {% elif today.day == 30 %} the last day of month. {% else %} I don't know. {%endif%} <p> {% for day in days_of_week %} {{day}} </p> {% endfor %} </body> </html>
And we should get something like −
Hello World!!! Today is Sept. 11, 2015 We are I don't know. Mon Tue Wed Thu Fri Sat Sun
یک سیستم قالب نمی تواند بدون وراثت الگو کامل شود. به این معنی که وقتی قالب های خود را طراحی می کنید، باید یک الگوی اصلی با حفره هایی داشته باشید که الگوی کودک با توجه به نیاز خود آن ها را پر می کند، مانند اینکه ممکن است یک صفحه برای برگه انتخاب شده به css خاصی نیاز داشته باشد.
بیایید الگوی hello.html را به ارث بردن از main_template.html تغییر دهیم.
main_template.html
<html> <head> <title> {% block title %}Page Title{% endblock %} </title> </head> <body> {% block content %} Body content {% endblock %} </body> </html>
hello.html
در مثال بالا، با فراخوانی /myapp/hello، همچنان همان نتیجه قبلی را خواهیم داشت، اما اکنون برای بازگرداندن کد خود به extensions و block تکیه می کنیم.
در main_template.html بلوک ها را با استفاده از بلوک تگ تعریف می کنیم. بلوک عنوان حاوی عنوان صفحه و بلوک محتوا محتوای اصلی صفحه خواهد بود. در home.html از extensions برای ارث بردن از main_template.html استفاده می کنیم سپس بلوک تعریف شده در بالا (محتوا و عنوان) را پر می کنیم.
تگ کامنت به تعریف نظرات در قالب ها کمک می کند، نه نظرات HTML، آنها در صفحه HTML ظاهر نمی شوند. این می تواند برای مستندسازی یا فقط نظر دادن یک خط کد مفید باشد.
مدل کلاسی است که جدول یا مجموعه را در DB ما نشان می دهد و هر ویژگی کلاس فیلدی از جدول یا مجموعه است. مدل ها در برنامه تعریف شده است
Following is a Dreamreal model created as an example −
from django.db import models class Dreamreal(models.Model): website = models.CharField(max_length = 50) mail = models.CharField(max_length = 50) name = models.CharField(max_length = 50) phonenumber = models.IntegerField() class Meta: db_table = "dreamreal"
هر مدلی از django.db.models.Model ارث می برد. کلاس ما دارای 4 ویژگی (3 CharField و 1 Integer) است که اینها فیلدهای جدول خواهند بود. کلاس Meta با ویژگی db_table به ما امکان می دهد تا جدول یا نام مجموعه واقعی را تعریف کنیم. جنگو به طور خودکار جدول یا مجموعه را نامگذاری می کند: myapp_modelName. این کلاس به شما امکان می دهد نام جدول را به چیزی که دوست دارید مجبور کنید. نوع فیلدهای بیشتری در django.db.models وجود دارد که می توانید در https در مورد آنها اطلاعات بیشتری کسب کنید:
$python manage.py syncdb
Manipulating Data (CRUD)
بیایید یک نمای "crudops" ایجاد کنیم تا ببینیم چگونه می توانیم عملیات CRUD را روی مدل ها انجام دهیم. برنامه ما
myapp/views.py
from myapp.models import Dreamreal from django.http import HttpResponse def crudops(request): #Creating an entry dreamreal = Dreamreal( website = "www.polo.com", mail = "sorex@polo.com", name = "sorex", phonenumber = "002376970" ) dreamreal.save() #Read ALL entries objects = Dreamreal.objects.all() res ='Printing all Dreamreal entries in the DB : <br>' for elt in objects: res += elt.name+"<br>" #Read a specific entry: sorex = Dreamreal.objects.get(name = "sorex") res += 'Printing One entry <br>' res += sorex.name #Delete an entry res += '<br> Deleting an entry <br>' sorex.delete() #Update dreamreal = Dreamreal( website = "www.polo.com", mail = "sorex@polo.com", name = "sorex", phonenumber = "002376970" ) dreamreal.save() res += 'Updating entry<br>' dreamreal = Dreamreal.objects.get(name = 'sorex') dreamreal.name = 'thierry' dreamreal.save() return HttpResponse(res)
Other Data Manipulation
بیایید دستکاری های دیگری را که می توانیم روی Models انجام دهیم را بررسی کنیم. توجه داشته باشید که عملیات CRUD بر روی نمونه هایی از مدل ما انجام شد، اکنون ما مستقیماً با کلاسی که مدل ما را نشان می دهد کار خواهیم کرد.
Let's create a 'datamanipulation' view in myapp/views.py
from myapp.models import Dreamreal from django.http import HttpResponse def datamanipulation(request): res = '' #Filtering data: qs = Dreamreal.objects.filter(name = "paul") res += "Found : %s results<br>"%len(qs) #Ordering results qs = Dreamreal.objects.order_by("name") for elt in qs: res += elt.name + '<br>' return HttpResponse(res)
Linking Models
Django ORM 3 راه برای پیوند مدل ها ارائه می دهد - یکی از اولین مواردی که در اینجا خواهیم دید، روابط یک به چند است. همانطور که در مثال بالا مشاهده می کنید، شرکت Dreamreal می تواند چندین وب سایت آنلاین داشته باشد. تعریف آن رابطه با استفاده از django.db.models.ForeignKey انجام می شود
myapp/models.py
from django.db import models class Dreamreal(models.Model): website = models.CharField(max_length = 50) mail = models.CharField(max_length = 50) name = models.CharField(max_length = 50) phonenumber = models.IntegerField() online = models.ForeignKey('Online', default = 1) class Meta: db_table = "dreamreal" class Online(models.Model): domain = models.CharField(max_length = 30) class Meta: db_table = "online"
همانطور که در myapp/models.py به روز شده مشاهده می کنید، ما مدل آنلاین را اضافه کرده و آن را به مدل Dreamreal خود پیوند دادیم.
بیایید بررسی کنیم که چگونه همه اینها از طریق shell manager.py − کار می کنند
ابتدا اجازه دهید چند شرکت (ورودی های Dreamreal) برای آزمایش در پوسته جنگو ایجاد کنیم -
$python manage.py shell >>> from myapp.models import Dreamreal, Online >>> dr1 = Dreamreal() >>> dr1.website = 'company1.com' >>> dr1.name = 'company1' >>> dr1.mail = 'contact@company1' >>> dr1.phonenumber = '12345' >>> dr1.save() >>> dr2 = Dreamreal() >>> dr1.website = 'company2.com' >>> dr2.website = 'company2.com' >>> dr2.name = 'company2' >>> dr2.mail = 'contact@company2' >>> dr2.phonenumber = '56789' >>> dr2.save()
Now some hosted domains −
>>> on1 = Online() >>> on1.company = dr1 >>> on1.domain = "site1.com" >>> on2 = Online() >>> on2.company = dr1 >>> on2.domain = "site2.com" >>> on3 = Online() >>> on3.domain = "site3.com" >>> dr2 = Dreamreal.objects.all()[2] >>> on3.company = dr2 >>> on1.save() >>> on2.save() >>> on3.save()
دسترسی به ویژگی شرکت میزبان (ورودی Dreamreal) از یک دامنه آنلاین ساده است -
>>> on1.company.name
و اگر بخواهیم تمام دامنه آنلاین میزبانی شده توسط یک شرکت در Dreamreal را بدانیم، از کد - استفاده خواهیم کرد
>>> dr1.online_set.all()
>>> dr1.online_set.all() برای دریافت QuerySet، توجه داشته باشید که تمام روش های دستکاری که قبلا دیده ایم (filter, all, exclude, order_by...) همچنین می توانید به ویژگی های مدل پیوند شده برای عملیات فیلتر دسترسی داشته باشید. میگویید که میخواهید همه دامنههای آنلاینی را که نام Dreamreal حاوی "شرکت" است، دریافت کنید
>>> Online.objects.filter(company__name__contains = 'company'
توجه - این نوع پرس و جو فقط برای SQL DB پشتیبانی می شود. برای DB غیر رابطه ای که در آن Join وجود ندارد و دو "_" وجود دارد، کار نمی کند. اما این تنها راه برای پیوند دادن مدل ها نیست، شما همچنین OneToOneField دارید، پیوندی که تضمین می کند که رابطه بین دو شی منحصر به فرد است. اگر در مثال بالا از OneToOneField استفاده کنیم، به این معنی است که برای هر ورودی Dreamreal فقط یک ورودی آنلاین و از راه دیگر امکان پذیر است. و آخرین مورد، ManyToManyField برای (n-n) رابطه بین جداول. توجه داشته باشید، این موارد مربوط به DB مبتنی بر SQL هستند.
تغییر مسیر صفحه به دلایل زیادی در برنامه وب مورد نیاز است. ممکن است بخواهید زمانی که یک عمل خاص اتفاق می افتد یا اساساً در صورت بروز خطا، کاربر را به صفحه دیگری هدایت کنید. به عنوان مثال، هنگامی که کاربر وارد وب سایت شما می شود، اغلب به صفحه اصلی اصلی یا داشبورد شخصی خود هدایت می شود. در جنگو، تغییر مسیر با استفاده از روش 'redirect' انجام می شود.
متد 'redirect' به عنوان آرگومان در نظر گرفته میشود: نشانی اینترنتی که میخواهید به عنوان نام یک view's name به آن هدایت شود.
The myapp/views looks like the following so far −
def hello(request): today = datetime.datetime.now().date() daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] return render(request, "hello.html", {"today" : today, "days_of_week" : daysOfWeek}) def viewArticle(request, articleId): """ A view that display an article based on his ID""" text = "Displaying article Number : %s" %articleId return HttpResponse(text) def viewArticles(request, year, month): text = "Displaying articles of : %s/%s"%(year, month) return HttpResponse(text)
Let's change the hello view to redirect to djangoproject.com and our viewArticle to redirect to our internal '/myapp/articles'. To do so the myapp/view.py will change to
from django.shortcuts import render, redirect from django.http import HttpResponse import datetime # Create your views here. def hello(request): today = datetime.datetime.now().date() daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] return redirect("https://www.djangoproject.com") def viewArticle(request, articleId): """ A view that display an article based on his ID""" text = "Displaying article Number : %s" %articleId return redirect(viewArticles, year = "2045", month = "02") def viewArticles(request, year, month): text = "Displaying articles of : %s/%s"%(year, month) return HttpResponse(text)
در مثال بالا، ابتدا ریدایرکت را از django.shortcuts وارد کردیم و برای تغییر مسیر به وب سایت رسمی جنگو، فقط URL کامل را به روش 'redirect' به عنوان رشته ارسال می کنیم و برای مثال دوم (نمای viewArticle) 'redirect' را ارسال می کنیم. متد نام view و پارامترهای آن را به عنوان آرگومان می گیرد.
Accessing /myapp/hello, will give you the following screen
And accessing /myapp/article/42, will give you the following screen −
همچنین می توان با افزودن پارامتر دائمی = True مشخص کرد که 'redirect' موقت است یا دائم. کاربر هیچ تفاوتی نمی بیند، اما اینها جزئیاتی هستند که موتورهای جستجو هنگام رتبه بندی وب سایت شما در نظر می گیرند.
همچنین به یاد داشته باشید که پارامتر "name" را در url.py خود در حین نگاشت URL ها تعریف کردیم -
url(r'^articles/(?P\d{2})/(?P\d{4})/', 'viewArticles', name = 'articles'),
این نام (در اینجا مقاله) می تواند به عنوان استدلال برای روش 'redirect' استفاده شود، سپس تغییر مسیر viewArticle ما می تواند از
def viewArticle(request, articleId): """ A view that display an article based on his ID""" text = "Displaying article Number : %s" %articleId return redirect(viewArticles, year = "2045", month = "02")
TO
def viewArticle(request, articleId): """ A view that display an article based on his ID""" text = "Displaying article Number : %s" %articleId return redirect(articles, year = "2045", month = "02")
توجه - همچنین یک تابع برای تولید URL وجود دارد. از آن به همان شیوه تغییر مسیر استفاده می شود. روش "reverse" (django.core.urlresolvers.reverse). این تابع یک شی HttpResponseRedirect را بر نمی گرداند، بلکه فقط یک رشته حاوی URL به نمای کامپایل شده با هر آرگومان ارسال شده است.
جنگو با یک موتور سبک آماده و آسان برای ارسال ایمیل ارائه می شود. مشابه پایتون شما فقط نیاز به واردات smtplib دارید. در جنگو فقط باید django.core.mail را وارد کنید. برای شروع ارسال ایمیل، فایل settings.py پروژه خود را ویرایش کرده و گزینه های زیر را تنظیم کنید
Let's create a "sendSimpleEmail" view to send a simple e-mail.
from django.core.mail import send_mail from django.http import HttpResponse def sendSimpleEmail(request,emailto): res = send_mail("hello paul", "comment tu vas?", "paul@polo.com", [emailto]) return HttpResponse('%s'%res)
در اینجا جزئیات پارامترهای send_mail - آمده است
Let's create a URL to access our view −
from django.conf.urls import patterns, url
urlpatterns = paterns('myapp.views', url(r'^simpleemail/(?P<emailto>
[\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/',
'sendSimpleEmail' , name = 'sendSimpleEmail'),)
So when accessing /myapp/simpleemail/polo@gmail.com, you will get the following page −
Sending Multiple Mails with send_mass_mail
این روش تعداد پیام هایی که با موفقیت تحویل داده شده است را برمی گرداند. این همان send_mail است اما یک پارامتر اضافی می گیرد. datatuple، نمای sendMassEmail ما پس از آن − خواهد بود
from django.core.mail import send_mass_mail from django.http import HttpResponse def sendMassEmail(request,emailto): msg1 = ('subject 1', 'message 1', 'polo@polo.com', [emailto1]) msg2 = ('subject 2', 'message 2', 'polo@polo.com', [emailto2]) res = send_mass_mail((msg1, msg2), fail_silently = False) return HttpResponse('%s'%res)
Let's create a URL to access our view −
rom django.conf.urls import patterns, url urlpatterns = paterns('myapp.views', url(r'^massEmail/(?P<emailto1> [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/(?P<emailto2> [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})', 'sendMassEmail' , name = 'sendMassEmail'),)
When accessing /myapp/massemail/polo@gmail.com/sorex@gmail.com/, we get −
send_mass_mail parameters details are −
همانطور که در تصویر بالا مشاهده می کنید، دو پیام با موفقیت ارسال شد. توجه - در این مثال ما از سرور اشکال زدایی smtp پایتون استفاده می کنیم که می توانید با استفاده از - راه اندازی کنید.
$python -m smtpd -n -c DebuggingServer localhost:1025
این بدان معنی است که تمام ایمیل های ارسالی شما در stdout چاپ می شود و سرور ساختگی روی localhost:1025 اجرا می شود.
Sending e-mails to admins and managers using mail_admins and mail_managers methods
ارسال ایمیل به ادمین ها و مدیران با استفاده از روش های mail_admins و mail_managers
ADMINS = (('polo', 'polo@polo.com'),)
MANAGERS = (('popoli', 'popoli@polo.com'),)
from django.core.mail import mail_admins from django.http import HttpResponse def sendAdminsEmail(request): res = mail_admins('my subject', 'site is going down.') return HttpResponse('%s'%res)
کد بالا برای هر مدیری که در قسمت ADMINS تعریف شده است یک ایمیل ارسال می کند.
from django.core.mail import mail_managers from django.http import HttpResponse def sendManagersEmail(request): res = mail_managers('my subject 2', 'Change date on the site.') return HttpResponse('%s'%res)
کد بالا برای هر مدیری که در قسمت MANAGERS تعریف شده است یک ایمیل ارسال می کند.
Parameters details −
Sending HTML E-mail
Sending HTML message in Django >= 1.7 is as easy as −
from django.core.mail import send_mail from django.http import HttpResponse res = send_mail("hello paul", "comment tu vas?", "paul@polo.com", ["polo@gmail.com"], html_message=")
این یک ایمیل چند بخشی/جایگزین تولید می کند.
اما برای Django < 1.7 ارسال پیام های HTML از طریق کلاس django.core.mail.EmailMessage و سپس فراخوانی 'send' روی شی انجام می شود -
بیایید یک نمای "sendHTMLEmail" برای ارسال یک ایمیل HTML ایجاد کنیم.
from django.core.mail import EmailMessage from django.http import HttpResponse def sendHTMLEmail(request , emailto): html_content = "<strong>Comment tu vas?</strong>" email = EmailMessage("my subject", html_content, "paul@polo.com", [emailto]) email.content_subtype = "html" res = email.send() return HttpResponse('%s'%res)
Parameters details for the EmailMessage class creation −
Let's create a URL to access our view −
from django.conf.urls import patterns, url urlpatterns = paterns('myapp.views', url(r'^htmlemail/(?P<emailto> [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/', 'sendHTMLEmail' , name = 'sendHTMLEmail'),)
When accessing /myapp/htmlemail/polo@gmail.com, we get −
این کار با استفاده از روش "پیوست" در شی EmailMessage انجام می شود. نمای ارسال ایمیل با پیوست − خواهد بود
from django.core.mail import EmailMessage from django.http import HttpResponse def sendEmailWithAttach(request, emailto): html_content = "Comment tu vas?" email = EmailMessage("my subject", html_content, "paul@polo.com", emailto]) email.content_subtype = "html" fd = open('manage.py', 'r') email.attach('manage.py', fd.read(), 'text/plain') res = email.send() return HttpResponse('%s'%res)
Details on attach arguments −
در برخی موارد، نوشتن views، همانطور که قبلاً دیدیم، واقعاً سنگین است. تصور کنید به یک صفحه ثابت یا یک صفحه فهرست نیاز دارید. جنگو یک راه آسان برای تنظیم این نماهای ساده ارائه می دهد که به آن generic views. می گویند. برخلاف classic views، نماهای generic کلاس هستند نه توابع. جنگو مجموعه ای از کلاس ها را برای نماهای عمومی در django.views.generic ارائه می دهد و هر نمای عمومی یکی از آن کلاس ها یا کلاسی است که از یکی از آنها به ارث می رسد.
There are 10+ generic classes −
>>> import django.views.generic >>> dir(django.views.generic) ['ArchiveIndexView', 'CreateView', 'DateDetailView', 'DayArchiveView', 'DeleteView', 'DetailView', 'FormView', 'GenericViewError', 'ListView', 'MonthArchiveView', 'RedirectView', 'TemplateView', 'TodayArchiveView', 'UpdateView', 'View', 'WeekArchiveView', 'YearArchiveView', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'base', 'dates', 'detail', 'edit', 'list']
این را می توانید برای نمای عمومی خود استفاده کنید. بیایید به چند مثال نگاه کنیم تا ببینیم چگونه کار می کند.
بیایید یک صفحه استاتیک از قالب "static.html" منتشر کنیم.
Our static.html −
<html> <body> This is a static page!!! </body> </html>
If we did that the way we learned before, we would have to change the myapp/views.py to be −
from django.shortcuts import render def static(request): return render(request, 'static.html', {})
and myapp/urls.py to be −
from django.conf.urls import patterns, url urlpatterns = patterns("myapp.views", url(r'^static/', 'static', name = 'static'),)
The best way is to use generic views. For that, our myapp/views.py will become −
from django.views.generic import TemplateView class StaticView(TemplateView): template_name = "static.html"
And our myapp/urls.py we will be −
from myapp.views import StaticView from django.conf.urls import patterns urlpatterns = patterns("myapp.views", (r'^static/$', StaticView.as_view()),)
When accessing /myapp/static you get −
For the same result we can also, do the following −
from django.views.generic import TemplateView from django.conf.urls import patterns, url urlpatterns = patterns("myapp.views", url(r'^static/',TemplateView.as_view(template_name = 'static.html')),)
همانطور که می بینید، فقط باید فایل url.py را در روش دوم تغییر دهید.
List and Display Data from DB
ما قصد داریم تمام ورودی های مدل Dreamreal خود را لیست کنیم. انجام این کار با استفاده از کلاس نمای عمومی ListView آسان می شود. فایل url.py را ویرایش کنید و آن را به صورت - به روز کنید
from django.views.generic import ListView from django.conf.urls import patterns, url urlpatterns = patterns( "myapp.views", url(r'^dreamreals/', ListView.as_view(model = Dreamreal, template_name = "dreamreal_list.html")), )
نکته مهم در این مرحله این است که متغیری که از نمای عمومی به الگو عبور می کند object_list است. اگر میخواهید خودتان آن را نام ببرید، باید یک آرگومان context_object_name به متد as_view اضافه کنید. سپس url.py تبدیل به − می شود
from django.views.generic import ListView from django.conf.urls import patterns, url urlpatterns = patterns("myapp.views", url(r'^dreamreals/', ListView.as_view( template_name = "dreamreal_list.html")), model = Dreamreal, context_object_name = ”dreamreals_objects” ,)
The associated template will then be −
{% extends "main_template.html" %} {% block content %} Dreamreals:<p> {% for dr in object_list %} {{dr.name}}</p> {% endfor %} {% endblock %}
Accessing /myapp/dreamreals/ will produce the following page −
ایجاد فرم در جنگو، واقعا شبیه به ایجاد یک مدل است. در اینجا دوباره فقط باید از کلاس جنگو ارث بری کنیم و ویژگی های کلاس فیلدهای فرم خواهند بود. بیایید یک فایل forms.py را در پوشه myapp اضافه کنیم تا حاوی فرمهای برنامه ما باشد. ما یک فرم ورود ایجاد خواهیم کرد.
myapp/forms.py
#-*- coding: utf-8 -*- from django import forms class LoginForm(forms.Form): user = forms.CharField(max_length = 100) password = forms.CharField(widget = forms.PasswordInput())
همانطور که در بالا مشاهده شد، نوع فیلد می تواند آرگومان "ویجت" را برای رندر html بگیرد. در مورد ما، ما می خواهیم رمز عبور پنهان باشد، نمایش داده نشود. بسیاری از ویجت های دیگر در جنگو وجود دارند: DateInput برای تاریخ ها، CheckboxInput برای چک باکس ها و غیره.
دو نوع درخواست HTTP وجود دارد، GET و POST. در جنگو، شی درخواست ارسال شده به عنوان پارامتر به view شما دارای یک ویژگی به نام "method" است که در آن نوع درخواست تنظیم شده است، و تمام داده های ارسال شده از طریق POST از طریق دیکشنری request.POST قابل دسترسی است.
Let's create a login view in our myapp/views.py −
#-*- coding: utf-8 -*- from myapp.forms import LoginForm def login(request): username = "not logged in" if request.method == "POST": #Get the posted form MyLoginForm = LoginForm(request.POST) if MyLoginForm.is_valid(): username = MyLoginForm.cleaned_data['username'] else: MyLoginForm = Loginform() return render(request, 'loggedin.html', {"username" : username})
نمایش، نتیجه فرم ورود ارسال شده از طریق loggedin.html را نمایش می دهد. برای تست آن ابتدا به قالب فرم ورود نیاز داریم. بیایید آن را login.html بنامیم.
<html> <body> <form name = "form" action = "{% url "myapp.views.login" %}" method = "POST" >{% csrf_token %} <div style = "max-width:470px;"> <center> <input type = "text" style = "margin-left:20%;" placeholder = "Identifiant" name = "username" /> </center> </div> <br> <div style = "max-width:470px;"> <center> <input type = "password" style = "margin-left:20%;" placeholder = "password" name = "password" /> </center> </div> <br> <div style = "max-width:470px;"> <center> <button style = "border:0px; background-color:#4285F4; margin-top:8%; height:35px; width:80%;margin-left:19%;" type = "submit" value = "Login" > <strong>Login</strong> </button> </center> </div> </form> </body> </html>
این الگو یک فرم ورود به سیستم را نمایش می دهد و نتیجه را در نمای ورود ما در بالا ارسال می کند. احتمالاً متوجه برچسب موجود در قالب شده اید که فقط برای جلوگیری از حمله جعل درخواست متقابل (CSRF) به سایت شما است.
{% csrf_token %}
هنگامی که ما الگوی ورود به سیستم را داریم، به الگوی loggedin.html نیاز داریم که پس از درمان فرم ارائه می شود.
<html> <body> You are : <strong>{{username}}</strong> </body> </html>
Now, we just need our pair of URLs to get started: myapp/urls.py
from django.conf.urls import patterns, url from django.views.generic import TemplateView urlpatterns = patterns('myapp.views', url(r'^connection/',TemplateView.as_view(template_name = 'login.html')), url(r'^login/', 'login', name = 'login'))
When accessing "/myapp/connection", we will get the following login.html template rendered −
On the form post, the form is valid. In our case make sure to fill the two fields and you will get −
In the above example, when validating the form −
MyLoginForm.is_valid()
ما فقط از موتور اعتبار سنجی خود فرم جنگو استفاده کردیم، در مورد ما فقط مطمئن شدیم که فیلدها مورد نیاز هستند. اکنون بیایید سعی کنیم مطمئن شویم که کاربری که قصد ورود به سیستم را دارد در DB ما به عنوان ورودی Dreamreal وجود دارد. برای این کار، myapp را تغییر دهید
#-*- coding: utf-8 -*- from django import forms from myapp.models import Dreamreal class LoginForm(forms.Form): user = forms.CharField(max_length = 100) password = forms.CharField(widget = forms.PasswordInput()) def clean_message(self): username = self.cleaned_data.get("username") dbuser = Dreamreal.objects.filter(name = username) if not dbuser: raise forms.ValidationError("User does not exist in our db!") return username
حال پس از فراخوانی متد "is_valid"، تنها در صورتی که کاربر در پایگاه داده ما باشد، خروجی صحیح را دریافت خواهیم کرد. اگر میخواهید یک فیلد از فرم خود را بررسی کنید، فقط یک روش را که با "clean_" شروع میشود، سپس نام فیلد خود را به کلاس فرم خود اضافه کنید. بالا بردن فرم ها. ValidationError مهم است.
به طور کلی برای یک برنامه وب مفید است که بتواند فایل ها (تصویر نمایه، آهنگ ها، pdf، کلمات ...) را آپلود کند. بیایید در این فصل درباره نحوه آپلود فایل ها بحث کنیم.
قبل از شروع بازی با یک تصویر، مطمئن شوید که کتابخانه تصویر پایتون (PIL) را نصب کرده اید. اکنون برای نشان دادن بارگذاری یک تصویر، بیایید یک فرم نمایه در myapp/forms.py ایجاد کنیم -
#-*- coding: utf-8 -*- from django import forms class ProfileForm(forms.Form): name = forms.CharField(max_length = 100) picture = forms.ImageFields()
همانطور که می بینید، تفاوت اصلی در اینجا فقط forms.ImageField می باشد. ImageField مطمئن می شود که فایل آپلود شده یک تصویر است. در غیر این صورت، اعتبار سنجی فرم ناموفق خواهد بود. اکنون بیایید یک مدل «نمایه» برای ذخیره نمایه آپلود شده خود ایجاد کنیم. این کار در myapp انجام می شود
اکنون بیایید یک مدل «نمایه» برای ذخیره نمایه آپلود شده خود ایجاد کنیم. این کار در myapp انجام می شود
from django.db import models class Profile(models.Model): name = models.CharField(max_length = 50) picture = models.ImageField(upload_to = 'pictures') class Meta: db_table = "profile"
همانطور که برای مدل می بینید، ImageField یک آرگومان اجباری می گیرد: upload_to. این نشان دهنده مکانی روی هارد دیسک است که تصاویر شما در آن ذخیره می شوند. توجه داشته باشید که این پارامتر به گزینه MEDIA_ROOT تعریف شده در فایل settings.py شما اضافه خواهد شد.
#-*- coding: utf-8 -*- from myapp.forms import ProfileForm from myapp.models import Profile def SaveProfile(request): saved = False if request.method == "POST": #Get the posted form MyProfileForm = ProfileForm(request.POST, request.FILES) if MyProfileForm.is_valid(): profile = Profile() profile.name = MyProfileForm.cleaned_data["name"] profile.picture = MyProfileForm.cleaned_data["picture"] profile.save() saved = True else: MyProfileForm = Profileform() return render(request, 'saved.html', locals())
قسمتی که نباید از دست داد این است که هنگام ایجاد یک ProfileForm یک تغییر ایجاد می شود، ما یک پارامتر دوم اضافه کردیم: request.FILES. در صورت عدم تصویب، اعتبار سنجی فرم با شکست مواجه می شود و پیامی می دهد که می گوید تصویر خالی است. اکنون، ما فقط به قالب saved.html و قالب profile.html برای فرم و صفحه تغییر مسیر نیاز داریم -
myapp/templates/saved.html −
<html> <body> {% if saved %} <strong>Your profile was saved.</strong> {% endif %} {% if not saved %} <strong>Your profile was not saved.</strong> {% endif %} </body> </html>
myapp/templates/profile.html −
<html> <body> <form name = "form" enctype = "multipart/form-data" action = "{% url "myapp.views.SaveProfile" %}" method = "POST" >{% csrf_token %} <div style = "max-width:470px;"> <center> <input type = "text" style = "margin-left:20%;" placeholder = "Name" name = "name" /> </center> </div> <br> <div style = "max-width:470px;"> <center> <input type = "file" style = "margin-left:20%;" placeholder = "Picture" name = "picture" /> </center> </div> <br> <div style = "max-width:470px;"> <center> <button style = "border:0px;background-color:#4285F4; margin-top:8%; height:35px; width:80%; margin-left:19%;" type = "submit" value = "Login" > <strong>Login</strong> </button> </center> </div> </form> </body> </html>
در مرحله بعد، برای شروع به جفت URL های خود نیاز داریم:
myapp/urls.py
from django.conf.urls import patterns, url from django.views.generic import TemplateView urlpatterns = patterns( 'myapp.views', url(r'^profile/',TemplateView.as_view( template_name = 'profile.html')), url(r'^saved/', 'SaveProfile', name = 'saved') )
When accessing "/myapp/profile", we will get the following profile.html template rendered −
And on form post, the saved template will be rendered −
ما یک نمونه برای تصویر داریم، اما اگر میخواهید نوع دیگری از فایل را آپلود کنید، نه فقط تصویر، فقط ImageField را در Model و Form با FileField جایگزین کنید.
تا اینجا در مثال هایمان از وب سرور جنگو dev استفاده کرده ایم. اما این سرور فقط برای تست است و برای محیط تولید مناسب نیست. پس از تولید، به یک سرور واقعی مانند Apache، Nginx و غیره نیاز دارید. بیایید در این فصل به آپاچی بپردازیم. سرویس دهی برنامه های جنگو از طریق آپاچی با استفاده از mod_wsgi انجام می شود. بنابراین اولین چیز این است که مطمئن شوید Apache و mod_wsgi را نصب کرده اید. به یاد داشته باشید، زمانی که پروژه خود را ایجاد کردیم و به ساختار پروژه نگاه کردیم، به نظر می رسد -
myproject/ manage.py myproject/ __init__.py settings.py urls.py wsgi.py
فایل wsgi.py فایلی است که از link بین جنگو و آپاچی مراقبت می کند. فرض کنید می خواهیم پروژه خود (myproject) را با آپاچی به اشتراک بگذاریم. فقط باید آپاچی را برای دسترسی به پوشه ما تنظیم کنیم. فرض کنید پوشه myproject خود را در حالت پیش فرض قرار داده ایم.
همانطور که مشاهده می شود، آپاچی مسائل جنگو را مدیریت نمی کند. برای اینکه به این موضوع رسیدگی شود، باید آپاچی را در httpd.conf پیکربندی کنیم. بنابراین httpd.conf را باز کنید و خط زیر را اضافه کنید -
WSGIScriptAlias / /var/www/html/myproject/myproject/wsgi.py WSGIPythonPath /var/www/html/myproject/ <Directory /var/www/html/myproject/> <Files wsgi.py> Order deny,allow Allow from all </Files> </Directory>
اگر می توانید به صفحه ورود به سیستم به عنوان 127.0.0.1 دسترسی داشته باشید
گاهی اوقات ممکن است بخواهید برخی از داده ها را بر اساس هر بازدیدکننده سایت، مطابق با الزامات برنامه وب خود ذخیره کنید. همیشه به خاطر داشته باشید که کوکیها در سمت سرویس گیرنده ذخیره میشوند و بسته به سطح امنیتی مرورگر مشتری شما، تنظیم کوکیها گاهی میتواند کار کند و گاهی اوقات ممکن است نه. برای نشان دادن نحوه مدیریت کوکی ها در جنگو، بیایید یک سیستم با استفاده از سیستم ورود به سیستمی که قبلا ایجاد کردیم ایجاد کنیم. سیستم شما را به مدت X دقیقه وارد سیستم میکند و پس از آن زمان، از برنامه خارج خواهید شد. برای این کار باید دو کوکی، last_connection و username را تنظیم کنید. در ابتدا، اجازه دهید نمای ورود خود را برای ذخیره نام کاربری و کوکیهای last_connection خود تغییر دهیم
from django.template import RequestContext def login(request): username = "not logged in" if request.method == "POST": #Get the posted form MyLoginForm = LoginForm(request.POST) if MyLoginForm.is_valid(): username = MyLoginForm.cleaned_data['username'] else: MyLoginForm = LoginForm() response = render_to_response(request, 'loggedin.html', {"username" : username}, context_instance = RequestContext(request)) response.set_cookie('last_connection', datetime.datetime.now()) response.set_cookie('username', datetime.datetime.now()) return response
همانطور که در نمای بالا مشاهده می شود، تنظیم کوکی با روش set_cookie انجام می شود که بر روی پاسخ فراخوانی می شود نه درخواست، و همچنین توجه داشته باشید که تمام مقادیر کوکی ها به عنوان رشته برگردانده می شوند. بیایید اکنون یک formView برای فرم ورود ایجاد کنیم، در صورتی که کوکی تنظیم شده باشد و از 10 ثانیه بیشتر نباشد، فرم را نمایش نخواهیم داد.
def formView(request): if 'username' in request.COOKIES and 'last_connection' in request.COOKIES: username = request.COOKIES['username'] last_connection = request.COOKIES['last_connection'] last_connection_time = datetime.datetime.strptime(last_connection[:-7], "%Y-%m-%d %H:%M:%S") if (datetime.datetime.now() - last_connection_time).seconds < 10: return render(request, 'loggedin.html', {"username" : username}) else: return render(request, 'login.html', {}) else: return render(request, 'login.html', {})
همانطور که در فرم مشاهده بالا مشاهده می کنید، دسترسی به کوکی که تنظیم کرده اید، از طریق ویژگی COOKIES (dict) درخواست انجام می شود. حالا بیایید فایل url.py را برای تغییر URL تغییر دهیم تا با نمای جدید ما جفت شود
from django.conf.urls import patterns, url from django.views.generic import TemplateView urlpatterns = patterns('myapp.views', url(r'^connection/','formView', name = 'loginform'), url(r'^login/', 'login', name = 'login'))
When accessing /myapp/connection, you will get the following page −
و در ارسال − به صفحه زیر هدایت خواهید شد
اکنون، اگر سعی کنید دوباره در بازه 10 ثانیه ای به /myapp/connection دسترسی پیدا کنید، مستقیماً به صفحه دوم هدایت می شوید. و اگر دوباره خارج از این محدوده به /myapp/connection دسترسی پیدا کنید، فرم ورود به سیستم (صفحه 1) را دریافت خواهید کرد.
همانطور که قبلاً بحث شد، میتوانیم از کوکیهای سمت سرویس گیرنده برای ذخیره دادههای مفید زیادی برای برنامه وب استفاده کنیم. قبلاً دیدهایم که میتوانیم از کوکیهای سمت کلاینت برای ذخیره دادههای مختلف مفید برای برنامه وب خود استفاده کنیم. این به حفره های امنیتی زیادی بسته به اهمیت داده هایی که می خواهید ذخیره کنید منجر می شود. به دلایل امنیتی، جنگو یک چارچوب جلسه برای مدیریت کوکی ها دارد. از Session ها برای انتزاع دریافت و ارسال کوکی ها استفاده می شود، داده ها در سمت سرور ذخیره می شوند (مانند پایگاه داده)، و کوکی سمت سرویس گیرنده فقط یک شناسه جلسه برای شناسایی دارد. جلسات همچنین برای جلوگیری از مواردی که مرورگر کاربر روی «نپذیرفتن» کوکیها تنظیم شده است مفید است.
Setting Up Sessions
در جنگو، فعال کردن جلسه در تنظیمات پروژه شما با افزودن چند خط به گزینه های MIDDLEWARE_CLASSES و INSTALLED_APPS انجام می شود. این باید در حین ایجاد پروژه انجام شود، اما دانستن آن همیشه خوب است، بنابراین MIDDLEWARE_CLASSES باید داشته باشد -
'django.contrib.sessions.middleware.SessionMiddleware'
And INSTALLED_APPS should have −
'django.contrib.sessions'
به طور پیش فرض، جنگو اطلاعات جلسه را در پایگاه داده (جدول یا مجموعه django_session) ذخیره می کند، اما می توانید موتور را برای ذخیره اطلاعات با استفاده از روش های دیگری مانند: در فایل یا در حافظه پنهان پیکربندی کنید. هنگامی که session فعال است، هر درخواست (اول آرگومان هر view در جنگو) دارای ویژگی session (dict) است. بیایید یک نمونه ساده ایجاد کنیم تا نحوه ایجاد و ذخیره جلسات را ببینیم. ما قبلاً یک سیستم ورود ساده ساختهایم (به فصل پردازش فرم جنگو و فصل مدیریت کوکیهای جنگو مراجعه کنید). اجازه دهید نام کاربری را در یک کوکی ذخیره کنیم تا در صورت عدم خروج از سیستم، هنگام دسترسی به صفحه ورود ما، فرم ورود را نبینید. اساساً، بیایید سیستم ورود خود را که در مدیریت کوکیهای جنگو استفاده میکنیم، با ذخیره کوکیها در سمت سرور، ایمنتر کنیم. برای این، ابتدا اجازه دهید نمای ورود خود را تغییر دهیم تا نام کاربری در سمت سرور کوکی ذخیره شود -
def login(request): username = 'not logged in' if request.method == 'POST': MyLoginForm = LoginForm(request.POST) if MyLoginForm.is_valid(): username = MyLoginForm.cleaned_data['username'] request.session['username'] = username else: MyLoginForm = LoginForm() return render(request, 'loggedin.html', {"username" : username}
سپس اجازه دهید نمای formView را برای فرم ورود ایجاد کنیم، جایی که اگر کوکی تنظیم شده باشد، فرم را نمایش نمی دهیم -
def formView(request): if request.session.has_key('username'): username = request.session['username'] return render(request, 'loggedin.html', {"username" : username}) else: return render(request, 'login.html', {})
Now let us change the url.py file to change the url so it pairs with our new view −
from django.conf.urls import patterns, url from django.views.generic import TemplateView urlpatterns = patterns('myapp.views', url(r'^connection/','formView', name = 'loginform'), url(r'^login/', 'login', name = 'login'))
When accessing /myapp/connection, you will get to see the following page −
And you will get redirected to the following page −
حالا اگر دوباره سعی کنید به /myapp/connection دسترسی پیدا کنید، مستقیماً به صفحه دوم هدایت می شوید.
Let's create a simple logout view that erases our cookie.
def logout(request): try: del request.session['username'] except: pass return HttpResponse("<strong>You are logged out.</strong>")
And pair it with a logout URL in myapp/url.py
url(r'^logout/', 'logout', name = 'logout'),
Now, if you access /myapp/logout, you will get the following page −
If you access /myapp/connection again, you will get the login form (screen 1).
Some More Possible Actions Using Sessions
ما نحوه ذخیره و دسترسی به یک جلسه را دیدهایم، اما خوب است بدانید که ویژگی session درخواست دارای اقدامات مفید دیگری مانند -
کش کردن چیزی به معنای ذخیره نتیجه یک محاسبه گران قیمت است، به طوری که دفعه بعد که به آن نیاز داشتید آن را انجام ندهید. در زیر یک شبه کد وجود دارد که نحوه عملکرد کش را توضیح می دهد
given a URL, try finding that page in the cache if the page is in the cache: return the cached page else: generate the page save the generated page in the cache (for next time) return the generated page
جنگو دارای سیستم کش مخصوص به خود است که به شما امکان می دهد صفحات پویا خود را ذخیره کنید تا در صورت نیاز از محاسبه مجدد آنها جلوگیری کنید. نکته خوب در چارچوب جنگو کش این است که می توانید − را کش کنید
برای استفاده از کش در جنگو، اولین کاری که باید انجام دهید این است که محل ماندن کش را تنظیم کنید. چارچوب کش امکانات مختلفی را ارائه می دهد - کش را می توان در پایگاه داده، در سیستم فایل یا مستقیماً در حافظه ذخیره کرد. تنظیمات در فایل settings.py پروژه شما انجام می شود.
Just add the following in the project settings.py file −
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'my_table_name', } }
برای انجام این کار و تکمیل تنظیمات، باید جدول کش «my_table_name» را ایجاد کنیم. برای این کار، باید موارد زیر را انجام دهید -
python manage.py createcachetable
Just add the following in the project settings.py file −
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': '/var/tmp/django_cache', } }
این کارآمدترین روش کش است، برای استفاده از آن میتوانید بسته به کتابخانه پایتونی که برای کش حافظه انتخاب میکنید از یکی از گزینههای زیر استفاده کنید.
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': '127.0.0.1:11211', } }
Or
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION': 'unix:/tmp/memcached.sock', } }
ساده ترین راه استفاده از کش در جنگو، کش کردن کل سایت است. این کار با ویرایش گزینه MIDDLEWARE_CLASSES در تنظیمات پروژه انجام می شود. موارد زیر باید به گزینه - اضافه شود
MIDDLEWARE_CLASSES += ( 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', )
توجه داشته باشید که ترتیب در اینجا مهم است، Update باید قبل از Fetch middleware باشد. سپس در همان فایل، باید − را تنظیم کنید
CACHE_MIDDLEWARE_ALIAS – The cache alias to use for storage. CACHE_MIDDLEWARE_SECONDS – The number of seconds each page should be cached.
اگر نمی خواهید کل سایت را کش کنید، می توانید یک نمای خاص را کش کنید. این کار با استفاده از cache_page decorator همراه با جنگو انجام می شود. فرض کنید میخواهیم نتیجه نمای viewArticles − را کش کنیم
from django.views.decorators.cache import cache_page @cache_page(60 * 15) def viewArticles(request, year, month): text = "Displaying articles of : %s/%s"%(year, month) return HttpResponse(text)
همانطور که می بینید cache_page به تعداد ثانیه هایی که می خواهید نتیجه view به عنوان پارامتر کش شود طول می کشد. در مثال بالا، نتیجه به مدت 15 دقیقه در حافظه پنهان ذخیره می شود. توجه - همانطور که قبلاً دیدیم نمای بالا به - نگاشت شده بود
urlpatterns = patterns('myapp.views', url(r'^articles/(?P<month>\d{2})/(?P<year>\d{4})/', 'viewArticles', name = 'articles'),)
از آنجایی که URL پارامترها را می گیرد، هر تماس مختلف به طور جداگانه ذخیره می شود. به عنوان مثال، درخواست به
urlpatterns = patterns('myapp.views', url(r'^articles/(?P<month>\d{2})/(?P<year>\d{4})/', cache_page(60 * 15)('viewArticles'), name = 'articles'),)
و البته، دیگر در myapp/views.py مورد نیاز نیست
شما همچنین می توانید بخش هایی از یک الگو را در حافظه پنهان نگه دارید، این کار با استفاده از تگ کش انجام می شود. بیایید الگوی hello.html خود را بگیریم -
{% extends "main_template.html" %} {% block title %}My Hello Page{% endblock %} {% block content %} Hello World!!!<p>Today is {{today}}</p> We are {% if today.day == 1 %} the first day of month. {% elif today == 30 %} the last day of month. {% else %} I don't know. {%endif%} <p> {% for day in days_of_week %} {{day}} </p> {% endfor %} {% endblock %}
و برای کش کردن بلوک محتوا، الگوی ما به − تبدیل می شود
{% extends "main_template.html" %} {% block title %}My Hello Page{% endblock %} {% block content %} Hello World!!!<p>Today is {{today}}</p> We are {% if today.day == 1 %} the first day of month. {% elif today == 30 %} the last day of month. {% else %} I don't know. {%endif%} <p> {% for day in days_of_week %} {{day}} </p> {% endfor %} {% endblock %}
And to cache the content block, our template will become −
{% load cache %} {% extends "main_template.html" %} {% block title %}My Hello Page{% endblock %} {% cache 500 content %} {% block content %} Hello World!!!<p>Today is {{today}}</p> We are {% if today.day == 1 %} the first day of month. {% elif today == 30 %} the last day of month. {% else %} I don't know. {%endif%} <p> {% for day in days_of_week %} {{day}} </p> {% endfor %} {% endblock %} {% endcache %}
همانطور که در بالا می بینید، تگ کش 2 پارامتر می گیرد - زمانی که می خواهید بلوک کش شود (در ثانیه) و نامی که به قطعه کش داده شود.
قبل از شروع، توجه داشته باشید که چارچوب نظرات جنگو از نسخه 1.5 منسوخ شده است. اکنون میتوانید از ویژگی خارجی برای این کار استفاده کنید، اما اگر همچنان میخواهید از آن استفاده کنید، همچنان در نسخههای 1.6 و 1.7 موجود است. شروع نسخه 1.8 وجود ندارد، اما همچنان می توانید کد را در یک حساب GitHub دیگر دریافت کنید. چارچوب نظرات، پیوست کردن نظرات را به هر مدلی در برنامه شما آسان می کند. برای شروع استفاده از چارچوب نظرات جنگو - فایل settings.py پروژه را ویرایش کنید و "django.contrib.sites" و "django.contrib.comments" را به گزینه INSTALLED_APPS اضافه کنید.
INSTALLED_APPS += ('django.contrib.sites', 'django.contrib.comments',)
Get the site id −
>>> from django.contrib.sites.models import Site >>> Site().save() >>> Site.objects.all()[0].id u'56194498e13823167dd43c64
Set the id you get in the settings.py file −
SITE_ID = u'56194498e13823167dd43c64'
همگام سازی db، برای ایجاد تمام جدول نظرات یا مجموعه -
python manage.py syncdb
Add the comment app’s URLs to your project’s urls.py −
from django.conf.urls import include url(r'^comments/', include('django.contrib.comments.urls')),
اکنون که چارچوب را نصب کرده ایم، بیایید الگوهای hello خود را به ردیابی نظرات در مدل Dreamreal خود تغییر دهیم. ما نظرات را برای یک ورودی Dreamreal خاص لیست می کنیم و ذخیره می کنیم که نام آن به عنوان پارامتر به آن ارسال می شود
class Dreamreal(models.Model): website = models.CharField(max_length = 50) mail = models.CharField(max_length = 50) name = models.CharField(max_length = 50) phonenumber = models.IntegerField() class Meta: db_table = "dreamreal"
def hello(request, Name): today = datetime.datetime.now().date() daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] dreamreal = Dreamreal.objects.get(name = Name) return render(request, 'hello.html', locals())
{% extends "main_template.html" %} {% load comments %} {% block title %}My Hello Page{% endblock %} {% block content %} <p> Our Dreamreal Entry: <p><strong>Name :</strong> {{dreamreal.name}}</p> <p><strong>Website :</strong> {{dreamreal.website}}</p> <p><strong>Phone :</strong> {{dreamreal.phonenumber}}</p> <p><strong>Number of comments :<strong> {% get_comment_count for dreamreal as comment_count %} {{ comment_count }}</p> <p>List of comments :</p> {% render_comment_list for dreamreal %} </p> {% render_comment_form for dreamreal %} {% endblock %}
Finally the mapping URL to our hello view −
url(r'^hello/(?P<Name>\w+)/', 'hello', name = 'hello'),
Now,
هنگام دسترسی به /myapp/hello/steve، اطلاعات نظرات مربوط به مدخل Dreamreal که نام آن استیو است را دریافت خواهید کرد. دسترسی به آن URL شما را دریافت می کند -
On posting a comment, you will get redirected to the following page −
If you go to /myapp/hello/steve again, you will get to see the following page −
همانطور که می بینید، تعداد نظرات در حال حاضر 1 است و شما نظر را در زیر خط لیست نظرات دارید.
جنگو با یک چارچوب تولید خوراک سندیکایی عرضه می شود. با آن میتوانید فیدهای RSS یا Atom را فقط با زیر کلاسبندی کلاس django.contrib.syndication.views.Feed ایجاد کنید.
بیایید یک فید برای آخرین نظرات انجام شده در برنامه ایجاد کنیم (همچنین به فصل جنگو - چارچوب نظرات مراجعه کنید)برای این، بیایید یک myapp/feeds.py ایجاد کنیم و فید خود را تعریف کنیم (شما می توانید کلاس های فید خود را در هر جایی که می خواهید در ساختار کد خود قرار دهید).
from django.contrib.syndication.views import Feed from django.contrib.comments import Comment from django.core.urlresolvers import reverse class DreamrealCommentsFeed(Feed): title = "Dreamreal's comments" link = "/drcomments/" description = "Updates on new comments on Dreamreal entry." def items(self): return Comment.objects.all().order_by("-submit_date")[:5] def item_title(self, item): return item.user_name def item_description(self, item): return item.comment def item_link(self, item): return reverse('comment', kwargs = {'object_pk':item.pk})
اکنون که فید خود را داریم، بیایید یک نمای نظر در views.py اضافه کنیم تا نظر خود را نمایش دهیم -
from django.contrib.comments import Comment def comment(request, object_pk): mycomment = Comment.objects.get(object_pk = object_pk) text = '<strong>User :</strong> %s <p>'%mycomment.user_name</p> text += '<strong>Comment :</strong> %s <p>'%mycomment.comment</p> return HttpResponse(text)
We also need some URLs in our myapp urls.py for mapping −
from myapp.feeds import DreamrealCommentsFeed from django.conf.urls import patterns, url urlpatterns += patterns('', url(r'^latest/comments/', DreamrealCommentsFeed()), url(r'^comment/(?P\w+)/', 'comment', name = 'comment'), )
When accessing /myapp/latest/comments/ you will get our feed −
سپس با کلیک بر روی یکی از نامهای کاربری به موارد زیر هدایت میشوید:
بنابراین، تعریف یک فید RSS فقط یک موضوع زیر طبقه بندی کلاس Feed و اطمینان از تعریف URL ها (یکی برای دسترسی به فید و دیگری برای دسترسی به عناصر فید) است. درست به عنوان نظر، این می تواند به هر مدلی در برنامه شما متصل شود.
Ajax اساساً ترکیبی از فناوریهایی است که برای کاهش تعداد بارگذاری صفحات با یکدیگر یکپارچه شدهاند. ما معمولاً از Ajax برای سهولت تجربه کاربر نهایی استفاده می کنیم. استفاده از Ajax در Django را می توان با استفاده مستقیم از یک کتابخانه Ajax مانند JQuery یا موارد دیگر انجام داد. فرض کنید می خواهید از JQuery استفاده کنید، سپس باید کتابخانه را از طریق آپاچی یا سایرین روی سرور خود دانلود و سرویس کنید. سپس از آن در قالب خود استفاده کنید، درست مانند کاری که ممکن است هنگام توسعه هر برنامه مبتنی بر Ajax انجام دهید. راه دیگر استفاده از Ajax در جنگو استفاده از فریمورک Django Ajax است. رایج ترین مورد استفاده، django-dajax است که ابزاری قدرتمند برای توسعه آسان و فوق العاده سریع منطق ارائه ناهمزمان در برنامه های وب، با استفاده از پایتون و تقریباً بدون کد منبع جاوا اسکریپت است. چهار مورد از محبوب ترین فریم ورک های آژاکس را پشتیبانی می کند: Prototype، jQuery، Dojo و MooTools.
اولین کاری که باید انجام دهید این است که django-dajax را نصب کنید. این را می توان با استفاده از easy_install یا pip − انجام داد
$ pip install django_dajax $ easy_install django_dajax
این به طور خودکار django-dajaxice مورد نیاز django-dajax را نصب می کند. سپس باید هم dajax و هم dajaxice را پیکربندی کنیم. dajax و dajaxice را در تنظیمات پروژه خود در گزینه INSTALLED_APPS اضافه کنید
INSTALLED_APPS += ( 'dajaxice', 'dajax' )
Make sure in the same settings.py file, you have the following −
TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', 'django.template.loaders.eggs.Loader', ) TEMPLATE_CONTEXT_PROCESSORS = ( 'django.contrib.auth.context_processors.auth', 'django.core.context_processors.debug', 'django.core.context_processors.i18n', 'django.core.context_processors.media', 'django.core.context_processors.static', 'django.core.context_processors.request', 'django.contrib.messages.context_processors.messages' ) STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'dajaxice.finders.DajaxiceFinder', ) DAJAXICE_MEDIA_PREFIX = 'dajaxice'
Now go to the myapp/url.py file and make sure you have the following to set dajax URLs and to load dajax statics js files −
from dajaxice.core import dajaxice_autodiscover, dajaxice_config from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.conf import settings Then dajax urls: urlpatterns += patterns('', url(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, include('dajaxice.urls')),) urlpatterns += staticfiles_urlpatterns()
Let us create a simple form based on our Dreamreal model to store it, using Ajax (means no refresh).
At first, we need our Dreamreal form in myapp/form.py.
class DreamrealForm(forms.Form): website = forms.CharField(max_length = 100) name = forms.CharField(max_length = 100) phonenumber = forms.CharField(max_length = 50) email = forms.CharField(max_length = 100)
Then we need an ajax.py file in our application: myapp/ajax.py. That's where is our logic, that's where we put the function that will be saving our form then return the popup −
from dajaxice.utils import deserialize_form from myapp.form import DreamrealForm from dajax.core import Dajax from myapp.models import Dreamreal @dajaxice_register def send_form(request, form): dajax = Dajax() form = DreamrealForm(deserialize_form(form)) if form.is_valid(): dajax.remove_css_class('#my_form input', 'error') dr = Dreamreal() dr.website = form.cleaned_data.get('website') dr.name = form.cleaned_data.get('name') dr.phonenumber = form.cleaned_data.get('phonenumber') dr.save() dajax.alert("Dreamreal Entry %s was successfully saved." % form.cleaned_data.get('name')) else: dajax.remove_css_class('#my_form input', 'error') for error in form.errors: dajax.add_css_class('#id_%s' % error, 'error') return dajax.json()
Now let's create the dreamreal.html template, which has our form −
<html> <head></head> <body> <form action = "" method = "post" id = "my_form" accept-charset = "utf-8"> {{ form.as_p }} <p><input type = "button" value = "Send" = "send_form();"></p> </form> </body> </html>
Add the view that goes with the template in myapp/views.py −
def dreamreal(request): form = DreamrealForm() return render(request, 'dreamreal.html', locals())
Add the corresponding URL in myapp/urls.py −
url(r'^dreamreal/', 'dreamreal', name = 'dreamreal'),
Now let's add the necessary in our template to make the Ajax work −
At the top of the file add −
{% load static %} {% load dajaxice_templatetags %}
And in the <head> section of our dreamreal.html template add −
We are using the JQuery library for this example, so add −
<script src = "{% static '/static/jquery-1.11.3.min.js' %}" type = "text/javascript" charset = "utf-8"> <script src = "{% static '/static/dajax/jquery.dajax.core.js' %}">
The Ajax function that will be called on click −
function send_form(){ Dajaxice.myapp.send_form(Dajax.process,{'form':$('#my_form').serialize(true)}); }
Note that you need the “jquery-1.11.3.min.js” in your static files directory, and also the jquery.dajax.core.js. To make sure all dajax static files are served under your static directory, run −
$python manage.py collectstatic
Note − Sometimes the jquery.dajax.core.js can be missing, if that happens, just download the source and take that file and put it under your static folder.
You will get to see the following screen, upon accessing /myapp/dreamreal/ −
On submit, you will get the following screen −