目次
Time zones
タイムゾーンサポート
-
settings.py
で設定するUSE_TZ = True
: タイムゾーンサポートが有効USE_TZ = False
: タイムゾーンサポートが無効 (default)
django-admin startproject
によって生成されるデフォルトのsettings.py
ファイル は、USE_TZ = True
タイムゾーンのサポートは
pytz
を使用する。Django をインストールしたときに一緒にインストールされている。
naive と aware
-
aware: タイムゾーンあり
Python の
datetime.datetime
のオブジェクトには、タイムゾーン情報を保持するために使える tzinfo 属性があり、これはdatetime.tzinfo
のサブクラスのインスタンスで表されます。この属性がセットされオフセットを示すとき、datetime オブジェクトは aware となります。それ以外の場合は naive となります。
naive: タイムゾーンなし
タイムゾーンサポートが有効なときの Django の日時の取り扱い方
- データベース
-
内部的に aware なタイムゾーンオブジェクトを使用して、 UTC で保持
- フォーム
-
入力された日時をカレントタイムゾーンで変換し、 cleaned_data 内で aware な datetime オブジェクトを返す
- テンプレート
-
レンダリングする際に aware な datetime オブジェクトをカレントタイムゾーンに変換する
現在日時の取得
-
タイムゾーンサポートが有効
# USE_TZ = True # TIME_ZONE = 'Asia/Tokyo' >>> from django.utils import timezone >>> import datetime >>> import pytz >>> timezone.now() datetime.datetime(2019, 10, 6, 9, 23, 19, 903697, tzinfo=<UTC>) >>> datetime.datetime.now() datetime.datetime(2019, 10, 6, 18, 23, 41, 152275) >>> timezone.make_aware(datetime.datetime.now()) datetime.datetime(2019, 10, 6, 18, 23, 56, 39144, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>) >>> timezone.localtime(timezone.now()) datetime.datetime(2019, 10, 6, 18, 24, 13, 36991, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>) >>> datetime.datetime.now(tz=pytz.timezone('Asia/Tokyo')) datetime.datetime(2019, 10, 6, 18, 24, 16, 258210, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
-
タイムゾーンサポートが無効
# USE_TZ = False >>> from django.utils import timezone >>> import datetime >>> import >>> timezone.now() datetime.datetime(2019, 10, 6, 18, 28, 34, 147660) >>> datetime.datetime.now() datetime.datetime(2019, 10, 6, 18, 28, 41, 569008) >>> timezone.make_aware(datetime.datetime.now()) datetime.datetime(2019, 10, 6, 18, 28, 54, 973598, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>) >>> timezone.localtime(timezone.now()) Traceback (most recent call last): File "<console>", line 1, in <module> File "/var/www/usonar/.tox/py37/lib/python3.7/site-packages/django/utils/timezone.py", line 207, in localtime raise ValueError("localtime() cannot be applied to a naive datetime") ValueError: localtime() cannot be applied to a naive datetime >>> datetime.datetime.now(tz=pytz.timezone('Asia/Tokyo')) datetime.datetime(2019, 10, 6, 18, 29, 5, 566142, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>)
デフォルトタイムゾーンとカレントタイムゾーン
デフォルトタイムゾーン:
settings.TIME_ZONE
に定義されたタイムゾーンカレントタイムゾーン: レンダリングに使われるタイムゾーン
naive な日時をデータベースに保存しようとすると、Django は警告を出す
RuntimeWarning: DateTimeField ModelName.field_name received a naive datetime (2012-01-01 00:00:00) while time zone support is active.
S3 アップロード
体感だけど、パターン1 のほうが速いような感じがした
# settings.py DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# upload.py from django.core.files.base import ContentFile from django.core.files.storage import default_storage # パターン1 file_path = default_storage.save(file_path, ContentFile(file_data)) # パターン2 with default_storage.open(file_path, 'w') as f: file_size = f.write(file_data)
マイグレーションを間違えたときのリカバリ方法
-
DjangoのDBシェルでローカルDBにつなぐ
$ python manage.py dbshell --settings=settings.local
-
django_migrations テーブルから該当アプリのレコードを削除する
SELECT * FROM django_migrations WHERE app like '%{application_name}%'; DELETE FROM django_migrations WHERE id={該当のID};
-
該当テーブルやカラムも DROP する
DROP TABLE {table_name}; ALTER TABLE {table_name} DROP COLUMN {column_name};
該当のマイグレーションファイルも削除しておく
-
もう一回最初からマイグレーションする
$ python manage.py makemigrations {application_name} --settings=settings.local $ python manage.py migrate {application_name} --settings=settings.local
こんなのある
MultiValueDict
なにがうれしいのかさっぱりわからない => MultiValueDict を継承してる QueryDict とか見るとユースケースはなんとなく想像つくと思います と教えて頂いた。
-
https://docs.djangoproject.com/ja/2.1/_modules/django/utils/datastructures/
A subclass of dictionary customized to handle multiple values for the same key.
-
よく見たら、こういうところが便利だと思った ↓
>>> from django.utils.datastructures import MultiValueDict >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) >>> d.update({'name': 'Momo'}) >>> d <MultiValueDict: {'position': ['Developer'], 'name': ['Adrian', 'Simon', 'Momo']}> >>> dd = {'name': ['Adrian', 'Simon'], 'position': ['Developer']} >>> dd.update({'name': 'Momo'}) >>> dd {'position': ['Developer'], 'name': 'Momo'}
QueryDict オブジェクト
In an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict だそうです。
In an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict, a dictionary-like class customized to deal with multiple values for the same key. This is necessary because some HTML form elements, notably <select multiple>, pass multiple values for the same key.
便利さん
django に便利コマンド追加してくれるさん django-extensions
-
django-allauth: 認証系機能の拡充
メールアドレスベースのログイン
ログインまわり
Google, Twitter, GitHub などのソーシャルアカウントを利用したサードパーティ認証機能
django-tables2: テーブル表示とページネーション
django-environ
django-debug-toolbar: GUI によるデバッグ