{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Web開発には多くのスキルが必要です。 \n", "あなたは正しく動作するようにウェブサイトをプログラムしなければならないだけでなく、ユーザーはそれも良い見て期待しています。 \n", "すべてを最初から作成しているときは、美しいサイトに必要なHTML / CSSをすべて追加することも圧倒的です。 \n", "幸いなことに、レスポンシブなモバイル第一のプロジェクトを構築するための最も一般的なフレームワークであるBootstrapがあります。 \n", "一般的なWebサイトのレイアウト機能に合わせて独自のCSSとJavaScriptを作成するのではなく、ブートストラップを利用して重い作業を行うことができます。 \n", "これは、私たちがすばらしい見た目のウェブサイトをすばやく得ることができる、私たちの部分にわずかなコードしかないことを意味します。 \n", "また、プロジェクトの進行に合わせてカスタム変更を加えたい場合は、必要に応じてBootstrapを簡単に上書きすることもできます。 \n", "デザインではなくプロジェクトの機能に集中したい場合は、ブートストラップが最適です。 だから私たちはここでそれを使用するのです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Pages app" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "前の章では、urls.pyファイルにビューロジックを含めることによってホームページを表示しました。 \n", "このアプローチはうまくいくものの、いくらか私にとってハックしているように感じています。 \n", "Django初心者にとってはやや混乱するかもしれません。 \n", "代わりに、すべての静的ページ用の専用ページアプリを作成する必要があります。 \n", "これにより、私たちのコードは素早く整理された状態に保たれます。 \n", "コマンドラインでstartappコマンドを使用して、新しいページアプリを作成します。 \n", "サーバーがまだ稼動している場合は、Ctrlキーを最初に押して終了する必要があります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-- cmd --" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "その後、直ちにsettings.pyファイルを更新してください。 \n", "私はこれをすることを忘れることが多いので、新しいアプリケーションを2段階のプロセスとして作成することをお勧めします。 \n", "まず、startappコマンドを実行してからINSTALLED_APPSを更新します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--code --" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "これで、プロジェクトレベルのurls.pyファイルを更新できます。 TemplateViewのインポートを削除してください。 また、ページアプリを含めるためのルートを更新します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-- code -- \n", "今度はDjangoの標準的なURL / views / templatesのダンスを意味するホームページを追加します。 pages / urls.pyファイルから始めます。 最初に作成します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--cmd--" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次に、まだ作成されていないビューをインポートし、ルートパスを設定して、各URLにも名前を付けるようにします。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--code--" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この時点で、views.pyコードはよく知られています。 \n", "私たちはDjangoのTemplateViewジェネリッククラスベースのビューを使用しています。 \n", "これは、template_nameを指定する必要があることを意味します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---code --" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この時点で、views.pyコードはよく知られています。 \n", "私たちはDjangoのTemplateViewジェネリッククラスベースのビューを使用しています。 \n", "これは、template_nameを指定する必要があることを意味します。 \n", "この時点で、views.pyコードはよく知られています。 \n", "私たちはDjangoのTemplateViewジェネリッククラスベースのビューを使用しています。 \n", "これは、template_nameを指定する必要があることを意味します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--code--" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "既存のhome.htmlテンプレートが既にあります。 \n", "新しいURLとビューで期待どおりに動作することを確認しましょう。 \n", "ローカルサーバーのpython manage.py runserverを起動し、http:// 127.0.0.1:8000 /にあるホームページに移動して、変更されていないことを確認します。 \n", "最後の章の最後で使用したログインしたスーパーユーザーアカウントの名前が表示されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Test" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "新しいコードと機能が追加されました。 \n", "つまり、テストの時間です。 \n", "あなたのプロジェクトでは、決して十分なテストを受けることはできません。 \n", "彼らは書き始める前に時間をかけていますが、プロジェクトの複雑さが増すにつれて、時間を節約し、自信を与えてくれます。 \n", "テストを追加するには2つの理想的な時間があります。 \n", "コードを書く前(テスト駆動開発)または新しい機能を追加した直後のどちらかに、あなたの心の中ではっきりとしています。 \n", "現在、私たちのプロジェクトは4ページあります:\n", " \n", "home \n", "サインアップ \n", "ログイン \n", "ログアウト \n", " \n", "しかし、最初の2つだけをテストする必要があります。 \n", "ログインとログアウトはDjangoの一部であり、内部ビューとURLルートに依存しています。 \n", "したがって、彼らはすでにテストカバレッジを持っています。将来的に大幅な変更を加えた場合は、そのテストを追加したいと考えています。 \n", "しかし、一般的なルールとして、Djangoの中核機能のテストを追加する必要はありません。 \n", "2つの新しいページごとにURL、テンプレート、ビューがあるので、それぞれのテストを追加します。 \n", "DjangoのSimpleTestCaseはホームページのテストには十分ですが、サインアップページではデータベースを使用するため、TestCaseも使用する必要があります。 \n", "コードはあなたのpages / tests.pyファイルのようになります。  " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-- code --" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一番上の行では、カスタムユーザモデルを参照するためにget_user_model()を使用します。 \n", "次に、両方のページについて、3つのことをテストします:ページが存在し、HTTP 200のステータスコードを返します。 \n", "適切なテンプレートが使用されているビューで正しいURL名が使用されますサインアップページにもフォームがあります。 test_signup_formテストでは、ユーザー名と電子メールアドレスがPOSTされたとき(データベースに送信されるとき)、CustomUserモデルに格納されているものと一致することを確認しています。 \n", "Control + cを使用してローカルサーバーを終了し、テストがすべて実行されたことを確認します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Bootstrap" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "あなたが本当の扱いをする前にブートストラップを使ったことがないなら。 小さなコードで多くのことを達成します。 \n", "ブートストラップをプロジェクトに追加するには、2つの方法があります。 \n", "すべてのファイルをダウンロードしてローカルに配信するか、コンテンツ配信ネットワーク(CDN)に依存させることができます。 \n", "第2のアプローチは、一貫したインターネット接続があれば実装するのが簡単です。 \n", "ここではこれを使用します。 \n", "ブートストラップには、必要な基本ファイルを含むスターターテンプレートが付属しています。 \n", "特に私たちが組み込んでいるのは4つです:\n", "\n", "Bootstrap.css \n", "jQuery.js \n", "Popper.js \n", "Bootstrap.js \n", "\n", "更新されたbase.htmlファイルは次のようになります。 \n", "一般的に、すべてのコード例を自分で入力する必要がありますが、これはかなり長いので、ここでコピーして貼り付けても構いません。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-- code --" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "python manage.py runserverでサーバーを再起動し、http:// 127.0.0.1:8000でホームページをリフレッシュすると、現時点でフォントサイズのみが変更されていることがわかります。\n", "\n", "ページ上部に、ホームページへのリンク、ログイン、ログアウト、サインアップを含むナビゲーションバーを追加してみましょう。 \n", "特に、Djangoテンプレートエンジンのif / elseタグを使用して、基本的なロジックを追加することができます。 \n", "ログアウトしたユーザーには「ログイン」ボタンと「サインアップ」ボタンを表示したいが、ログインしたユーザーには「ログアウト」ボタンと「パスワード変更」ボタンを表示したい。\n", "\n", "コードは次のようになります。 この本の焦点はHTML、CSS、BootstrapではなくDjangoを学んでいるからです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-- code --" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "http:// 127.0.0.1:8000 /でホームページをリフレッシュすると、新しいnavが魔法のように登場しました! \n", "また、{%block content%}タグを追加して、タイトルに \"Newspaper App\"と同様にユーザーの挨拶が返されました。 \n", "私のケースでは、右上隅のwsvのユーザ名をクリックして、Bootstrapが提供する素敵なドロップダウンメニューを見てください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "「ログアウト」リンクをクリックすると、ナビゲーションバーのリンクが「ログイン」または「サインアップ」に変わります。 \n", "\n", "\"ブートストラップナビのホームページがログアウトしているブラウザウィンドウのサイズを縮小した方が良いでしょう。ブートストラップは自動的にサイズを変更して調整して、モバイルデバイス上でも見栄えがよくなります。 \n", " \n", "Webブラウザの幅を変更して、画面サイズが増減するにつれてどのようにサイドマージンが変化するかを確認することもできます。 \n", " \n", "「ログアウト」ボタンをクリックしてからトップのナビゲーションから「ログイン」をクリックすると、ログインページhttp:// 127.0.0.1:8000 / users / loginも良く見えます。 \n", " \n", "外に出ているのは、「ログイン」ボタンだけです。 ブートストラップを使用して、緑色にしたり招待したりするなど、スタイリングを追加することができます。 ボタンの行を変更する " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ページを更新して、新しいボタンを表示します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Sign Up Form" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "http:// 127.0.0.1:8000/ users/ signup/のサインアップページには、ブートストラップのスタイリングだけでなく、ヘルパーテキストの混乱もあります。たとえば、 \"Username\"の後に \"Required\"と表示されます。 150文字以下文字、数字、@ / / / - / _のみです。 \"\n", "\n", "そのテキストはどこから来たのでしょうか? Djangoで \"魔法\"のような何かが感じられるときはいつでも、それは決してないと確信しています。おそらくコードはDjangoの内部から来たものでしょう。\n", "\n", "Djangoで何が起こっているのかを知るための最も速い方法は、単にGithubのDjangoソースコードに行き、検索バーを使って特定のテキストを見つけようとすることです。\n", "\n", "たとえば、「150文字以下」を検索すると、301行目のdjango / contrib / auth / models.pyページに表示されます。このテキストは、authアプリケーションの一部として、 AbstractUserのusernameフィールド。\n", "\n", "我々は今、3つの選択肢があります:\n", "\n", "既存のhelp_textを上書きする\n", "help_textを非表示にする\n", "help_textのスタイルを変更する\n", "\n", "3番目のオプションは、優れたサードパーティ製のdjango-crispy-formsを導入するのに適しているので、これを選択します。\n", "\n", "フォームを使って作業することは難しいことであり、django-crispy-formsはDRYコードを書くのを容易にします。\n", "\n", "まず、Controlを使用してローカルサーバーを停止します。次に、Pipenvを使用してプロジェクトにパッケージをインストールします。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--cmd--" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "新しいappをsettings.pyファイルのINSTALLED_APPSリストに追加してください。 \n", "アプリの数が増え始めると、サードパーティアプリと私が自分で追加したローカルアプリを区別すると便利です。 \n", "ここに、コードがどのようになっているかがあります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--code--" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Bootstrap4を使用しているので、設定ファイルをsettings.pyファイルに追加する必要があります。 これはファイルの一番下に表示されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--code --" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "今、signup.htmlテンプレートでは、すっきりしたフォームをすばやく使用できます。 まず、crispy_forms_tagsを一番上にロードし、{{form.as_p}}を{{form | サクサク}}。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--code--" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "python manage.py runserverでサーバーを再起動してサインアップページをリフレッシュすると、新しい変更が表示されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ずっといい。 しかし、「サインアップ」ボタンがもう少し魅力的だったのはどうですか? 多分それを緑にする? ブートストラップには、あらゆる種類のボタンスタイリングオプションが用意されています。 緑色の背景と白いテキストを持つ「成功」を使いましょう。\n", "サインアップボタンの行にあるsignup.htmlファイルを更新します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--code--" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ページを更新すると、更新された作業が表示されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Next Steps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "私たちの新聞アプリはかなり良く見え始めています。 ユーザー認証フローの最後のステップは、パスワードの変更とリセットを構成することです。 ここでもまたDjangoは私たちのために重い持ち上げをしてくれましたので、最小限の量のコードを必要としています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.0" } }, "nbformat": 4, "nbformat_minor": 2 }