自動化無しに生活無し

WEB開発関係を中心に備忘録をまとめています

  • DRFでModelViewSetの動的ルーティング(URL内引数)を作る

    例えば、ModelViewSetが以下のような場合 from rest_framework import viewsets from .models import Category,Topic,Reply from .serializers import CategorySerializer,TopicSerializer,ReplySerializer class CategoryView(viewsets.ModelViewSet): serializer_class = CategorySerializer queryset = Category.objects.all() class TopicView(viewsets.ModelViewSet): serializer_class = TopicSerializer queryset = Topic.objects.all() class ReplyView(viewsets.ModelViewSet): serializer_class = ReplySerializer queryset = Reply.objects.all() ルーティングは、このように DefaultRouter を使うと良い。 from django.contrib import admin from django.urls import path,include from rest_framework import routers from bbs import views router = routers.DefaultRouter() router.register(r"topics", views.TopicView, "topic") router.register(r"categories", views.CategoryView, "category") router.register(r"replies", views.ReplyView, "reply") urlpatterns = [ path('admin/', admin.site.urls), path('api/', include(router.urls)), ] だが、これではTopicに紐付いていないReplyまで取得できてしまう。 そこで、 HTTP GET /api/replies/ でReplyを取得するのではなく、 HTTP GET /api/topics/1/replies/ このように動的ルーティング(URL引数 ...
  • DRF+ReactのSPAでCRUD簡易掲示板をつくる

    開発要件 DRF+ReactでSPA react-router-domでページURLの構築 簡易掲示板のCRUD機能 カテゴリ指定・追加機能 リプライ投稿機能 CSRF検証の挙動を確認するため、あえてJWT認証はオミット CRAではなくViteを使用 以前のものは、1対多には対応しておらず、CRAを利用していた。またページもない。 更に、axiosがコールバック地獄になっているので、そちらも修正した。 使用ライブラリ ...
  • DRFはいつCSRF検証をするのか?

    開発中、おかしなことが起こった。 これまでCSRFトークン無しで、PUTやDELETEメソッドが送信できていた。 だが、突然、同様の状況で403エラー(CSRF token missing)が起きた。 CSRFトークン無しでリクエストできていたものが、急に403エラーになりCSRF検証を行うようになった。 何故か? DRFのビューでは、CSRF検証が免除されている https://github.com/encode/django-rest-framework/blob/master/rest_framework/viewsets.py#L146 DRFのビューは、このように .as_view()の戻り ...
  • DateTimeFieldで、フォーマットを指定したserializers.pyを作る

    DateTimeFieldを含むモデルで、シリアライザをこう作ると from rest_framework import serializers from .models import Category,Todo class CategorySerializer(serializers.ModelSerializer): class Meta: model = Category fields = ("id", "created_at", "name", "color") class TodoSerializer(serializers.ModelSerializer): category = CategorySerializer() class Meta: model = Todo fields = ("id", "category", "created_at", "content", "deadline", "is_done") このようにタイムゾーン表記になってしまう。 作成日: 2024-12-25T12:00:00+09:00 締切: 2024-12-25T12:00:00+09:00 年月日表記に修正をするには、serializers.pyでフォーマットを指定する。 from rest_framework import serializers from .models import Category,Todo class CategorySerializer(serializers.ModelSerializer): created_at = serializers.DateTimeField(format="%Y年%m月 ...
  • 1対多のモデル構造で、ネストしたserializers.pyを作る

    通常、 class Category(models.Model): name = models.CharField(max_length=100) class Todo(models.Model): title = models.CharField(max_length=200) category = models.ForeignKey(Category, on_delete=models.CASCADE) このモデル構造の場合、シリアライザはこうなる。 from rest_framework import serializers from .models import Todo, Category class CategorySerializer(serializers.ModelSerializer): class Meta: model = Category fields = ['id', 'name'] class TodoSerializer(serializers.ModelSerializer): class Meta: model = Todo fields = ['id', 'title', 'category'] ただこれだと、フロントサイドで得られる、JSONは、 [ { "id": 1, "title": "Todo 1", "category": 1 }, { "id": 2, "title": "Todo 2", "category": 2 } ] このように、categoryのidのみであり、カテゴリ名を表示することはできない。 ネストしたSerializerを指定する。 そこで、このように、TodoSerial ...
  • DjangoでWebSocketを使って、チャットサイトを作る

    django-channelsを使ってWebSocketを実現させる【チャットサイト開発に】 ここで、チャットサイトを作ったが、ページリロードで全て消えてしまう。 チャンネルレイヤーにメッセージを与えるだけでなく、DBにも記録するように仕立てた。 consumers.py import json from channels.generic.websocket import AsyncWebsocketConsumer from asgiref.sync import sync_to_async from .forms import ChatLogForm from django.utils import timezone class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope['url_route']['kwargs']['room_name'] self.room_group_name = 'chat_%s' % self.room_name await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() async def disconnect(self, close_code): await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) async def receive(self, text_data): text_data_json = json.loads(text_data) message = text_data_json['message'] chat_log = await self.save_chat_log(message) if chat_log == None: return False local_created_at = timezone.localtime(chat_log.created_at) created_at_str = local_ ...
  • DjangoでServerSentEvents(SSE)とローカルキャッシュを使い、リアルタイムでDB内の情報を表示する

    【前置き】Djangoでリアルタイム通信する場合 DjangoでDB内の情報をリアルタイムで表示させる場合、 ポーリング Server Sent Events Web Socket この3つが候補に挙がる。 ポーリングはシンプルではあるが、リクエストを送らない限り、情報は得られない。 【Django】Ajax(jQuery)でロングポーリングを実装させる【チャットサイトの開発に】 WebSocketは実装難度が高い。 【Django】channelsを使ってW ...
  • 【Django】アップロードしたPythonファイルを動かす【subprocessと動的import】

    • 作成日時:
    • 最終更新日時:
    • Categories: サーバーサイド
    • Tags: django
    アップロードしたPythonファイルをDjango側で動作させる。 仮想環境を動かし、事前にインストールしておいたライブラリも動くようにする。 views.py from django.shortcuts import render,redirect from django.views import View from .models import Document from .forms import DocumentForm from django.conf import settings import subprocess import importlib.util import os class IndexView(View): def get(self, request, *args, **kwargs): context = {} context["documents"] = Document.objects.all() # アップロードされたPythonを実行する。 document = Document.objects.filter(id=1).first() # アップロードされたPythonプログラムのファイルパスを作成 program_path = str(settings.BASE_DIR) + document.file.url # 仮想環境のファイルパスを作成(pythonファイルのある ...
  • Djangoのcreatesuperuserでインタラクティブシェルを省略する。

    python manage.py createsuperuserで管理ユーザーをつくることができるが、その後のインタラクティブシェルの入力がめんどくさい。 そこで、環境変数を使ってインタラクティブシェルを省略する。 更に、エイリアスを使ってコマンド入力も簡略化させる。 # createsuperuser の自動化 export DJANGO_SUPERUSER_USERNAME="asahina" export DJANGO_SUPERUSER_EMAIL="asahina@asahina.com" export DJANGO_SUPERUSER_PASSWORD="seiya0723" alias django_createsuperuser="python manage.py createsuperuser --noinput" ...