Django メモ¶
Model.objectsなどを参照の際のvscodeのエラー対策¶
djangoが動的に作成したプロパティを参照すると、vscodeがエラーをはいて鬱陶しい。 django用のpylintを用いるようにする
pip install pylint-django
vscodeの設定
"python.linting.pylintArgs": [
"--load-plugins=pylint_django"
],
参考 https://stackoverflow.com/questions/45135263/class-has-no-objects-member
Fieldクラスの第一引数¶
フィールドクラスの第一引数には、そのフィールドの人間用の名前をつけることができる。 管理サイトでの表示に使われたりするそうだ
参考 https://docs.djangoproject.com/ja/2.0/topics/db/models/#verbose-field-names
複数のDBを扱いたい場合の例¶
参考 https://tokibito.hatenablog.com/entry/20160202/1454344534
複合ユニーク制約を付与したい¶
以下のようにする(models.py):
class Exsample(models.Model):
sample_1 = models.IntegerField()
sample_2 = models.IntegerField()
class Meta:
unique_together=(("sample_1","sample_2"))
画像のアップロード¶
マイグレーション¶
1.settings.pyを編集:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', #任意のアプリケーションを追加
)
2.models.pyを編集
3.makemigrationsにて、モデルの変更を通知:
$ ./manage.py makemigrations
Migrations for 'myapp':
0001_initial.py:
...
4.実行されるddlを確認(ここで0001はmakemigrationsにて出力された値を指定):
$ ./manage.py sqlmigrate myapp 0001
5.マイグレーションの実行:
./manage.py migrate
2回目以降のマイグレーションも2.から同じ処理を繰り返す。 また、4.のddlの確認、5.のマイグレーションの実行では1つのDBのみが対象(指定なしの場合はdefaultのDBが対象) になるため、以下のコマンドでマイグレーションするDBを指定する必要がある
./manage.py migrate --database=exsample
makemigrationsで変更が検知できない場合、アプリ名を明示してやると上手くいく
python manage.py makemigrations exsample_app
参考 https://remotestance.com/blog/2612/
参考 https://docs.djangoproject.com/en/2.0/topics/db/multi-db/#synchronizing-your-databases
FileFieldを持つモデルが削除されたら、対応するファイルを削除する¶
削除のタイミングで発生するシグナルを拾ってファイルを削除する
参考 https://stackoverflow.com/questions/16041232/django-delete-filefield
画像のサムネイルを作成したい¶
django-imagekitが使える。 例
from django.db import models
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill
class Profile(models.Model):
avatar = models.ImageField(upload_to='avatars')
avatar_thumbnail = ImageSpecField(source='avatar',
processors=[ResizeToFill(100, 50)],
format='JPEG',
options={'quality': 60})
このavatar_thumbnailのURLにリクエストを送ると、ImageKitが引数に対応した処理を行い、 サムネイルを返す(引数次第では別の画像処理も可能)。 また一度画像にリクエストを送ると、次以降はMEDIA_ROOT/CACHE下のファイルを参照して画像を返すようになる。
参考 https://github.com/matthewwithanm/django-imagekit
例のprocessorsに使えるものは以下のページを参照
http://pilkit.readthedocs.io/en/latest/#processors
自分でも簡単に定義できそう。
QuerySetにて発行されるSQLを確認したい¶
QuerySetのqueryを確認する。 shellを立ち上げて確認するのが手っ取り早い。 例:
python manage.py shell
>>> from polls.models import Question
>>> print(Question.objects.all().query)
DBの列に関数を適用した上でDistinctしたい¶
selectする列などは、django.db.models.functionsにて関数を適用できる。 関数を適用した列に別名をつけて、distinctしてやればよい。
from django.db.models.functions import ExtractYear, ExtractMonth
a = Picture.objects.values(year=ExtractYear("take_date"),
month=ExtractMonth("take_date")).distinct()
https://docs.djangoproject.com/en/2.0/ref/models/database-functions/
テンプレート内で文字をフォーマットしたい¶
stringformatフィルタを用いる。古い形式のPythonのフォーマットしかできないっぽい
参考 https://docs.djangoproject.com/ja/2.0/ref/templates/builtins/#stringformat
管理サイトで画像を表示したい¶
以下のサイトの二番目に回答がついている、ver1.9対象のものが役に立つ
また、画像のHTMLを返す関数はモデルではなく、admin.pyの方に以下のように定義してもよい:
class PictureAdmin(admin.ModelAdmin):
list_display = ('admin_put_picture',) #一覧に表示される項目
readonly_fields = ('admin_put_picture',)
def admin_put_picture(self, row):
return mark_safe('<img src="{}" style="width:100px;height:auto;">'.format(row.picture_thumbnail.url))
admin.site.register(models.Picture, PictureAdmin)
settings.pyのALLOWED_HOSTS¶
Hostヘッダインジェクションを防ぐために、HTTPのHostヘッダに許される値を指定する。 ドメインそのまま書けばおk。
バージョンによっては、デバッグフラグがTrueの時はALLOWED_HOSTSが無視されたりもしたらしいが、Django2.0ではデバッグフラグ関係ない?
参考 https://docs.djangoproject.com/ja/2.0/ref/settings/#allowed-hosts
EC2, Apache上での環境構築¶
前提¶
以下の環境にて作業を実施
- 2018/07に実施
- Amazon Linux 2 AMI - ami-e99f4896を使用
- Apache2.4はインストール済
- その他は何もインストールしていない
手順¶
python3のインストール¶
sudo yum install python3
python仮想環境の準備¶
$ pwd
/var/www/environments
$ sudo python3 -m venv myenv
$ sudo su
# source myenv/bin/activate
以下は仮想環境上で実行。 仮想環境上では、python3, pip3がデフォルトとなっており、python, pipコマンドで3系に対する操作が可能。
django, mod_wsgiのインストール¶
# pip install django
# pip install mod_wsgi
# yum install httpd-devel
# yum groupinstall "Development Tools"
python3-develが入っていないことが原因で、以下のエラーが発生。
src/server/wsgi_python.h:24:10: fatal error: Python.h: No such file or directory
#include <Python.h>
以下のコマンドでインストールする
# yum install python3-devel
参考 https://sekisuiseien.com/computer/10626/
その後再度mod_wsgiをインストールした。
Apacheの設定¶
/etc/httpd/conf.modules.d/mod_wsgi.confに、以下のwsgi_moduleをロードする設定を記述
LoadModule wsgi_module /var/www/environments/myenv/lib/python3.7/site-packages/mod_wsgi/server/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so
/etc/httpd/conf.d/django.confに以下の設定を記述
WSGIPythonHome /var/www/environments/myenv
WSGIScriptAlias /app /var/www/environments/mysite/mysite/wsgi.py
WSGIPythonPath /var/www/environments/mysite:/var/www/environments/myenv/lib/python3.7/site-packages
<Directory /var/www/environments/mysite/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
apacheを起動し、ドメイン名/appにアクセスしてdjangoの起動を確認出来たら完了。
静的ファイル周りの設定¶
{% static "myapp/image.jpg" %}
といった感じでアクセスできる。sample_record.sample_file.url()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
ここらへん鑑みて、設定としては以下のようにしている。
settings.py
if DEBUG:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
else:
# Webサーバの設定にて、http://ドメイン/static にアクセスした際はSTATIC_ROOTを、
# http://ドメイン/media にアクセスした際はMEDIA_ROOTのファイルを参照するよう設定。
STATIC_ROOT = '/静的ファイルを配置したい絶対パス/'
MEDIA_ROOT = '/メディアファイルを配置したい絶対パス/'
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
urls.conf
urlpatterns = [
...
]
# 開発の場合のみ、djangoにてメディアファイルを配信するよう設定
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
mod_wsgiのWSGIScriptAlias¶
最後に/付けるのはまずいみたい。しばらくはまった。
ダメな例 WSGIScriptAlias /hoge/app/ /var/www/environments/mysite/mysite/wsgi.py
問題ない例 WSGIScriptAlias /hoge/app /var/www/environments/mysite/mysite/wsgi.py
これ WSGIScriptAlias / /var/www/environments/mysite/mysite/wsgi.py
が通るから
最後にスラッシュついてても問題ないかと勘違いしてしまった。