ご無沙汰しております。
少し前に引っ越しました。 今は引っ越しに関する話も落ち着いています。 報告ブログを書いておきます。
DRFでURLにパラメータを含んだRouterを作りたいと思った。
調べたところ、次の質問にたどり着いた。
まず、以下のような形で、正規表現を作る。
router.register(
r"project/(?P<project_id>\d+)/task",
ProjectTaskViewSet
)
そして、ViewSet側では、 lookup_url_kwarg
を指定して、それを元にQuerySetを絞り込む。
from rest_framework.mixins import ListModelMixin from rest_framework.viewsets import GenericViewSet class ProjectTaskViewSet(ListModelMixin, GenericViewSet): queryset = Task.objects.all() serializer_class = ProjectTaskSerializer lookup_url_kwarg = "project_id" def get_queryset(self): project_id = self.kwargs.get(self.lookup_url_kwarg) return self.queryset.filter(project=project_id)
docker-composeでMySQLコンテナと、MySQLのDBを利用するアプリケーションがある時、DBを利用するアプリは、MySQLコンテナの起動を待ちたい。
docker-composeの depends_on で以下のように指定したもアプリのコンテナが起動しはじめるの早すぎて、接続エラーが出ていた。
version: '3' services: web: ... 略 depends_on: - db db: image: mysql:5.7 ... 略
少し調べると、depends_onにはShort SyntaxとLong Syntaxがあるらしい。
参考 : Docker Compose の depends_on の使い方まとめ | gotohayato.com
なので、Long Syntaxを利用して以下のように書いてみる。
version: '3' services: web: ... 略 depends_on: db: condition: service_healthy db: image: mysql:5.7 ... 略
するとdocker-compose upしたタイミングで次のエラーが出た。
container for service "db" has no healthcheck configured
どうやらどうやってhealthcheckするかの設定は自分で書く必要があるらしい。
良い設定を探したところ、stackoverflowで以下のスレにたどり着いた。
mysqladmin pingを実行してヘルスチェックにする方法が紹介されていたので、以下のように記載した。
version: '3' services: web: ... 略 depends_on: db: condition: service_healthy db: image: mysql:5.7 ... 略 healthcheck: test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"] timeout: 20s retries: 10
これで、うまくMySQLの起動を待てるようになった。
ヘルスチェック時に、以下の警告が出るので、コマンドを微調整しておく。
Access denied for user ‘root’@’localhost’
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-u", "mysql", "-pmysql"]
昨日、django-filterを動かした記録を書きました。 次は、DRFで利用する前提で動かしてみた記録を書きます。
以下、記事から続く形で動かしていきます。
前回の記事にも書いたことと重複しますが、基本的にドキュメントに書いてあることを斜め読みしながら動かしつつ、気になった部分のドキュメントやソースを僕が読んで記録していく記事です。間違っている可能性はありますので、より確かな情報は各自ドキュメントやソースを読んでください。
そもそも、DRFには、FilterBackendという概念がある。
Filtering - Django REST framework
ドキュメントをざっと読みしたところ、次の経緯で作られたと考えると、自分にとってはわかりやすいと感じました。(あくまで私の解釈です)
get_queryset()
に実装するdjango-filterはDRFのFilterBackendに使える形式になっていますが、django-filter以外のもDRFで利用できるFilterがあるようです。
DRFドキュメントの末尾で以下のものが紹介されていました。
今回は、django-filterを動かしてみます。 今後、気が向いたら動かしてみたいと思います。
とりあえずdjango-filterを導入する前に、DRF側でAPIを作っておきます。
serializersに以下を追加します。
from rest_framework import serializers from myapp.models import Product class ProductSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Product fields = ["name", "price", "description", "release_date"]
viewsに以下を追加。
from rest_framework import viewsets from myapp.models import Product from myapp.serializers import ProductSerializer class ProductViewSet(viewsets.ModelViewSet): queryset = Product.objects.all() serializer_class = ProductSerializer
urls.pyに以下を追加。
from django.urls import path, include from rest_framework import routers from myapp.views import ProductViewSet router = routers.DefaultRouter() router.register(r"products", ProductViewSet) app_name = "myapp" urlpatterns = [ path("", include(router.urls)), ]
この状態でブラウザブルAPIを確認して表示されることを確認しておく。
ListAPIViewの絞り込み結果に、FilterSetを利用するためにはViewに以下の差分を追加します。これで、有効化されます。
@@ -1,5 +1,6 @@ from django.shortcuts import render from rest_framework import viewsets +from django_filters import rest_framework as filters from myapp.filters import ProductFilter from myapp.models import Product from myapp.serializers import ProductSerializer ... class ProductViewSet(viewsets.ModelViewSet): queryset = Product.objects.all() serializer_class = ProductSerializer + filter_backends = (filters.DjangoFilterBackend,) + filterset_class = ProductFilter
この状態で、ブラウザブルAPIを開くと、Filterボタンが追加されてました。
モーダルでパラメータを渡せるようになって動作確認ができました。
簡単ー!!
あとは、Djangoの時と同じくFilterクラスを修正すれば検索クエリを実装できそうです
なお、django-filterのFilterSetをDRFで利用するためには、Viewに filter_backends = (filters.DjangoFilterBackend,)
を指定する必要があるのですが、settingsで以下のように書いておくと、プロジェクト共通の設定として、済ませることができるとのことです。
REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ( 'django_filters.rest_framework.DjangoFilterBackend', ... ), }
DRFの仕組みを調査している際に、以下のようなことが気になりました。
というわけで、次の二点が知りたくて、実装を調査してみました。
すると、まず、FilterBackendでページネーションやSchema自動生成との兼ね合い、FilterSetクラスなどを処理してるというのはわかりました。
また、元々、django-rest-frameworkでDjangoFilterBackendと呼ばれる処理を持っていたが、途中で非推奨となり、django-filterのDjangoFilterBackendが推奨となったという、雑学が手に入りました。
とりあえずdjango-filterをDRFで動かした記録を書きました。
DRFのfilter拡張のライブラリはいくつかあるみたいなので、また気が向いたら動かしてみたいと思います。
あと、関連で以下のライブラリも見つけたので、こちらも気が向いたら動かしてみたいところ。
django-filterというものが視界に入ってきた。 使ったことがなかったので、とりあえず動かしてみることにしました。 これは動かしてみた記録。
続きを読むふと、次のような疑問が頭をよぎった。
Webサービスのサブスクリプションはよく聞くけど、リースとは言わない。
何となくビジネスの仕組みが違うような気がしたので、本を買ってざっと読んでみた。備忘録的に書いておく。
続きを読む