CORS (cross origin resource sharing)
- オリジン間リソース共有Cross-Origin Resource Sharing (CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組み
- ウェブアプリケーションは、自分とは異なるオリジン (ドメイン、プロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行
- https://domain-a.com で提供されているウェブアプリケーションのフロントエンド JavaScript コードが XMLHttpRequest を使用して https://domain-b.com/data.json へリクエストを行う場合。セキュリティ上の理由から、ブラウザーは、スクリプトによって開始されるオリジン間 HTTP リクエストを制限
- XMLHttpRequestや Fetch API は同一オリジンポリシーsame-origin policyに従う
- XMLHttpRequestや Fetch API 使用するウェブアプリケーションは、そのアプリケーションが読み込まれたのと同じオリジンに対してのみリソースのリクエストを行うことができ、それ以外のオリジンの場合は正しい CORS ヘッダーを含んでいることが必要
- オリジン間リソース共有の仕様は、ウェブブラウザーから情報を読み取ることを許可されているオリジンをサーバーが記述することができる、新たな HTTP ヘッダーを追加することで作用します。
- サーバーの情報に副作用を引き起こすことがある HTTP のリクエストメソッド (特に GET 以外の HTTP メソッドや、特定の MIME タイプを伴う POST) のために、ブラウザーが HTTP の OPTIONS リクエストメソッドを用いて、あらかじめリクエストの「プリフライト」 (サーバーから対応するメソッドの一覧を収集すること) を行い、サーバーの「認可」のもとに実際のリクエストを送信することを指示
- CORS は様々なエラーで失敗することがありますが、セキュリティ上の理由から、エラーについて JavaScript から知ることができないよう定められている
- 何が悪かったのかを具体的に知ることができる唯一の方法は、ブラウザーのコンソールで詳細を見ること
- request type
- Simple requests
- Preflighted requests
- Requests with credentials
単純リクエスト
- 「単純リクエスト」は、以下のすべての条件を満たすものです。
- 許可されているメソッドのうちの一つであること。
- GET
- HEAD
- POST
- ユーザーエージェントによって自動的に設定されたヘッダー (たとえば Connection、 User-Agent、 または Fetch 仕様書で「禁止ヘッダー名」として定義されているヘッダー) を除いて、手動で設定できるヘッダーは、 Fetch 仕様書で「CORS セーフリストリクエストヘッダー」として定義されている以下のヘッダーだけ
- Accept
- Accept-Language
- Content-Language
- Content-Type (但し、下記の要件を満たすもの)
- DPR
- Downlink (en-US)
- Save-Data
- Viewport-Width
- Width
- Content-Type ヘッダーでは以下の値のみが許可されています。
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- リクエストに使用されるどの XMLHttpRequestUpload にもイベントリスナーが登録されていないこと。これらは正しく XMLHttpRequest.upload を使用してアクセスされます。
- リクエストに ReadableStream オブジェクトが使用されていないこと。
- 許可されているメソッドのうちの一つであること。
- 注: これらはウェブコンテンツが発行可能になっているサイト間リクエストと同じ種類のものであり、サーバーが適切なヘッダーを送信しなければレスポンスデータは送信元へ送られません。従ってクロスサイトリクエストフォージェリ対策をしているサイトは、 HTTP アクセス制限について新たに心配することはありません。
- 注: WebKit Nightly および Safari Technology Preview は、 Accept, Accept-Language, Content-Language ヘッダーの値に追加の制限を掛けています。これらのヘッダーが「標準外」の値の場合、 WebKit/Safari はそのリクエストが「単純リクエスト」の条件に合うとは判断しません。 WebKit/Safari がこれらのヘッダーのどの値を「標準外」と判断するかについては、以下の WebKit のバグを除いて文書化されていません。Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language / Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS / Switch to a blacklist model for restricted Accept headers in simple CORS requests / これは仕様の一部ではないので、他のブラウザーはこの追加の制限を実装していません。
- https://foo.example にあるウェブコンテンツがドメイン https://bar.other にあるコンテンツを呼び出したいと仮定
// src const xhr = new XMLHttpRequest(); const url = 'https://bar.other/resources/public-data/'; xhr.open('GET', url); xhr.onreadystatechange = someHandler; xhr.send();
bar.otherへの リクエスト GET /resources/public-data/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive Origin: https://foo.example
特筆すべきリクエストヘッダーは Origin であり、呼び出しが https://foo.example から来たことを表す
bar.otherからのレスポンス HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2 Access-Control-Allow-Origin: * Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml
レスポンスでは、サーバーが Access-Control-Allow-Origin ヘッダーを返信
この場合、サーバーは Access-Control-Allow-Origin: * を返しており、これはそのリソースがすべてのドメインからアクセスできることを意味
https://bar.other にあるリソースの所有者が、リソースへの制限を https://foo.example からのリクエストのみに制限したい場合
Access-Control-Allow-Origin: https://foo.example
Origin ヘッダーと Access-Control-Allow-Origin ヘッダーの使用は、最も単純なアクセス制御プロトコルを表す
プリフライトリクエスト
- 始めに OPTIONS メソッドによる HTTP リクエストを他のドメインにあるリソースに向けて送り、実際のリクエストを送信しても安全かどうかを確かめる
- サイト間リクエストがユーザーデータに影響を与える可能性があるような場合に、このようにプリフライトを行う
// exsample const xhr = new XMLHttpRequest(); xhr.open('POST', 'https://bar.other/resources/post-here/'); xhr.setRequestHeader('X-PINGOTHER', 'pingpong'); xhr.setRequestHeader('Content-Type', 'application/xml'); xhr.onreadystatechange = handler; xhr.send('<person><name>Arun</name></person>');
POST で送信する XML の本体を作成
標準外の X-PINGOTHER HTTP リクエストヘッダーを設定
このようなヘッダーは HTTP/1.1 プロトコルに含まれていませんが、ウェブアプリケーションでは一般的に便利
Content-Type に application/xml を使用し、かつカスタムヘッダーを設定しているため、このリクエストではプリフライトを行う
注: 後述するように、実際の POST リクエストには Access-Control-Request-* ヘッダーが含まれず、 OPTIONS リクエストのみで必要になります。
// プリフライトリクエスト OPTIONS /doc HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive Origin: http://foo.example Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type // プリフライトレスポンス HTTP/1.1 204 No Content Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2 Access-Control-Allow-Origin: https://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400 Vary: Accept-Encoding, Origin Keep-Alive: timeout=2, max=100 Connection: Keep-Alive
・リクエスト解説
ブラウザーは上記で使用された JavaScript コードで使用しているリクエストの引数に基づいて、プリフライトの送信が必要であることを判断
これによりサーバーは実際のリクエストの引数によって、送られるリクエストが受け入れ可能かをレスポンスできる
OPTIONS はサーバーから付加的な情報を得るために用いる HTTP/1.1 のメソッドであり、また安全なメソッド、つまりリソースを変更するためには使用できないメソッド
Access-Control-Request-Method ヘッダーは、プリフライトリクエストの一部として、実際のリクエストが POST リクエストメソッドで送られることをサーバーに通知
Request-Headers ヘッダーは、実際のリクエストにカスタムヘッダーである X-PINGOTHER および Content-Type が含まれることをサーバーに通知
ここでサーバーは、この状況下でリクエストの受け入れるかを判断する機会がある
・レスポンス解説
Access-Control-Allow-Methods は当該リソースへの問い合わせに POST および GET が実行可能であることを伝える
Access-Control-Allow-Methods ヘッダーはレスポンスヘッダーの Allow と似ていますが、アクセス制御でのみ使用
サーバーは、 Access-Control-Allow-Headers を X-PINGOTHER の値で送信し、これが実際のリクエストで使用されるヘッダーであることを承認
Access-Control-Allow-Headers は受け入れ可能なヘッダーをカンマ区切りのリストで表す
Access-Control-Max-Age は、プリフライトリクエストを再び送らなくてもいいように、プリフライトのレスポンスをキャッシュしてよい時間を秒数で与える
この例では86400秒、つまり24時間
ブラウザーは個々に内部の上限値を持っており、 Access-Control-Max-Age が上回った場合に制限を掛ける
// 本命のリクエスト POST /doc HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive X-PINGOTHER: pingpong Content-Type: text/xml; charset=UTF-8 Referer: https://foo.example/examples/preflightInvocation.html Content-Length: 55 Origin: https://foo.example Pragma: no-cache Cache-Control: no-cache <person><name>Arun</name></person> // 本命のレスポンス HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT Server: Apache/2 Access-Control-Allow-Origin: https://foo.example Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain [Some XML payload]
プリフライトリクエストとリダイレクト
"The request was redirected to 'https://example.com/foo', which is disallowed for cross-origin requests that require preflight"
"Request requires preflight, which is disallowed to follow cross-origin redirect"
- もともと CORS プロトコルはそのような振る舞いを要求してたが、その後で必要なしに変更されたが、多くのブラウザーはまだ変更を実装しておらず、もともと要求されていた振る舞いに従っている
- ブラウザーが仕様に追いつくまで、以下の一方もしくは両方を行うことでこの制限を回避できる
- これらの変更ができない場合は、次のような別な方法があります。
- 単純リクエストを行い (Fetch API の Response.url (en-US) または XMLHttpRequest.responseURL を使用して)、実際のプリフライトリクエストが転送される先を特定する。
- 最初のステップの Response.url または XMLHttpRequest.responseURL で得た URL を使用して、もう一つのリクエスト (「本当の」リクエスト) を行う。
- リクエストに Authorization ヘッダーが存在するためにプリフライトを引き起こすリクエストの場合、上記の手順を使用して制限を回避できない
資格情報を含むリクエスト
- XMLHttpRequest や Fetch と CORS の両方が、 HTTP クッキーと HTTP 資格情報によってわかる「資格情報を含む」リクエストを作成することができる
- 既定では、サイト間の XMLHttpRequest または Fetch の呼び出しにおいて、ブラウザーは資格情報を送信しない
- XMLHttpRequest オブジェクトまたは Request のコンストラクターの呼び出し時に、特定のフラグの設定が必要
- http://foo.example から読み込まれた元のコンテンツが、 http://bar.other にあるリソースに対してクッキーを設定したシンプルな GET リクエスト
const invocation = new XMLHttpRequest(); const url = 'http://bar.other/resources/credentialed-content/'; function callOtherDomain() { if (invocation) { invocation.open('GET', url, true); invocation.withCredentials = true; invocation.onreadystatechange = handler; invocation.send(); } }
XMLHttpRequest に設定する必要があるフラグ、 withCredentials という真偽値型の値を設定
既定では、クッキーなしで呼び出す
単純な GET リクエストなのでプリフライトは行いませんが、ブラウザーは Access-Control-Allow-Credentials: true ヘッダーを持たないレスポンスを拒否し、ウェブコンテンツを呼び出すレスポンスを作成しない
// request GET /resources/credentialed-content/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive Referer: http://foo.example/examples/credential.html Origin: http://foo.example Cookie: pageAccess=2 // response HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:34:52 GMT Server: Apache/2 Access-Control-Allow-Origin: https://foo.example Access-Control-Allow-Credentials: true Cache-Control: no-cache Pragma: no-cache Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 106 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain [text/plain payload]
http://bar.other 向けのクッキーが含まれていますが、bar.other が Access-Control-Allow-Credentials: true (17行目) をレスポンスに含めなければ、レスポンスは無視されウェブコンテンツで使用できない
資格情報付きリクエストとワイルドカード
- 格情報を含むリクエストに対するレスポンスの時、サーバーは Access-Control-Allow-Origin ヘッダーで "*" ワイルドカードではなくオリジンを指定しなければならない
- 上記のリクエストヘッダーは Cookie ヘッダーを含んでいるため、 Access-Control-Allow-Origin ヘッダーが "*" であったらリクエストは失敗
- Access-Control-Allow-Origin ヘッダーの値が "*" ワイルドカードではなく "http://foo.example" (実際のオリジン) なので、ウェブコンテンツの呼び出しに対して資格情報を意識したコンテンツが返る
- 上記の中にある Set-Cookie レスポンスヘッダーは、将来のクッキーの設定も行ないます。失敗した場合、 (使われている API によりますが) 例外が発生
- CORS のレスポンスに設定されたクッキーは、サードパーティーのクッキーに関する通常のポリシーに従う
- 上記では、ページは foo.example から読み込まれてるが、クッキーは bar.other から送られているので、ユーザーがブラウザーでサードパーティーのクッキーをすべて拒否するよう設定していた場合は保存されない
HTTP レスポンスヘッダー
- Access-Control-Allow-Origin
- Access-Control-Allow-Origin は、リソースへのアクセスを許可するオリジンをブラウザーに伝えるための単一のオリジンを指定することができます。
- 資格情報を含まないリクエストのみ、どのオリジンにもリソースへのアクセスを許可することをブラウザーに伝えるワイルドカード "*" を指定することができます。
- サーバーがワイルドカード "*" ではなく (ホワイトリストの一部としてリクエストするオリジンに基づいて動的に変更される可能性がある) 単一のオリジンを指定した場合は、サーバーは Vary レスポンスヘッダーに Origin も含めて、サーバーのレスポンスが Origin リクエストヘッダーの値によって変化することをクライアントに知らせる必要がある
Access-Control-Allow-Origin: https://mozilla.org
Vary: Origin
- Access-Control-Allow-Credentials
django思い出しメモ
- Django
- 環境立ち上げ
- プロジェクト作成
- アプリ作成
- サーバの起動
- リクエストハンドラーの作成
- path関数の説明
- データベースバインディング·コンフィグレーション
- 基本DBの作成
- モデルの作成
- アプリ用DBの作成
- 可読性をあげる1(strを使えるようにする)
- urlパターン マッチングをする
- templateの使用
- 404エラーハンドリング
- テンプレートシステムの基本
- urlのハードコーディングを避ける。
- csrf_tokenの使用
- POSTデータの取り出し
- リダイレクト
- urlの作成
- 汎用ビュー(リストビュー)の使用
- 汎用ビュー(デテールビュー)の使用
- testを書く
- ビューのテストを書く
- 静的要素の使用
- Django Adminの使用
Django
環境立ち上げ
python3 -m venv env source env/bin/activate
プロジェクト作成
django-admin startproject プロジェクト名
アプリ作成
python manage.py startapp アプリ名
サーバの起動
python manage.py runserver
リクエストハンドラーの作成
from django import HttpResponse def index(request): return HttpResponse("Hello")
- ビューをurlと紐付ける
1. app/urls.pyを作成する
2.app/urls.pyに追加する
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]
3.project/urls.pyに追加する
from django.contrib import admin from django.urls import include, path urlpatterns = [ path('polls/', include('polls.urls')), path('admin/', admin.site.urls), ]
path関数の説明
1.path() 引数: route----------------------------------------------------
route は URL パターンを含む文字列です。リクエストを処理するとき、Django は urlpatterns のはじめのパターンから開始し、リストを順に下に見ていきます。要求された URL を一致するものを見つけるまで各パターンと比較します。
パターンはGETやPOSTのパラメーター、そしてドメイン名を検索しません。例えば、 https://www.example.com/myapp/ へのリクエストにおいては、URLconfは myapp/ を見ます。 https://www.example.com/myapp/?page=3 へのリクエストにおいても、URLconfは myapp/ を見ます。
2.path() 引数: view----------------------------------------------------
Django がマッチする正規表現を見つけると、 Django は指定されたビュー関数を呼び出します。その際は HttpRequest オブジェクトを第一引数に、そしてキーワード引数としてrouteから「キャプチャされた」値を呼び出します。この例はこの後すぐ出てきます。
3.path() 引数: kwargs----------------------------------------------------
任意のキーワード引数を辞書として対象のビューに渡せます。この機能はチュートリアルでは使いません。
4path() 引数: name----------------------------------------------------
URL に名前付けをしておけば Django のどこからでも明確に参照でき、とくにテンプレートの中で有効です。この便利な機能のおかげで、プロジェクトのURLにグローバルな変更を加える場合にも1つのファイルを変更するだけで済むようになります。
データベースバインディング·コンフィグレーション
1. 関連リンクDjango のインストール方法 | Django ドキュメント | Django
2. DATABASES の 'default' 項目内の以下のキーをデータベースの接続設定に合うように変更してください。
ENGINE -- 'django.db.backends.sqlite3'、 'django.db.backends.postgresql'、 'django.db.backends.mysql' または 'django.db.backends.oracle' のいずれかにします。その他のバックエンド も利用可能です。
NAME -- データベースの:setting:NAME です。SQLiteを使用している場合、データベースはコンピュータ上のファイルになります。デフォルト値の BASE_DIR / 'db.sqlite3' は、プロジェクトディレクトリにファイルを保存します。
USER や PASSWORD そして HOST などの追加設定を加える必要があります
3.sqlite以外の場合
もし SQLite 以外を使っている場合、 database を今のうちに作っておいてください。 "CREATE DATABASE database_name;" とデータベースのインタラクティブプロンプトで実行してください。
mysite/settings.py のデータベースユーザに 「データベース作成」の権限があるならばDB を自動作成することができます。
詳細リンク設定 | Django ドキュメント | Django
4.project/settings.py を編集する際、 TIME_ZONE に自分のタイムゾーンも設定します。
モデルの作成
from django.db import models class MyModel(models.Model): data1 = models.CharField(max_length=100)
アプリ用DBの作成
1.Djangoインスタンス(project/settings.py)にアプリを登録する
INSTALLED_APPS = [
~~~~
'polls.apps.PollsConfig',
]
2. マイグレーションの作成
python manage.py makemigrations アプリ名
3.マイグレイトの実行
python manage.py migrate
可読性をあげる1(strを使えるようにする)
モデルに__str__メソッドを追加する。
def __str__(self): return self.member
urlパターン マッチングをする
path('<int:some_integer>/detail/', views.my_view, "description")
templateの使用
1.app/templates/app/を作成
2.上記ディレクトリ にhtmlファイルを作成
3.viewで使用する
loaderを使用する場合
from django.http import HttpResponse from django.template import loader from .models import Question def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] template = loader.get_template('polls/index.html') context = { 'latest_question_list': latest_question_list, } return HttpResponse(template.render(context, request))
renderを使用する場合
from django.shortcuts import render from .models import Question def index(request): latest_question_list = Question.objects.order_by('-pub_date')[:5] context = {'latest_question_list': latest_question_list} return render(request, 'polls/index.html', context)
404エラーハンドリング
ショートカットなし
from django.http import Http404 from django.shortcuts import render from .models import Question # ... def detail(request, question_id): try: question = Question.objects.get(pk=question_id) except Question.DoesNotExist: raise Http404("Question does not exist") return render(request, 'polls/detail.html', {'question': question})
ショートカット有り
from django.shortcuts import get_object_or_404, render from .models import Question # ... def detail(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/detail.html', {'question': question})
テンプレートシステムの基本
1.for文
{% for a in b %} ~~~ {% endfor %}
2.if文
{% if contidtion %} ~~~ {% else %} ~~~ {% endif %}
3.式
{{ a.attribute }}
urlのハードコーディングを避ける。
基本イディオム
{% url 'urls.pyのnameに対応する文字列' %}
もし他のアプリケーションでも同じnameのビューがあった場合の対処法
app/urls.pyでapp_nameの定義をし、url関数の引数を変更する。
app_name = 'myapp'
{% url 'myapp:detail' %}
csrf_tokenの使用
<form action="~~~" method="post"> {% csrf_token %} <input ~~~> <input type="submit" > </form>
POSTデータの取り出し
request.POST['key']
リダイレクト
HttpResponseRedirectを使用する引数にはurlを渡す。
urlの作成
reverse関数を使用する
reverse('app:name', args=(パラメータ))
汎用ビュー(リストビュー)の使用
class ItemsView(generic.ListView): template_name = 'app/items.html' context_object_name = 'latest_item_list' def get_queryset(self): return MyModel.objects.order_by('-pub_date')[:5]
get_querysetをオーバーライドすることでビューに渡すデータを変更できる
template_nameで使うテンプレートを指定できる
汎用ビュー(デテールビュー)の使用
詳細ページを作成するときに使う
class ItemView(generic.DetailView): model = MyModel template_name = "app/item.html"
決まり
templateではmodel名を小文字にした物が変数として使われる。
詳細ビューのデータ取得にはurlのpkを使っているので
urls.pyの文字列で
template_nameで使うテンプレートを指定できる
testを書く
書く場所はapp/tests.py
#基本形 import datetime from django.test import TestCase from django.utils import timezone from .models import Question class QuestionModelTests(TestCase): def test_was_published_recently_with_future_question(self): """ was_published_recently() returns False for questions whose pub_date is in the future. """ time = timezone.now() + datetime.timedelta(days=30) future_question = Question(pub_date=time) self.assertIs(future_question.was_published_recently(), False)
1.TestCaseを継承したクラスを作成する。
2.
python manage.py test app
を実行することでtest_で始まるメソッドが端から実行される
ビューのテストを書く
# 基本形 class QuestionIndexViewTests(TestCase): def test_no_questions(self): """ If no questions exist, an appropriate message is displayed. """ response = self.client.get(reverse('polls:index')) self.assertEqual(response.status_code, 200) self.assertContains(response, "No polls are available.") self.assertQuerysetEqual(response.context['latest_question_list'], [])
静的要素の使用
1.app/static/app/を作成
2.上記ディレクトリ ないに静的ファイルを設置
3.テンプレートで読みこむ
{% load static %} <link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">
Django Adminの使用
管理ユーザの作成
python manage.py createsuperuser
admin機能の使用
1./admin/にアクセスします
2.ログインします
アプリをadminに登録する。
app/admin.pyに下記のコードを追加する
from .models import Question admin.site.register(Question)
フォームの変更
モデルの admin のオプションを変更したいときには、モデルごとに admin クラスを作成して、 admin.site.register() の 2 番目の引数に渡すと いうパターンに従ってください。
ex. app/admin.py
from django.contrib import admin from .models import Question class QuestionAdmin(admin.ModelAdmin): fields = ['pub_date', 'question_text'] admin.site.register(Question, QuestionAdmin)
この例ではフォームの並び順を変更しています。
リレーションオブジェクトの追加
class ChoiceInline(admin.StackedInline): model = Choice extra = 3 class QuestionAdmin(admin.ModelAdmin): ~~~ inlines = [ChoiceInline]
オブジェクト一覧ページの変更
class QuestionAdmin(admin.ModelAdmin): # ... list_display = ('question_text', 'pub_date', 'was_published_recently')
フィルタリング 検索
class Question(models.Model): # ... def was_published_recently(self): now = timezone.now() return now - datetime.timedelta(days=1) <= self.pub_date <= now was_published_recently.admin_order_field = 'pub_date' was_published_recently.boolean = True was_published_recently.short_description = 'Published recently?'
list_filter = ['pub_date']
search_fields = ['question_text']
adminテンプレートのカスタム
1.設定ファイル (mysite/settings.py) を開いて、TEMPLATES 設定オプションの中に、次のように DIRS オプションを追加します。
{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], # ここ 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
2.manage.pyと同じ階層にtemplates/admin/を作成しましょう
3.django/contrib/admin/templates/admin/base_site.htmlを2のディレクトリ にコピーします。
4.お好きなように編集してください。
django.contrib.admin.AdminSiteを変更すれば一部の値は簡単に変更できる。
day 48 調べたこと。
考察
引数にする。
レシーバにする。
関数にする。
・taro.greet();
・greet(taro);
・greet_taro();
どれがいいのか。
基本
引数は少ない方がいい。
レシーバも同様。
とすると基本的には3番目がいいということになる?
3番目は表面的依存もないし、抽象度も高いし3番目をラッパーとして1を使ったりするのがいい?
単語
一手(チェス、将棋) | a move |
day 47 @go 配列を含むスライス
[][]Type
と型宣言する。