این حالت نمایش چند صفحه ای قابل پرینت این قسمت میباشد. برای پرینت کلیک کنید..
فصل بیستم
- 1: شکلدهی و استقرار
- 2: شکل دادن به پروژه
- 3: تغییر دادن base.html
- 4: تعریف کردن نوار پیمایش
- 5: تعریف قسمت اصلی صفحه
- 6: شکلدهی به صفحهی خانه به کمک جامباترون
- 7: آراستن صفحهی ورود
- 8: شکل دادن به صفحهی موضوعات
- 9: شکل دادن به مطالب در صفحهی موضوعها
- 10: استقرار پروژه
- 11: ساختن فایلهای پیکربندی
- 12: استفاده از Git برای ردگیری فایلهای پروژه
- 13: ارسال به هروکو و برپا کردن پایگاه داده
- 14: بهبود استقرار هروکو
- 15: امن کردن پروژهی در حال کار
- 16: ساختن صفحههای خطای شخصی
- 17: استفاده از get_object_or_404()
- 18: توسعههای آینده و نکتههای پایانی
- 19: خلاصه
1 - شکلدهی و استقرار
سایت Learning Log اکنون کاملاً کارآمد است امّا هیچ شکل و سیاقی ندارد و روی ماشین محلی شما اجرا میشود. در این فصل پروژه را به شکلی ساده امّا حرفهای درمیآوریم و سپس آن را روی سرور در حال اجرا مستقر میکنیم تا هر کس در هر جای دنیا بتواند حساب کاربری بسازد و از آن استفاده کند.
برای شکلدهی به سایت از کتابخانهی Bootstrap استفاده میکنیم که مجموعهای از ابزارها برای سر و شکل دادن به برنامههای کاربردی تحت وب است تا آنها در افزارههای مدرن حرفهای به نظر برسند، از نمایشگرهای تخت بزرگ گرفته تا گوشیهای هوشمند. برای چنین کاری از برنامهی django-bootstrap4 کمک میگیریم تا علاوه بر هدف اصلی خود، در کار کردن با برنامههایی که دیگر توسعهدهندگان جانگو ساختهاند تجربه کسب کنید.
برای استقرار پروژه از Heroku استفاده میکنیم، سایتی که به شما امکان میدهد که پروژهی خود را روی یکی از سرورهای آن قرار دهید تا هر کس با اتّصال اینترنت به آن دسترسی داشته باشد. افزون بر این کار با یک سیستم کنترل نسخه به نام Git برای ردگیری تغییرات پروژه شروع میکنیم.
زمانی که پروژهی Learning Log را به پایان برسانید قادر خواهید بود که برنامههای کاربردی سادهی تحت وب را توسعه دهید، آنها را به شکل و قیافهی مناسبی درآورید و آنها را روی یک سرور زنده مستقر کنید. علاوه بر اینها میتوانید از منابع آموزشی پیشرفتهتر استفاده کنید تا مهارتهای خود را گسترش دهید.
2 - شکل دادن به پروژه
ما عمداً تا الان به شکل و قیافهی سایت توجّهی نکردیم تا ابتدا روی کارآمدی سایت تمرکز کرده باشیم. این راه خوبی برای توسعه دادن است زیرا یک برنامه تنها زمانی سودمند است که کار کند. البته به محض اطمینان از کارایی، ظاهر آن حیاتی میشود تا افراد به استفاده از آن تمایل داشته باشند.
در این بخش برنامهی django-bootstrap4 را معرّفی میکنم و به شما نشان میدهم که چگونه میتوان آن را در یک پروژه تجمیع کرد تا برای استقرار آماده شود.
برنامه django-bootstrap4
برای مجتمع کردن بوتاسترپ در پروژهی خود از django-bootstrap4 استفاده میکنیم. این برنامه فایلهای مورد نیاز بوتاسترپ را دریافت کرده و آنها را در مکان مناسب داخل پروژهی شما قرار میدهد و استفاده از راهنماهای شیوهدهی را در قالبهای پروژه ممکن میسازد.
برای نصب django-bootstrap4 فرمان زیر را در یک محیط مجازی فعّال صادر کنید:
سپس باید کد زیر را به settings.py اضافه کنید تا django-bootstrap4 در INSTALLED_APPS قرار بگیرد:
بخش جدیدی به نام Third party apps (برنامههای شخص ثالث) برای برنامههایی ایجاد کنید که دیگر توسعهدهندگان ساختهاند و 'bootstrap4' را به آن بیفزایید. مطمئن شوید که این بخش را پس از # My apps و پیش از بخشی که برنامههای پیشفرض جانگو را در برمیگیرد قرار دهید.
استفاده از بوتاسترپ برای شکل دادن به Learning Log
بوتاسترپ مجموعهای بزرگ از ابزارهای شکلدهی است.173 همچنین تعدادی قالب دارد که میتوانید آنها را به پروژهی خود اعمال کنید تا شکلی کلّی پیدا کند. استفاده کردن از این قالبها به مراتب سادهتر از بهکارگیری ابزارهای شکلدهی متفرقّه است. برای دیدن قالبهایی که بوتاسترپ عرضه میکند به https://getbootstrap.com/ بروید، روی Examples کلیک کنید و به دنبال بخش Navbars بگردید. ما از قالب نوار پیمایش ایستا (Navbar Static) استفاده میکنیم که یک نوار پیمایش ساده در بالا و یک دربردارنده برای مطالب سایت ارائه میکند.
شکل ۲۰-۱ صفحهی خانه را پس از اعمال قالب بوتاسترپ به base.html و تغییر جزئی index.html نشان میدهد.
شکل ۲۰-۱- صفحهی خانه با استفاده از بوتاسترپ
3 - تغییر دادن base.html
باید برای جای دادن قالب بوتاسترپ در قالب base.html آن را تغییر داد. فایل base.html جدید را بخش به بخش معرّفی میکنم.
تعیین سربرگهای HTML
اوّلین تغییری که در base.html ایجاد میکنیم تعریف174 سربرگهای HTML در این فایل است تا هر گاه صفحهی Learning Log باز بود مرورگر در نوار عنوان خود نام سایت را نمایش دهد. علاوه بر این تعدادی از نیازمندیهای مربوط به بهکارگیری بوتاسترپ در قالبهای خود را نیز اضافه میکنیم. هر آنچه در base.html وجود دارد پاک کنید و کد زیر را جایگزین کنید:
{% load bootstrap4 %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1,
shrink-to-fit=no">
<title>Learning Log</title>
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
</head>
در ۱ مجموعههایی از تگهای قالبی موجود در django-bootstrap4 را بارگذاری میکنیم. سپس تعیین میکنیم که این یک سند HTML است(۲) که به زبان انگلیسی نوشته شده است (۳) هر فایل HTML به دو بخش اصلی تقسیم میشود سربرگ و بدنه—سربرگ فایل از ۴ شروع میشود. سربرگ یک فایل HTML هیچ محتوایی را در بر نمیگیرد: این بخش تنها به مرورگر میگوید که برای نمایش صحیح این صفحه باید چه چیزهایی را بداند. در ۵ عنصر title صفحه را اضافه میکنیم که هر گاه صفحهی سایت باز باشد، در نوار عنوان مرورگر نمایش داده میشود.
در ۶ از یکی از تگهای قالبی شخصی django-bootstrap4 استفاده میکنیم که به جانگو میگوید تمام فایلهای شکلدهی بوتاسترپ را وارد کند. تگی که بعد از این میآید تمام رفتارهای تعاملی مورد استفاده در صفحه را شامل فعّال میکند، مانند نوارهای پیمایش باز و بستهشونده. تگ بستن </head> در ۷ میآید.
4 - تعریف کردن نوار پیمایش
کدی که نوار پیمایش را در بالای صفحه تعریف میکند کمی طولانی است زیرا این نوار باید در صفحههای کمعرض گوشی و نمایشگرهای رومیزی عریض به درستی کار کند. کار بر روی نوار پیمایش را در چند بخش ادامه میدهیم.
این اوّلین بخش نوار پیمایش است:
--snip--
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light mb-4 border">
<a class="navbar-brand" href="{% url 'learning_logs:index'%}">
Learning Log</a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarCollapse" aria-controls="navbarCollapse"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span></button>
اوّلین عنصر، تگ گشایش <body> است (۱). بدنهی یک فایل HTML دربردارندهی محتویّا175
تی است که کاربران بر روی صفحه خواهند دید. در ۲ یک عنصر <nav> وجود دارد که نشانگر بخش پیوندهای پیمایش صفحه است. سیاق هر چه که داخل این عنصر باشد مطابق قواعد شکلدهی بوتاسترپ تعیین میشود که با انتخابگرهای navbar، navbar-expand-md و دیگر موارد مشخّص شدهاند. یک انتخابگر تعیین میکند که مجموعهای از قوانین شکلدهی به کدام عنصرها در صفحه اعمال شوند. انتخابگرهای navbar-light و bg-light پسزمینهی نوار پیمایش را به رنگ روشن درمیآورند. mb در mb-4 سرواژهی margin-bottom (حاشیهی پایین) است؛ این انتخابگر وجود یک فاصلهی کوچک بین نوار پیمایش و دیگر اجزای صفحه را تضمین میکند. انتخابگر border یک لبهی نازک به پسزمینهی روشن اضافه میکند تا آن را کمی از باقی قسمتهای صفحه متمایز کند.
در ۳ کاری میکنیم که نام پروژه در منتها الیه سمت چپ نوار پیمایش پدیدار شود و آن را به صورت پیوندی به صفحهی خانه درمیآوریم؛ این نام در تمام صفحههای پروژه دیده خواهد شد. انتخابگر navbar-brand این پیوند را به شکلی درمیآورد که با بقیهی پیوندها متفاوت باشد و به نوعی نشان سایت به شمار آید.
در ۴ قالب دکمهای تعریف میکند که اگر عرض صفحهی مرورگر خیلی کم شد پدیدار شود و کل نوار پیمایش را به صورت افقی نمایش دهد. زمانی که کاربر روی این دکمه کلیک میکند عنصرهای پیمایش در یک فهرست پایینافتادنی نمایش داده خواهند شد. ارجاع به collapse باعث میشود که هرگاه کاربر صفحهی مرورگر را خیلی کوچک کرد یا صفحه را روی یک گوشی همراه با صفحهی کوچک باز کرد، نوار پیمایش جمع شود.
این بخش بعدی کدی است که نوار پیمایش را تعریف میکند:
--snip--
<span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="{% url 'learning_logs:topics'%}">
Topics</a></li>
</ul>
در ۱ بخش جدیدی از نوار پیمایش را باز میکنیم. عبارت div مخفّف division به معنای قسمت است؛ شما صفحههای وب را با تقسیم کردن آن به بخشهای مختلف و تعیین شیوهها و قواعد رفتاری به آن بخش طرّاحی میکنید. هر شکل و شیوه یا قاعدهی رفتاری که در یک تگ گشایش div نوشته شود، روی تمام عنصرهایی که قبل از تگ بستن به صورت </div> قرار میگیرند تأثیر میگذارند. این آغاز بخشی از نوار پیمایش است که هنگام نمایش بر روی صفحهها و پنجرههای باریک جمع میشود.
در ۲ مجموعهی جدیدی از پیوندها را تعریف میکنیم. ب176 وتاسترپ عنصرهای پیمایش را در قالب یک فهرست نامرتّب تعریف میکند ولی قواعد شکلدهی آن به شکلی است که به صورت یک فهرست دیده نمیشود. هر پیوند یا عنصری که بخواهید روی نوار نمایش دهید میتواند به صورت عضوی از این لیستها باشد. اینجا تنها مورد در فهرست ما پیوندی به صفحهی Topics است (۳).
این بخش بعدی نوار پیمایش است:
--snip--
</ul>
<ul class="navbar-nav ml-auto">
{% if user.is_authenticated %}
<li class="nav-item">
<span class="navbar-text"}">Hello, {{ user.username }}.</span>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'users:logout' %}">Log out</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'users:register' %}">Register</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'users:login' %}">Log in</a></li>
{% endif %}
</ul>
</div>
</nav>
در ۱ مجموعهای دیگر از پیوندها را با یک تگ گشایش <ul> آغاز میکنیم. شما میتوانید هر تعداد مجموعه پیوند که نیاز داشته باشید به صفحه اضافه کنید. این مجموعه پیوندهایی خواهند بود که به ورود و ثبت نام مرتبطند و در سمت راست نوار پیمایش نمایش داده میشوند. انتخابگر ml-auto مخفّف margin-left-automatic است: این انتخابگر دیگر عناصر نوار پیمایش را میسنجد و حاشیهای در سمت چپ ایجاد میکند که این گروه از پیوندها را به سمت راست صفحه براند.
بخش if در ۲ همان شرطهایی است که پیشتر، بسته به وارد شدن یا نشدن177
کاربران، برای نمایش پیامهای مناسب به آنها استفاده میکردیم. این بخش کمی طولانیتر است زیرا چند قاعدهی شکلدهی هم در داخل تگهای شرطی وجود دارد. در ۳ یک عنصر <span> داریم. عنصر محدوده بخشی از متن یا عنصرهای صفحه را شکلدهی میکند که خود جزئی از یک خط طولانیتر هستند. درحالیکه عنصرهای div بخشهای مختلفی در صفحه ایجاد میکنند، عنصرهای محدوده در داخل یک بخش بزرگتر قرار میگیرند. اینجا از این عنصر محدوده برای شکلدهی به متنهای اطّلاعدهنده مانند نام کاربری واردشده، استفاده میکنیم. هدف ما این است که این اطّلاعات از یک پیوند متمایز باشند تا کاربران تلاش نکنند روی آن کلیک کنند.
در ۴ بخشی را میبندیم که قسمتهای پنهانشوندهی نوار پیمایش در صفحههای باریک را در برمیگیرد و در نهایت کل قسمت مربوط به نوار پیمایش را میبندیم. اگر بخواهید پیوندهای بیشتری به نوار پیمایش اضافه کنید میتوانید یک <li> دیگر به هر یک از گروههای <ul> که تعریف کردیم اضافه کنید و از همان روشهای شیوهدهی که اینجا دیدهاید استفاده کنید.
5 - تعریف قسمت اصلی صفحه
هنوز موارد اندکی مانده تا به base.html اضافه کنیم. باید دو بلوک اضافه کنیم تا صفحههای جداگانه بتوانند از آنها برای قرار دادن محتوای مخصوص به خود استفاده کنند.
باقی base.html قسمت اصلی صفحه را در برمیگیرد:
--snip--
</nav>
<main role="main" class="container">
<div class="pb-2 mb-2 border-bottom">
{% block page_header %}{% endblock page_header %}
</div>
<div>
{% block content %}{% endblock content %}
</div>
</main>
</body>
</html>
در ۱ یک تگ <main> باز میکنیم. عنصر بخش اصلی برای نمایش برجستهترین بخش بدنهی صفحههای شما استفاده میشود. اینجا از انتخابگر container بوتاسترپ بهره میگیریم که راهی ساده برای گروهبندی عنصرها در یک صفحه است. دو عنصر div در آن قرار میدهیم.
اوّلین عنصر div در ۲ بلوک page_header را در برمیگیرد. از این قسمت برای تعیین عنوان بیشتر صفحه180
179
178
ها استفاده میکنیم. برای این که این بخش را از دیگر قسمتهای صفحه متمایز کنیم، در داخل بخش زیرین عنوان کمی فاصله ایجاد میکنیم. این درونفاصله به فضایی اشاره دارد که بین محتویات یک عنصر و کنارهی آن وجود دارد. انتخابگر pb-2 بوتاسترپ درونفاصلهای متوسط در پایین عنصر ایجاد میکند. حاشیه فاصلهای است که بین کنارهی یک عنصر و دیگر عنصرهای صفحه وجود دارد. از آنجایی که تنها در پایین صفحه به کناره نیاز داریم از انتخابگر border-bottom کمک میگیریم که کنارهای نازک در پایین بخش page_header میاندازد.
در ۳ یک عنصر div دیگر تعریف میکنیم که شامل بلوک content است. هیچ شیوهی خاصّی را در این بلوک اعمال نمیکنیم تا هر صفحه بتواند با شکل و شیوهی مناسب خود در اینجا نشان داده شود. کار فایل base.html را با افزودن تگهای پایانی برای عنصرهای main، body و html خاتمه میدهیم.
اگر اکنون صفحهی خانهی Learning Log را در مرورگری باز کنید باید یک نوار پیمایش با ظاهر حرفهای مطابق آنچه در شکل ۲۰-۱ نمایش داده شده ببینید. سعی کنید که پنجره را خیلی باریک کنید؛ باید به جای نوار پیمایش یک دکمه قرار بگیرد. اگر روی آن کلیک کنید باید تمام پیوندها را به صورت یک فهرست پایینافتادنی ببینید.
6 - شکلدهی به صفحهی خانه به کمک جامباترون
برای بهروزرسانی صفحهی خانه از یک عنصر بوتاسترپ181 به نام جامباترون استفاده میکنیم. این عنصر جعبهی بزرگی است که از دیگر بخشهای صفحه متمایز بوده و میتواند هر چیزی را که بخواهید دربربگیرد. به طور معمول از این عنصر در صفحههای آغازین پروژه و برای بیان شرحی مختصر از آن استفاده میشود و میتواند بیننده را به انجام عملی در سایت دعوت کند.
این فایل index.html بازبینیشده است:
{% extends "learning_logs/base.html" %}
{% block page_header %}
<div class="jumbotron">
<h1 class="display-3">Track your learning.</h1>
<p class="lead">Make your own Learning Log, and keep a list of the
topics you're learning about. Whenever you learn something new
about a topic, make an entry summarizing what you've learned.</p>
<a class="btn btn-lg btn-primary" href="{% url 'users:register' %}"
role="button">Register »</a>
</div>
{% endblock page_header %}
در ۱ به جانگو میگوییم که آنچه در قسمت page_header قرار میگیرد تعریف کند. جامباترون در عمل یک عنصر div است که تعدادی دستور شیوهدهی به آن اعمال میشود (۲). انتخابگر jumbotron این دستورهای شیوهدهی را از کتابخانهی بوتاسترپ بر این عنصر اعمال میکند.
داخل جامباترون سه عنصر قرار دارد. اوّلی پیامی کوتاه است، Track your learning، که به کاربران تازهوارد دیدی کلّی از کل پروژه میدهد. کلاس h1 عنوان سطح اوّل است و انتخابگر display-3 این عنوان خاص را کمی نازکتر و بلندتر میکند (۳). در ۴ پیامی طولانیتر میآوریم که حاوی اطّلاعات بیشتری دربارهی آنچه کاربر میتواند با دفترچهی آموختههای خود بکند است.
به جای استفاده از یک پیوند متنی، در ۵ یک دکمه میسازیم که کاربران را به ایجاد حساب دعوت میکند. این همان پیوند موجود در عنوان است امّا دکمه در صفحه به چشم میآید و به بیننده میگوید برای شروع کار در پروژه باید چه بکند. انتخابگرهایی که اینجا میبینید این دکمه را بزرگ میکنند که بیانگر درخواست انجام یک عمل است. کد » یک عنصر HTML است که مانند دو علامت بزرگتری ترکیبشده (>>) به نظر میآید. در ۶ بلوک page_header را میبندیم. چون هیچ مطلب دیگری قرار نیست به این صفحه اضافه کنیم، به تعریف بلوک content احتیاجی نیست.
اکنون صفحهی اوّل مانند شکل ۲۰-۱ دیده میشود و این پیشرفت محسوسی نسبت پروژهی بدون شکل ما به حساب میآید.
7 - آراستن صفحهی ورود
ما ظاهر کلی صفحهی ورود را بازنگری کردیم امّا هنوز به فرم ورود نپرداختهایم. حال با تغییر دادن فایل login.html کاری میکنیم که این فرم مشابه بخشهای صفحه به نظر بیاید:
{% extends "learning_logs/base.html" %}
{% load bootstrap4 %}
{% block page_header %}
<h2>Log in to your account.</h2>
{% endblock page_header %}
{% block content %}
<form method="post" action="{% url 'users:login' %}" class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">Log in</button>
{% endbuttons %}
<input type="hidden" name="next"
value="{% url 'learning_logs:index' %}" />
</form>
{% endblock content %}
در ۱ تگهای قالبی bootstrap4 را وارد قالب خود میکنیم. در ۲ قسمت page_header را تعریف میکنیم که به کاربر توضیح میدهد این صفحه چه میکند. دقّت کنید که بخش {% if form.errors %} را از قالب حذف کردهایم زیرا django-bootstrap4 به طور خودکار خطاهای فرم را مدیریّت میکند.
در ۳ مشخّصهی class="form" را اضافه میکنیم و سپس از تگ قالبی {% bootstrap_form %} برای نمایش فرم استفاده میکنیم (۴)؛ این تگ جایگزین {{ form.as_p }} بهکاررفته در فصل ۱۹ میشود. تگ قالبی {% bootstrap_form %} هنگام تولید فرم قواعد شکلدهی بوتاسترپ را به تک تک اعضای آن اعمال میکند. در ۵ یک تگ قالبی {% buttons %} باز میکنیم که شکلدهی بوتاسترپ را به دکمهها اعمال میکند.
شکل ۲۰-۲ فرم ورود را پس از تغییرات نشان میدهد. این صفحه بسیار تمیزتر شده، شکل آن مشابه بقیهی صفحهها شده و هدف مشخّصی دارد. سعی کنید با نام کاربری یا گذرواژهای نادرست وارد شوید؛ خواهید دید که حتّی شیوهی پیامهای خطا هم یکشکل است و به کلیّت سایت میخورد.
شکل ۲۰-۲: صفحهی ورود به کمک بوتاسترپ شکل گرفته است.
8 - شکل دادن به صفحهی موضوعات
حال باید مطمئن شویم که صفحههای مربوط به دیدن اطّلاعات هم به خوبی شکل گرفتهاند، کار را از صفحهی موضوعات شروع میکنیم:
{% extends "learning_logs/base.html" %}
{% block page_header %}
<h1>Topics</h1>
{% endblock page_header %}
{% block content %}
<ul>
{% for topic in topics %}
<li><h3>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</h3></li>
{% empty %}
<li><h3>No topics have been added yet.</h3></li>
{% endfor %}
</ul>
<h3><a href="{% url 'learning_logs:new_topic' %}">Add a new topic</a></h3>
{% endblock content %}
اینجا به تگ {% load bootstrap4 %} دیگری احتیاجی نداریم زیرا در این فایل از هیچکدام از تگهای قالبی bootstrap4 استفاده نمیکنیم. عنوان Topics را به بخش page_header منتقل میکنیم و به جای استفاده از یک تگ سادهی پاراگراف، به آن شکل عنوان میدهیم (۱). هر موضوع را به شکل یک عنصر <h3> درمیآوریم تا در صفحه کمی بزرگتر به چشم بیاید (۲) و همین کار را برای پیوند افزودن موضوع جدید انجام میدهیم.
9 - شکل دادن به مطالب در صفحهی موضوعها
صفحهی موضوعها بیشترین محتوا را در بین صفحههای سایت دارد پس کمی کار بیشتری میبرد. از مولفهی کارت بوتاسترپ استفاده میکنیم تا هر موضوع متمایز به نظر بیاید. کارت یک div با مجموعهای از شیوههای منعطف و ازپیشتعریفشده است که برای نمایش مطالب مرتبط با یک موضوع عالی هستند:
{% extends 'learning_logs/base.html' %}
{% block page_header %}
<h3>{{ topic }}</h3>
{% endblock page_header %}
{% block content %}
<p>
<a href="{% url 'learning_logs:new_entry' topic.id %}">Add new entry</a>
</p>
{% for entry in entries %}
<div class="card mb-3">
<h4 class="card-header">
{{ entry.date_added|date:'M d, Y H:i' }}
<small><a href="{% url 'learning_logs:edit_entry' entry.id %}">
edit entry</a></small>
</h4>
<div class="card-body">
{{ entry.text|linebreaks }}
</div>
</div>
{% empty %}
<p>There are no entries for this topic yet.</p>
{% endfor %}
{% endblock content %}
ابتدا در ۱ موضوع را داخل بخش page_header قرار میدهیم. سپس فهرست نامرتّبی را که قبلاً در این قالب به کار بردهایم، حذف میکنیم. به جای آن هر مطلب را به یک عضو فهرست تبدیل میکنیم و یک عنصر div با انتخابگر card در ۲ درست میکنیم. این کارت دو عنصر داخلی دارد: یکی که برچسب زمانی و پیوند ویرایش مطلب را نگه میدارد و دیگری بدنهی مطلب را در برمیگیرد.
اوّلین عنصر داخل کارت عنوانی از نوع <h4> با انتخابگر card-header است (۳). این کارت شامل تاریخ نوشته شدنِ مطلب و پیوندی برای ویرایش آن است. تگ <small> پیرامون پیوند edit_entry باعث میشود کوچکتر از برچسب زمانی دیده شود (۴). دومین عنصر یک div با انتخابگر card-body است (۵) که متن مطلب را داخل یک جعبهی ساده در کارت قرار میدهد. توجّه کنید که کد جانگو برای آوردن اطّلاعات در صفحه تغییر نکرده است؛ تنها عنصرهایی تغییر کردهاند که ظاهراً صفحه را تحت تأثیر قرار میدهند.
شکل ۲۰-۳ صفحهی موضوع را با ظاهر جدید نمایش میدهد. عملکرد سایت عوض نشده امّا اکنون به نظر کاربران حرفهایتر و جذّابتر میآید.
شکل ۲۰-۳: صفحهی موضوعها با شکلدهی بوتاسترپ
خودآزمایی
۲۰-۱- فرمهای دیگر: شیوههای بوتاسترپ را به صفحهی ورود اعمال کردیم. تغییراتی مشابه را در بقیهی صفحههای فرمدار مانند new_topic، new_entry، edit_entry و register اعمال کنید.
۲۰-۲- بلاگ خوشقیافه: از بوتاسترپ برای شکل دادن به پروژهی وبلاگی که در فصل ۱۹ ساختید استفاده کنید.
10 - استقرار پروژه
اکنون که یک پروژه با قیافهای حرفهای داریم بیایید آن را روی یک سرور در حال کار مستقر کنیم تا هر شخص متّصل به اینترنت بتواند از آن استفاده کند. ما از Heroku استفاده میکنیم که یک بستر مبتنی بر وب است و به شما امکان میدهد که استقرار نرمافزارهای تحت وب خود را مدیریّت کنید. ما پروژهی Learning Log را برپا کرده و روی هروکو اجرا میکنیم.
ساختن یک حساب کاربری هروکو
برای ساختن یک حساب کاربری به https://heroku.com/ بروید و روی یکی از پیوندهای ثبت نام کلیک کنید. ساختن حساب رایگان است، هروکو یک گزینهی رایگان دارد که به شما اجازه میدهد پروژههای خود را پیش از استقرار کامل در یک محیط زنده آزمایش کنید.
نصب کردن رابط خط فرمان هروکو
برای استقرار و مدیریّت یک پروژه روی سرورهای هروکو182 به ابزارهایی نیاز دارید که در رابط خطّ فرمان (CLI) هروکو در دسترساند. برای نصب کردن آخرین نسخهی این رابط به https://devcenter.heroku.com/articles/heroku-cli/ بروید و دستورالعملهای مربوط به سیستم عامل خود را پی بگیرید. این دستورالعملها یا شامل یک فرمان ترمینال یکخطی است یا یک نصبکننده است که میتوانید آن را دریافت و اجرا کنید.
نصب کردن بستههای مورد نیاز
شما باید سه بسته را نیز نصب کنید که کمک میکنند تا پروژههای جانگو را روی یک سرور زنده قرار دهید. در یک محیط فعّال مجازی فرمانهای زیر را صادر کنید:
بستهی psycopg2 برای مدیریّت پایگاهدادهی مورد استفادهی هروکو م183
ورد نیاز است. بستهی django-heroku تقریباً تمام تنظیمات مورد نیاز را برای اجرای برنامه روی سرورهای هروکو مدیریّت میکند. این شامل مدیریّت پایگاه داده و ذخیره کردن فایلهای ایستا در جایی که بتواند به خوبی عرضه شود میشود. فایلهای ایستا قواعد شکلدهی و فایلهای جاوااسکریپت را شامل میشوند. بستهی gunicorn سروری ارائه میکند که قادر به ارائهی برنامهها در محیطی زنده است.
11 - ساختن فایلهای پیکربندی
ساختن یک فایل requirements.txt
هروکو باید بداند که پروژهی ما روی چه بستههایی بنا شده است بنابراین از pip برای تولید فایلی شامل آنها استفاده میکنیم. دوباره در یک محیط مجازی فعّال فرمان زیر را صادر کنید:
|
|
دستور freeze از pip میخواهد که نام تمام بستههایی که در حال حاضر در پروژهی ما نصب شده در فایل requirements.txt بنویسد. این فایل را باز کنید تا نام و نسخهی بستههای نصبشده در پروژهی خود را ببینید:
dj-database-url==0.5.0
Django==2.2.0
django-bootstrap4==0.0.7
django-heroku==0.3.1
gunicorn==19.9.0
psycopg2==2.7.7
pytz==2018.9
sqlparse==0.2.4
whitenoise==4.1.2
Learning Log در حال حاضر به هشت بسته با نسخههای مشخّص وابسته است بنابراین به محیطی مشخّص برای اجرا شدن نیاز دارد. (چهار بسته را خودمان نصب کردهایم و چهار بستهی دیگر به دلیل وابستگی این بستهها به صورت خودکار نصب شدهاند.)
زمانی که Learning Log را مستقر میکنیم هروکو تمام بستههای فهرستشده در requirements.txt را نصب میکند و محیطی پدید میآورد که بستههای آن مشابه آن چیزی است که به صورت محلّی استفاده کردهایم. به همین دلیل ما میتوانیم مطمئن باشیم که رفتار پروژهی استقراریافته مشابه پروژهای خواهد بود که در سیستم محلّی ما اجرا میشود. هنگامی که ساختن و نگهداری پروژههای مختلف را بر سیستم خود آغاز میکنید، این مزیّتی بسیار بزرگ به شمار میآید.
تعیین نسخهی پایتون اجرایی
تا زمانی که نسخهی پایتون را مشخّص نکنید هروکو از نسخهی پایتون پیشفرض فعلی خود استفاده میکند. بیایید مطمئن شویم که هروکو از همان نسخهی پایتون ما استفاده میکند. در یک محیط مجازی فعّال فرمان python --version را صادر کنید:
در این مثال من پایتون نسخهی ۳.۷.۲ را اجرا میکنم. فایل جدیدی به نام runtime.txt در همان پوشهی manage.py بسازید و این را داخل آن فایل وارد کنید:
python-3.7.2
در این فایل یک خط وجود دارد که در آن نسخهی پایتون شما به شکل بالا تعیین میشود؛ مطمئن شوید که python را با حروف کوچک مینویسید و پس از آن یک خط فاصله میگذارید و نسخه را به صورت سهبخشی مینویسید.
تغییر settings.py برای هروکو
حال باید به انتهای settings.py قسمتی اضافه کنیم تا برخی تنظیمات را برای محیط هروکو تعریف کنیم:
اینجا ما ماژول django_heroku را وارد کرده و تابع settings() را صدا میزنیم. این تابع برخی تنظیمات را تغییر میدهد که برای محیط هروکو باید مقدارهای خاصّی داشته باشند.
ساختن یک Procfile برای آغاز کردن فرآیندها
Procfile به هروکو میگوید که برای ارائهی درست پروژه چه فرآیندهایی باید آغاز شوند. این فایل یکخطی را با نام Procfile، با P بزرگ و بدونِ پسوند، در همان پوشهی حاوی manage.py ذخیره کنید.
این خطّی است که در فایل Procfile قرار میگیرد:
web: gunicorn learning_log.wsgi --log-file –
این خط به هروکو میگوید که از gunicorn به عنوان سرور و از تنظیمات داخل learning_log/wsgi.py برای اجرای برنامه استفاده کند. پرچم log-file به هروکو میگوید که چه نوع رویدادهایی را ثبت کند.
12 - استفاده از Git برای ردگیری فایلهای پروژه
چنانکه در فصل ۱۷ گفتیم گیت یک برنامهی کنترل نسخه است که به شما ا184 مکان میدهد هر بار که ویژگی جدیدی را با موفقیّت پیاده میکنید تصویری لحظهای از کد بگیرید. اگر هر مشکلی پیش آمد میتوانید به آخرین تصویری که کار میکرده برگردید؛ برای مثال اگر هنگام کار کردن روی ویژگی جدید به طور اتّفاقی ایرادی ایجاد کردید. به هر کدام از این تصویرها یک سپارش میگویند.
به کمک گیت میتوانید بدون نگرانی از خراب شدن پروژهی خود، پیادهسازی ویژگیهای جدید را امتحان کنید. زمانی که برنامهای را در سرور در حال کار مستقر میکنید باید مطمئن باشید که یک نسخهی عملیّاتی از پروژهی خود را استقرار میدهید. برای کسب اطّلاعات بیشتر دربارهی گیت و کنترل نسخه به پیوست ت مراجعه کنید.
نصب کردن گیت
ممکن است گیت قبلاً روی سیستم شما نصب شده باشد. برای دریافتن این موضوع یک پنجرهی ترمینال جدید باز کنید و دستور git --version را وارد کنید:
اگر به دلایلی با پیام خطا مواجه شدید، دستورالعمل نصب گیت را در پیوست ت ببینید.
پیکربندی گیت
گیت مراقب است که چه کسی در حال ایجاد تغییرات در یک پروژه است، حتّی اگر فقط یک نفر روی پروژه کار کند. برای چنین کار گیت باید نام کاربری و ایمیل شما را بداند. شما باید یک نام کاربری ارائه کنید ولی در پروژههای تمرینی میتوانید از یک ایمیل ساختگی استفاده کنید.
اگر این گام را فراموش کنید، هنگام انجام اوّلین سپارش گیت این اطّلاعات را از شما خواهد پرسید.
نادیده گرفتن فایلها
ما نیازی نداریم که گیت تمام فایلهای پروژه را ردگیری کند بنابراین از آن میخواهیم که از برخی فایلها صرف نظر کند. فایلی به نام .gitignore در پوشهای که حاوی manage.py است بسازید. توجّه کنید که نام فایل با یک نقطه آغاز میشود و پسوند ندارد. این کدی است که در .gitignore قرار میگیرد:
ll_env/
__pycache__/
*.sqlite3
به گیت میگوییم که کل پوشهی ll_env را نادیده بگیرد زیرا میتوانیم آن را هر زمان به طور خودکار بازتولید کنیم. همچنین نمیخواهیم که پوشهی __pycache__ را دنبال کنید چون فایلهای .pyc است که جانگو هنگام اجرای فایلهای .py به طور خودکار میسازد. ما تغییرات اعمالی در پایگاه دادهی محلّی را هم دنبال نمیکنیم زیرا این کار عادت بدی است: اگر از SQLite روی یک سرور استفاده میکنید، ممکن است هنگام ارسال پروژهی خود به آن، به طور تصادفی پایگاه دادهی آزمایشی محلّی خود را جایگزین پایگاه دادهی در حال کار کنید. علامت ستاره در *.sqlite3 به گیت میگوید که هر فایلی با پسوند .sqlite3 را نادیده بگیرد.
.DS_Store را به فایل .gitignore خود اضافه کنید. این فایلی است که اطّلاعاتی در مورد تنظیمات پوشه در macOS را دربرمیگیرد و هیچ ربطی به پروژهی ما ندارد.هویدا کردن فایلهای پنهان
بیشتر سیستمعاملها فایل و پوشههایی را که با نقطه آغاز میشوند پنهان میکنند، مانند .gitignore. اگر از مرورگر فایل یا برنامههایی مانند Sublime Text برای باز کردن آنها استفاده کنید، این نوع فایلها را به صورت پیشفرض نمیبینید. امّا به عنوان یک برنامهنویس باید بتوانید آنها را ببینید. این روش هویدا کردن این فایلهاست بسته به این که از چه سیستم عاملی استفاده کنید:
- در ویندوز Windows Explorer را باز کنید و سپس پوشهای مانند میز کار را باز کنید. روی برگهی Tab بزنید و مطمئن شوید که File name extensions و Hidden items علامت خورده باشند.
- در macOS میتوانید دکمههای SHIFT-. را در پنجرهی هر مرورگر فایلی بزنید تا فایل و پوشههای پنهان را ببینید.
- در سیستمهای لینوکسی مانند اوبونتو، با فشار دادن CTRL-H در هر مرورگر فایل میتوانید فایلها و پوشههای پنهان را ببینید. برای این که این تنظیمات را دائمی کنید مرورگر فایلی مانند Nautilus را باز کنید و روی برگهی گزینهها (که با سه خط نشان داده شده) کلیک کنید. گزینهی Show Hidden Files را انتخاب کنید.
سپارش پروژه
ما باید برای Learning Log یک مخزن گیت راه بینداز185 یم، تمام فایلهای لازم را به آن اضافه کنیم و وضعّیت اوّلیّهی پروژه را برونسپاری کنیم. این روش انجام این کار است:
|
|
در ۱ فرمان git init را برای راهاندازی یک مخزن خالی در پوشهی حاوی Learning Log صادر میکنیم. در ۲ از git add . استفاده میکنیم که تمام فایلهایی را که نادیده گرفته نشدهاند، به مخزن اضافه میکند. (نقطه را فراموش نکنید.) در ۳ فرمان git commit -am commit message را صادر میکنیم: پرچم -a به گیت میگوید که تمام فایلهای تغییریافته را هنگام سپارش در نظر بگیر و پرچم -m یک پیام پیگیری را درخواست میکند.
صدور فرمان git status در ۴ نشان میدهد که در شاخهی master هستیم و درخت کاری ما تمیز است. این وضعیّتی است که پس از هر بار ارسال پروژه به هروکو میخواهید ببینید.
13 - ارسال به هروکو و برپا کردن پایگاه داده
ارسال به هروکو
در نهایت میخواهیم پروژه را به هروکو بفرستیم. در یک محیط فعّال مجازی فرمانهای زیر را وارد کنید:
|
|
ابتدا فرمان heroku login را وارد میکنید که شما را به صفحهای در مرورگرتان میبرد تا در آنجا به حساب هروکوی خود وارد شوید (۱). سپس به هروکو میگویید که یک پروژهی خالی درست کند (۲). هروکو نامی متشکّل از دو کلمه و یک عدد درست میکند؛ میتوانید آن را بعداً عوض کنید. سپس دستور git push heroku master را وارد میکنیم (۳) که به گیت میگوید شاخهی اصلی پروژه را در مخزنی که هروکو ساخته بفرست. هروکو با استفاده از این فایلها پروژه را در سرورهای خود میسازد. در ۴ آدرسی قرار دارد که از آن برای دسترسی به پروژهی در حال کار استفاده میکنیم و میتوانیم آن را به همراه نام پروژه عوض کنیم.
زمانی که این فرمانها را صادر میکنید پروژه استقرار مییابد امّا به طور کامل پیکربندی نشده است. برای بررسی این که فرآیندهای سرور به درستی آغاز شدهاند یا نه، از دستور heroku ps استفاده کنید:
|
|
خروجی نشان میدهد که این پروژه در ماه آینده چهقدر دیگر میتواند فعّال بماند (۱). در زمان نگارش این مطلب هروکو به استقرارهای رایگان اجازه میدهد که حداکثر ۵۵۰ ساعت در ماه فعّال باشند. اگر پروژهای این حد را بگذراند یک صفحهی خطای سرور استاندارد نمایش داده خواهد شد؛ که آن را به زودی شخصی میکنیم. در ۲ میبینیم که فرآیند تعریفشده در Procfile شروع شده است.
حال میتوانیم به کمک دستور heroku open برنامه را در یک مرورگر باز کنیم:
این دستور شما را از باز کردن یک مرورگر و وارد کردن آدرسی که هروکو نشان داده خلاص میکند و این راهی دیگر برای باز کردن سایت است. شما باید صفحهی خانهی Learning Log را با شیوهی درست ببینید. با این حال هنوز نمیتوانید از آن استفاده کنید چون پایگاه داده را برپا نکردهاید.
برپا کردن پایگاه داده در هروکو
ما نیاز داریم که migrate را یک بار اجرا کنیم تا پایگاه دادهی در حال اجرا را برپا و تمام انتقالهایی را که طیّ توسعهی پروژه انجام دادهایم در آن اعمال کنیم. شما میتوانید به کمک دستور heroku run دستورهای جانگو و پایتون را روی پروژهی هروکو اجرا کنید. این روش اجرای migrate روی هروکو است:
|
|
ابتدا دستور heroku run python manage.py migrate را اجرا میکنیم (۱). هروکو سپس یک نشست ترمینال میسازد تا فرمان migrate را اجرا کنید (۲). در ۳ جانگو انتقال پیشفرض و دیگر انتقالهایی را که طی توسعهی پروژه ساخته شدهاند، اعمال میکند.
اگر اکنون برنامهی استقراریافتهی خود را ببینید، باید درست مثل آنچه در سیستم محلّی شما بود، بتوانید با آن کار کنید. امّا هیچکدام از دادههایی را که در سیستم محلّی وارد کردهاید، شامل حساب ابرکاربر خود، نخواهید دید زیرا آنها را به سرور در حال کار کپی نکردهاید. این عملکردی طبیعی است: شما معمولاً دادههای محلّی را به سرور در حال کار منتقل نمیکنید زیرا دادههای محلّی معمولاً دادههای آزمایشی هستند.
میتوانید پیوند هروکوی خود را همخوان کنید تا هر کس که خواست از برنامهی شما استفاده کند. در بخش بعدی چند کار دیگر را تکمیل میکنیم تا فرآیند استقرار تکمیل شود و شما را برای ادامه دادن به توسعهی Learning Log راه بیندازد.
14 - بهبود استقرار هروکو
اکنون فرآیند استقرار را با ساختن یک ابرکاربر بهبود میبخشیم، درست همانند آن چه به صورت محلّی کردیم. همچنین پروژه را با تغییر تنظیم DEBUG به False امنتر میکنیم تا کاربران در پیامهای خطا هیچ اطّلاعات اضافیتری که با آنها در حمله به سرور کمک میکند، مشاهده نکنند.
ساختن یک ابرکاربر در هروکو
شما قبلاً دیدهاید که میتوانیم دستورهای یکطرفه را به کمک فرمان heroku run اجرا کنیم. امّا علاوه بر این شما میتوانید هنگامی که با دستور heroku run bash به سرور هروکو متّصل شدهاید، دستورها را با باز کردن یک نشست ترمینال Bash اجرا کنید. بَش یک زبان است که در بسیاری از ترمینالهای لینوکسی اجرا میشود. ما از نشست ترمینال بَش برای ساختن یک ابرکاربر استفاده میکنیم تا بتوانیم روی برنامهی در حال کار به سایت مدیر دسترسی داشته باشیم:
|
|
در ۱ ls را اجرا میکنیم تا ببینیم چه فایلها و پوشههایی روی سرور وجود دارد که این موارد باید مشابه آنهایی باشند که در سیستم محلّی داریم. شما میتوانید مانند هر سیستم فایلی دیگر در این فایلها و پوشهها بگردید.
ls به جای dir) زیرا شما از طریق یک ارتباط از راه دور در حال اجرای یک ترمینال لینوکسی هستید.در ۲ فرمان ساختن ابرکاربر را اجرا میکنیم که خروجی آن مشابه با خروجیای است که در سیستم محلّی خود هنگام ساختن ابرکاربر در فصل ۱۸ دیدیم. زمانی که کار ساختن ابرکاربر در این ترمینال به پایان رسید فرمان exit را اجرا کنید تا به نشست ترمینال سیستم محلّی خود برگردید.
حال میتوانید /admin/ را به انتهای آدرس برنامهی در حال کار اضافه کنید و به سایت مدیر وارد شوید. برای من آدرس https://secret-lowlands-82594.herokuapp.com/admin/ است.
اگر دیگران استفاده از پروژهی شما را آغاز کردهاند، دقّت کنید که به تمام اطّلاعات آنها دسترسی دارید! این را ساده نگیرید تا کاربران همچنان به شما اعتماد کنند.
ساختن یک آدرس کاربرپسند در هروکو
به احتمال فراوان شما دوست دارید که آدرس پروژه دوستانهتر و بهیادماندنیتر از https://secret-lowlands-82594.herokuapp.com باشد. میتوانید نام برنامه را با یک دستور عوض کنید:
|
|
برای نامگذاری برنامهی خود میتوانید از حرفها، اعداد و خطهای فاصله استفاده کنید و آن را هر چه که بخواهید بنامید مگر این که کسی قبلاً آن نام را گرفته باشد. این استقرار اکنون بر https://learning-log.herokuapp.com در حال اجراست. این پروژه دیگر از آدرس قبلی در دسترس نخواهد بود؛ دستور apps:rename پروژه را کاملاً به URL جدید منتقل میکند.
15 - امن کردن پروژهی در حال کار
یک ایراد امنیّتی چشمگیر در نحوهی استقرار فعلی پروژهی ما این است: تنظیم DEBUG=True در settings.py که هنگام بروز خطا پیامهای اشکالزدایی را نمایش میدهد. صفحههای خطای جانگو هنگام توسعه پروژه اطّلاعاتی حیاتی برای اشکالزدایی در اختیار شما قرار میدهند؛ با این حال اگر آنها را در سرور در حال کار فعّال بگذاریم به مهاجمان اطّلاعاتی بیش از اندازه میدهند.
این که اطّلاعات اشکالزدایی روی سرور زنده نمایش دا188 ده شوند یا نه با تنظیم یک متغیّر محیطی کنترل میشوند. متغیّرهای محیطی مقدارهایی هستند که در یک محیط خاص تنظیم میشوند. این یکی از راههای نگهداری اطّلاعات حسّاس روی سرور است: آنها را از دیگر کدهای پروژه جدا میکنیم.
اجازه دهید settings.py را تغییر دهیم تا هنگام اجرای پروژه روی هروکو به دنبال یک متغیّر محیطی بگردد:
متد os.environ.get() مقدار مرتبط با یک متغیّر محیطی خاص را در هر محیطی که پروژه در آن اجرا میشود میخواند. اگر متغیّری که به دنبال آن هستیم مقدار داشته باشد، متد آن را برمیگرداند و اگر نه متد None برمیگرداند. استفاده از متغیّرهای محیطی برای ذخیره کردن مقدارهای بولی ممکن است گیجکننده باشد. در بسیاری از موارد متغیّرهای محیطی به صورت رشته ذخیره میشوند و شما باید مراقب این باشید. این قطعهکد را از یک نشست ترمینال پایتون در نظر بگیرید:
مقدار بولی رشتهی 'False' برابر با True است زیرا هر رشتهی غیر تهی True ارزیابی میشود. بنابراین از رشتههای 'TRUE' و 'FALSE' با حروف بزرگ استفاده میکنیم تا شفّاف بگوییم مقدارهای بولی True و False پایتون را ذخیره نمیکنیم. زمانی که جانگو متغیّری محیطی را با کلید 'DEBUG' در هروکو میخواند، اگر مقدار آن 'TRUE' باشد، مقدار DEBUG را True میگذارد و اگر 'FALSE' باشد مقدار متغیّر DEBUG را False میگذارد.
سپارش و انتقال تغییرات
حال باید تغییراتی را که در settings.py اعمال کردهایم در مخزن گیت اعمال کنیم و آنها را به هروکو بفرستیم. این نشست ترمینالی است که این فرآیند را نشان میدهد:
فرمان git commit را به همراه یک پیام سپارش ساده امّا گویا اجرا میکنیم (۱). به یاد بیاورید که پرچم -am باعث میشود گیت تمام فایلهای تغییریافته را اعمال کند و پیامی برای پیگیری ضبط کند. گیت تشخیص میدهد که یک فایل تغییر کرده است و این تغییر را در مخزن اعمال میکند.
در ۲ وضعیّت نشان میدهد که ما در حال کار روی شاخهی اصلی مخزن هستیم و اکنون تغییر جدیدی برای اعمال وجود ندارد. مهم است که پیش از ارسال تغییرات به هروکو وضعیّت را بررسی کنید. اگر این پیام را نبینید برخی از تغییرات هنوز اعمال نشدهاند و آن تغییرات به سرور ارسال نخواهند شد. در این صورت میتوانید دستور commit را دوباره صادر کنید و اگر مطمئن نیستید که چگونه این مشکل را حل کنید پیوست ت را ببینید تا کار کردن با گیت را بهتر درک کنید.
حال مخزن بهروزشده را به هروکو ارسال میکنیم:
|
|
هروکو تشخیص میدهد که مخزن بهروزشده است و این باعث میشود که پروژه بازسازی شود تا مطمئن شود تمام تغییرات در نظر گرفته شدهاند. این کار باعث بازسازی پایگاه داده نمیشود بنابراین نیازی نیست migrate را برای این بهروزرسانی اجرا کنیم.
تنظیم متغیّرهای محیطی در هروکو
حال میتوانیم مقدار مورد نظر خود برای DEBUG در settings.py را از طریق هروکو تنظیم کنیم. دستور heroku config:set یک متغیّر محیطی را برای ما تنظیم میکند:
زمانی که در هروکو یک متغیّر محیطی را تنظیم میکنید، پروژه را به طور خودکار دوباره اجرا میکند تا متغیّر محیطی عمل کند.
برای این که ببینید استقرار پروژه اکنون امنتر شده است آدرس پروژه را با مسیری که تعریف نکردهایم وارد کنید. برای مثال سعی کنید http://learning-log.herokuapp.com/letmein را باز کنید. باید یک صفحهی خطای نوعی را ببینید که به شما هیچ اطّلاعات خاصّی دربارهی پروژه نمیدهد. اگر همین درخواست را روی نسخهی محلّی پروژه به آدرس http://localhost:8000/letmein/ بدهید صفحهی خطای کامل جانگو را خواهید دید. نتیجه عالی است: شما هنگام توسعهی پروژه روی سیستم خود پیامهای خطای پرمعنا میبینید امّا کاربران روی سایت در حال کار هیچ اطّلاعات حیاتیای دربارهی برنامهی پروژه نخواهند دید.
اگر قصد شما تنها استقرار برنامه و اشکالزدایی اوّلیّهی آن است میتوانید heroku config:set DEBUG='TRUE' را اجرا کنید و به طور موقّت یک گزارش خطای کامل ببینید. مطمئن شوید که پس از پایان اشکالزدایی این مقدار را به 'FALSE' برمیگردانید. همچنین مراقب باشید هنگامی که کاربران به طور معمول به سایت شما دسترسی دارند این کار را انجام ندهید.
16 - ساختن صفحههای خطای شخصی
در فصل ۱۹ پروژه را طوری پیکربندی کردیم که اگر کاربر صفحهای را درخواست کرد که وجود نداشت یا نوشتهای را که متعلّق به او نبود درخواست کرد، یک خطای 404 برگرداند. شما احتمالاً تا الان به برخی خطاهای سرور 500 (خطاهای داخلی) برخوردهاید. خطای 404 معمولاً به این معنی است که کد جانگو درست است امّا چیزی که درخواست میشود وجود ندارد؛ خطای 500 به طور معمول به این معنی است که در کدی که نوشتهاید خطایی وجود دارد، مانند خطایی در یک تابع در views.py. هماکنون جانگو همان صفحهی خطای عمومی را در هر دو وضعیّت برمیگرداند. امّا میتوانیم قالب صفحههای خطای 404 و 500 خودمان را بنویسیم که به ظاهر کلّی پروژه میخورد. این قالبها باید در پوشهی ریشهی قالبها قرار بگیرند.
ساختن قالبهای شخصی
در بیرونیترین پوشهی learning_log پوشهای به نام templates بسازید. سپس فایلی جدید به نام 404.html بسازید؛ مسیر این فایل باید learning_log/templates/404.html باشد. این کد این فایل است:
{% extends "learning_logs/base.html" %}
{% block page_header %}
<h2>The item you requested is not available. (404)</h2>
{% endblock page_header %}
این قالب ساده اطّلاعات صفحهی خطای 404 را در اختیار میگذارد امّا شکل آن مانند بقیهی سایت است.
فایلی دیگر به نام 500.html با کد زیر بسازید:
{% extends "learning_logs/base.html" %}
{% block page_header %}
<h2>There has been an internal error. (500)</h2>
{% endblock page_header %}
این دو فایل جدید به تغییر کوچک در settings.py نیاز دارند:
این تغییر به جانگو میگوید که داخل پوشهی ریشهی قالبها به دنبال قالب صفحههای خطا بگردد.
دیدن صفحههای خطا به صورت محلّی
اگر بخواهید پیش از ارسال پروژه به هروکو صفحههای خطا را مانند قبل در سیستم خود ببینید باید ابتدا در تنظیمات محلّی خود DEBUG=False را اعمال کنید تا صفحههای اشکالزدایی پیشفرض جانگو غیرفعّال شوند. برای این کار تغییر زیر را در settings.py اعمال کنید (مطمئن شوید روی بخشی از settings.py کار میکنید که به محیط محلّی مربوط است نه بخشی که به هروکو ارتباط دارد):
حال یک موضوع یا مطلب را که به شما مربوط نیست درخواست کنید تا صفحهی خطای 404 را ببینید. برای امتحان صفحهی خطای 500 موضوع یا مطلبی را درخواست کنید که وجود ندارد. برای مثال آدرس http://localhost:8000/topics/999 باید یک خطای 500 ایجاد کند مگر این که قبلاً ۹۹۹ موضوع آزمایشی ایجاد کرده باشید!
پس از این که آزمایش صفحههای خطا به پایان رسید برای توسعهی پروژه در آینده مقدار محلّی DEBUG را به True برگردانید. (مطمئن شوید روشی را که DEBUG در بخش تنظیمات محیط هروکو مدیریّت میشود تغییر ندهید.)
انتقال تغییرات به هروکو
حال باید تغییراتی که در صفحههای خطا ایجاد کردهایم اعمال و آن را به سرور هروکو بفرستیم:
|
|
فرمان git add . را در ۱ صادر میکنیم زیرا چند فایل جدید به پروژه اضافه کردهایم و باید به گیت بگوییم که آنها را ردگیری کند. سپس در ۲ تغییرات را اعمال و در ۳ پروژهی بهروزشده را به هروکو میفرستیم.
حال اگر صفحهی خطایی پدیدار شود شکل آن باید شبیه به بقیهی سایت باشد که این هنگام بروز خطا موجب تجربهی کاربری لطیفتری میشود.
17 - استفاده از get_object_or_404()
تا اینجا اگر کاربر موضوع یا مطلبی را که وجود ندارد به صورت دستی درخواست کند به خطای سرور 500 برمیخورد. جانگو سعی میکند صفحهای را که وجود ندارد بسازد امّا چون برای این کار اطّلاعات کافی ندارد خطای 500 ایجاد میشود. این وضعّیت به طور دقیقتر شبیه به خطای 404 است و میتوانیم این رفتار را به کمک تابع میانبر get_object_or_404() جانگو پیادهسازی کنیم. این تابع تلاش میکند که شیء درخواستی را از پایگاه داده بگیرد، امّا اگر وجود نداشت یک استثنای 404 ایجاد میکند. این تابع را در views.py وارد میکنیم و آن را به جای get() میگذاریم:
|
|
حال اگر موضوعی را درخواست کنید که وجود ندارد (برای مثال http://localhost:8000/topics/999) یک صفحهی خطای 404 خواهید دید. برای استقرار این تغییر یک سپارش جدید ایجاد کنید و پروژه را به هروکو انتقال دهید.
18 - توسعههای آینده و نکتههای پایانی
شما ممکن است بخواهید پس از انتقال اوّلیّهی پروژه به سرور آن را توسعه دهید یا پروژههای خود را برای استقرار توسعه دهید. فرآیندی تقریباً یکسان برای بهروزرسانی پروژهها وجود دارد.
ابتدا هر تغییری که مورد نیاز است در پروژهی محلّی خود ایجاد میکنید. اگر این تغییرات به ایجاد فایلهای جدید منجر میشود آنها را با دستور git add . به مخزن گیت اضافه کنید. (مطمئن شوید که نقطه را در پایان دستور میآورید.) هر تغییری در انتقال پایگاه داده به این دستور نیاز دارد چون در هر انتقال یک فایل انتقال جدید ساخته میشود.
دوم تغییرات را در مخزن خود به کمک دستور git commit -am "commit message" اعمال کنید. پس از آن تغییرات را با دستور git push heroku master به سرور منتقل کنید. اگر پایگاه دادهی محلّی خود را هم انتقال داده باشید باید پایگاه دادهی در حال کار روی سرور را هم انتقال دهید. یا باید از دستورهای یکطرفه مانند heroku run python manage.py migrate استفاده کنید یا یک نشست ترمینال از راه دور با دستور heroku run bash باز کنید و دستور python manage.py migrate را اجرا کنید. سپس پروژهی در حال کار خود را ببینید و مطمئن شوید که تغییرات مورد انتظارتان اعمال شده است یا نه.
تنظیمات SECRET_KEY
جانگو از مقدار تنظیمشدهی SECRET_KEY در settings.py برای پیادهسازی تعدادی از پروتکلهای امنیّتی استفاده میکند. در این پروژه فایل تنظیمات خود را به همراه تنظیم SECRET_KEY اعمال کردهایم. این برای پروژههای تمرینی خوب است امّا برای محصول نهایی باید این تنظیم را با دقّت بیشتری انجام داد. اگر پروژهای میسازید که کاربردی جدّیتر دارد مطمئن شوید که دربارهی روش مدیریّت امنتر SECRET_KEY تحقیق کنید.
پاک کردن پروژهای از هروکو
طی کردن چندبارهی فرآیند استقرار برای یک پروژه یا استقرار چند پروژهی کوچک برای آشنایی با روندها تمرین بسیار خوبی است. امّا باید روش پاک کردن پروژهای را که مستقر شده هم بدانید. علاوه بر این هروکو تعداد پروژههایی را که میتوانید به صورت رایگان مستقر کنید محدود میکند و شما نمیخواهید که حساب خود را با پروژههای تمرینی به هم بریزید.
به وبسایت هروکو (https://heroku.com) وارد شوید؛ به صفحهای که نمایانگر پروژههای شماست راهنمایی میشوید. روی پروژهای که میخواهید پاک کنید کلیک کنید. صفحهای جدید با اطّلاعاتی دربارهی آن پروژه خواهید دید. روی پیوند Settings کلیک کنید و پایین بروید تا به پیوندی برای پاک کردن پروژه برسید. این عمل برگشتپذیر نیست پس هروکو از شما میخواهد که با وارد کردن دستی نام پروژه درخواست پاک کردن آن را تایید کنید.
اگر کار کردن از یک ترمینال را ترجیح میدهید میتوانید پروژه را با صدور فرمان destroy هم پاک کنید:
|
|
در اینجا appname نام پروژهی شماست که باید چیزی شبیه به secret-lowlands-82594 یا اگر نام پروژه را عوض کردهاید، learning-log باشد. از شما خواسته میشود که نام پروژه را دوباره وارد کنید تا حذف کردن تایید شود.
خودآزمایی
۲۰-۳- وبلاگ زنده: پروژهی بلاگی را که روی آن کار میکردهاید روی هروکو مستقر کنید. مطمئن شوید که DEBUG را برابر با False میگذارید تا صفحههای خطای کامل جانگو هنگام بروز خطا دیده نشوند.
۲۰-۴- 404های بیشتر: تابع get_object_or_404() باید در نماهای new_entry() و edit_entry() هم استفاده شود. این تغییر را ایجاد کنید و با وارد کردن آدرسی مانند http://localhost:8000/new_entry/999 بررسی کنید که آیا خطای 404 را میبینید یا نه.
۲۰-۵- Learning Log توسعهیافته: یک ویژگی جدید به پروژه اضافه کنید و تغییر را به استقرار در حال کار خود بفرستید. تغییری ساده را امتحان کنید، مثلاً در صفحهی خانه کمی بیشتر دربارهی پروژه بنویسید. یک ویژگی پیشرفتهتر را امتحان کنید، مثلاً این که به کاربران امکان عمومی کردن یک موضوع را بدهید. برای این کار باید مشخّصهای به نام public را به مدل Topic اضافه کنید (که به صورت پیشفرض False باشد) و همچنین عنصری به فرم صفحهی new_topic اضافه کنید که به کاربر اجازهی تغییر موضوع از خصوصی به عمومی را بدهد. در ادامه باید پروژه را انتقال دهید و views.py را بازنگری کنید تا هر موضوعی که عمومی بود برای کاربران واردنشده هم قابل دیدن باشد. فراموش نکنید که پایگاه دادهی در حال کار را هم پس از ارسال تغییرات به هروکو انتقال دهید.
19 - خلاصه
در این فصل آموختید که چگونه به کمک کتابخانهی بوتاسترپ و برنامهی django-bootstrap4 پروژههای خود ظاهری ساده امّا حرفهای بدهید. به کمک بوتاسترپ شکل و شیوهای که انتخاب میکنید تقریباً روی هر افزارهای که مردم برای دیدن پروژهی شما استفاده میکنند به یک شکل به نظر میآید.
شما دربارهی قالبهای بوتاسترپ آموختید و از قالب Navbar static برای ساختن یک شکل و ظاهر ساده برای Learning Log استفاده کردید. از جامباترون برای متمایز کردن پیام صفحهی خانه استفاده کردید و آموختید که چگونه تمام صفحهها را به یک صورت شکل دهید.
در آخرین بخش پروژه یاد گرفتید که چگونه یک پروژه را روی سرورهای هروکو مستقر کنید تا هر کس بتواند به آن دسترسی داشته باشد. یک حساب کاربری هروکو ساختید و چند ابزار نصب کردید که در مدیریّت فرآیند استقرار به شما کمک میکند. از گیت برای سپارش پروژهی در حال کار به یک مخزن و سپس انتقال آن به سرورهای هروکو کمک گرفتید. در نهایت یاد گرفتید که با تنظیم DEBUG=False روی سرور امن کردن برنامهی خود را شروع کنید.
حال که این پروژه را به پایان رساندهاید میتوانید ساختن پروژههای خود را شروع کنید. از کارهای ساده شروع کنید و مطمئن شوید که پروژههای پیش از افزودن پیچیدگی به درستی کار میکنند. از آموختن پیوستهی خود لذّت ببرید و در پروژههای خود موفّق باشید!