js n個の要素を持つ配列を作成する
jsで、1〜nの連番を持つ要素を作るときに スマートな書き方を教えてもらったのでメモ。
// Array.from()の連番の生成で素直に書いていたやつ const range = Array.from(new Array(100)).map((v, i) => i + 1); // こっちの方がちょっとだけ短く書ける const better = [...Array(100)].map((v, i) => i + 1)
js 配列の中の特定のオブジェクトを上書き
[{ },{///},{ }]
↑条件に当てはまるこのオブジェクトだけ上書きしたい、という時
const oldDataArray = [{id:"1", ☆},{id:"2",☆},{id:"3",☆}]; const editedData = {id:"2",★}; const newDataArray = Array.from(oldDataArray, data => { if (data.id === editedData.id) { return editedData; } else { return data; } }); console.log(newDataArray);
datatables ページを跨いでチェックボックスを操作する
- datatablesで、ページを跨いでチェックボックスを操作する処理。
- サーバー側ではなく画面側でページングしている場合。
var table=null; table = $("#result-table").DataTable({ // 色々設定 〜〜 // 描画後にイベントを付与 drawCallback: addCheckEvent }); var addCheckEvent = function () { // チェックボックス全体操作 var checkboxs = table.$('.check_line') // $('.check_line')のみで指定すると1ページ分しか取得できない $(document).on('change', '#check_all', function(){ for (var i = 0; i < checkboxs.length; i++) { table.$('.check_line').prop('checked', $('#check_all).prop('checked')); } }); // 一つでもチェックが外れていたら全選択チェックを外す for (var checkbox of checkboxs) { checkbox.onclick = function () { for (var i = 0; i < checkboxs.length; i++) { if (checkboxs[i].checked == false) { $('#check_all'').prop('checked', false); } else { if (table.$('.check_line').filter(':checked').length == checkboxs.length) { $('#check_all'').prop('checked', true); } } } }; }; }
datatables 再描画処理
困っていたこと
jQueryのdatatablesで、
- ajaxによるデータ取得とテーブル描画($("#table").find('tbody').append(tr_contents)で描画)とdatatablesへの変換を分離
- 「検索」ボタンでデータ再取得・テーブル再描画
ていう処理をしたいときに、datatablesの初期化がすんなりいかなかったのでメモ。
こうすると
var table = null; if (table) { // 二回目以降の描画の場合、初期化が必要 $("#result-table tbody > tr").remove(); table.state.clear(); } // table描画処理 table = $("#result-table").DataTable({ 〜〜
テーブル自体の初期化は上手くいき、新たなデータでテーブルが作成されるが 「○件中X~X件を表示」の部分が初回の情報のまま更新されない。
var table = null; if (table) { // 二回目以降の描画の場合、初期化が必要 $("#result-table tbody > tr").remove(); table.state.clear(); table.destroy(); } // table描画処理 table = $("#result-table").DataTable({ 〜〜
table.destroy()を追加すると、件数情報は更新されるのだが テーブルが初期化されず、初回に描画したテーブルに新たな行がどんどん追加されてしまう。
解決
var table = null; if (table) { // 二回目以降の描画の場合、初期化が必要 table.state.clear(); table.destroy(); $("#result-table tbody > tr").remove(); // $("#result-table tbody").empty();で良い } // table描画処理 table = $("#result-table").DataTable({ 〜〜
tbodyを空にする処理のタイミングを変えたら実現できた。 蓋を開けてみたらブログに書くほどのことでもないレベル!! でも下書きしてたので載せる。
Djangoをbeanstalk上にデプロイした時に認証が通らない
事象
リクエストのヘッダーにAuthorization情報を付けて、各APIに認証チェックを入れたい。 curlにすると以下のイメージ
curl -H "Authorization: JWT XXXXXXX" -G http://localhost:8000/api/piyo/getList?login_id=test@test.jp
ローカルではちゃんと認証が通ってレスポンスが返却されるが、
AWSにデプロイしたAPIに同じリクエストを送っても認証エラーになってしまう。
{"status":false,"errors":[{"error_id":"認証エラー"}]}
解決方法
python - Authentication credentials were not provided. when deployed to AWS - Stack Overflow
.ebextensions/django.configに対して、「container_commands:〜」以下のコマンドを追加する
option_settings: aws:elasticbeanstalk:container:python: WSGIPath: XXX_api/wsgi.py aws:elasticbeanstalk:application:environment: DJANGO_SETTINGS_MODULE:XXX_api.settings container_commands: 01wsgipass: command: 'echo "WSGIPassAuthorization On" >> ../wsgi.conf'
認証が通るようになった!
Django rest frameworkで認証エラー時のレスポンスをカスタマイズ
認証モデルのカスタマイズ方法はこちらを参考にさせて頂きました。
django-rest-framework-jwtの認証をカスタマイズする方法 - らっちゃいブログ
sampleView.py
class SampleView(APIView): permission_classes = (permissions.IsAuthenticated,) # 認証チェック def post(self, request, format=None): ~~
こんな感じでViewを定義するだけで
{"detail":"Incorrect authentication credentials."}
こういうレスポンスを返してくれる。優しい
でもこのレスポンスをこちらの仕様に合わせてカスタマイズしたい。
→ 認証エラー時のハンドルはAPIViewで行なっていたので、該当箇所をオーバーライドしてみた。
sampleAuth.py
from rest_framework_jwt.settings import api_settings from rest_framework.views import APIView from rest_framework.response import Response class APIViewWithTokenCheck(APIView): ''' APIViewに対してエラーレスポンス返却処理をオーバーライド ''' def handle_exception(self, exc): """ Handle any exception that occurs, by returning an appropriate response, or re-raising the error. """ if isinstance(exc, (exceptions.NotAuthenticated, exceptions.AuthenticationFailed)): return Response( #返却値をカスタマイズ data={ 'status': False, 'error_code':'999_auth_error', }, status=status.HTTP_401_UNAUTHORIZED) exception_handler = self.get_exception_handler() context = self.get_exception_handler_context() response = exception_handler(exc, context) if response is None: self.raise_uncaught_exception(exc) response.exception = True return response
これでレスポンスがカスタマイズされる。
{"status":false,"error_code":"999_auth_error"}
ベストなやり方かは不明…
DRF serializerで値の上書き
- Django REST Frameworkで、serializerのis_valid()とsave()を使用してDBへの登録を実装する
- table Aへの新規登録後に発行されるIDを使ってtable Bにインサートしたい
- 先に全てのserializerに対してチェックを行ってから登録を実行したい
A_serializer = ASerializer(data=request_data) if A_serializer.is_valid(): return Response( data={ 'status': False, 'errors':A_serializer.errors, }, status=status.HTTP_400_BAD_REQUEST) request_data["id_for_b"] = None # request_dataからは空文字が渡される。設定先の変数はint型なのでエラーになるためNoneで上書き B_serializer = BSerialiser(data=request_data) if not B_serializer.is_valid(): return Response( data={ 'status': False, 'errors':B_serializer.errors, }, status=status.HTTP_400_BAD_REQUEST) A_serializer.save() # 発行されたIDで測定情報を登録 B_serializer.validated_data["id_for_b"] = A_serializer.data["id"] B_serializer.save()
validated_data["id_for_b"]で上書きできるというのがわからなかった・・・。