1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

LocalStackとdjango-rest-frameworkを使ってSMSを送信しよう!

Posted at

概要

AWSのマネージドサービスをローカル上で実行できるLocalStackとdjango-rest-frameworkを使ってSMSを送信する方法について解説していきたいと思います

前提

  • Djangoのプロジェクトを作成済み

ディレクトリ構成

tree
・
├── .gitignore
├── README.md
├── backend
│   ├── application
│   │   ├── __init__.py
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── fixtures
│   │   │   └── fixture.json
│   │   ├── migrations
│   │   │   ├── __init__.py
│   │   │   └── 0001_initial.py
│   │   ├── models.py
│   │   ├── urls.py
│   │   └── views.py
│   ├── manage.py
│   ├── poetry.lock
│   ├── project
│   │   ├── __init__.py
│   │   ├── asgi.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py
│   └── pyproject.toml
└── docker-compose.yml

以下のファイルを作成・編集します

  • docker-compose.yml
  • settings.py
  • models.py
  • fixtures.py
  • views.py

LocalStackの設定

まずはローカル上でAWS SNSを使用できるようにLocakStackの設定をしていきます
SERVICESにSNSを追加し、今回は

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

の環境変数をlocalstackにします

docker-compose.yml
  localstack:
    image: localstack/localstack
    container_name: localstack
    ports:
      - '4566:4566'
    environment:
      - SERVICES=sns
      - AWS_ACCESS_KEY_ID=localstack
      - AWS_SECRET_ACCESS_KEY=localstack
      - DEBUG=1
    volumes:
      - localstack_data:/tmp/localstack/data
      - localstack_bin:/var/lib/localstack

boto3の設定

Djangoのプロジェクト内でLocalStackとAWS SNSを使えるよう設定をしていきます
LocalStackを使う際はboto3.client内に以下の引数を指定します

引数 説明
aws_access_key_id localstack AWSのアクセスキー
LocalStack内の環境変数と同じ値にします
aws_secret_access_key localstack AWSのシークレットキー
LocalStack内の環境変数と同じ値にします
region_name ap-northeast-1 リージョン名
endpoint_url http://localstack:4566 ローカル環境のboto3の接続先
今回だとLocalStack

本番環境ではIAMロールを使った開発が一般的なので

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

は使用しません

settings.py
import boto3
import os

if DEBUG:
    SNS_CLIENT = boto3.client(
        "sns",
        aws_access_key_id="localstack",
        aws_secret_access_key="localstack",
        region_name=os.environ.get("AWS_DEFAULT_REGION_NAME"),
        endpoint_url=os.environ.get("AWS_SNS_ENDPOINT_URL"),
    )
else:
    SNS_CLIENT = boto3.client(
        "sns",
        region_name=os.environ.get("AWS_DEFAULT_REGION_NAME"),
        endpoint_url=os.environ.get("AWS_SNS_ENDPOINT_URL"),
    )

SMS送信用APIの実装

Modelの作成

SMSを送信するお客様のModelを作成します

models.py
import uuid

from django.core.validators import RegexValidator
from django.db import models


class Customer(models.Model):
    """お客様"""

    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        db_comment="ID",
    )
    kana = models.CharField(
        max_length=255,
        db_comment="カナ氏名",
    )
    name = models.CharField(
        max_length=255,
        db_comment="氏名",
    )
    birthday = models.DateField(
        db_comment="誕生日",
    )
    email = models.EmailField(
        db_comment="メールアドレス",
    )
    phone_no = models.CharField(
        max_length=11,
        validators=[RegexValidator(r"^[0-9]{11}$", "11桁の数字を入力してください。")],
        blank=True,
        db_comment="電話番号",
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        db_comment="作成日時",
    )
    updated_at = models.DateTimeField(
        auto_now=True,
        db_comment="更新日時",
    )

    class Meta:
        db_table = "Customer"

テストデータの作成

お客様用のテストデータを作成します

fixtures.json
[
    {
        "model": "application.Customer",
        "pk": 1,
        "fields": {
            "kana": "オオサカタロウ",
            "name": "大阪太郎",
            "birthday": "1992-01-06",
            "email":"osaka@example.com",
            "phone_no": "08011112222",
            "created_at": "2022-07-28T00:31:09.732Z",
            "updated_at": "2022-07-28T00:31:09.732Z"
        }
    },
    {
        "model": "application.Customer",
        "pk": 2,
        "fields": {
            "kana": "キョウトジロウ",
            "name": "京都二郎",
            "birthday": "1994-01-06",
            "email":"kyoto@example.com",
            "phone_no": "08022223333",
            "created_at": "2022-07-28T00:31:09.732Z",
            "updated_at": "2022-07-28T00:31:09.732Z"
        }
    },
    {
        "model": "application.Customer",
        "pk": 3,
        "fields": {
            "kana": "ヒョウゴサブロウ",
            "name": "兵庫三郎",
            "birthday": "1995-03-06",
            "email":"hyogo@example.com",
            "phone_no": "08033334444",
            "created_at": "2022-07-28T00:31:09.732Z",
            "updated_at": "2022-07-28T00:31:09.732Z"
        }
    }
]

viewの作成

今回はパラメータにお客様のIDを入れてメッセージ名にお客様の氏名が入るので動的に簡易的なメッセージを送るようにします

{{customer}}様
問い合わせありがとうございます

SMSを送信する際はSNSのClientを作成し、publishメソッドを使って送信します
日本の電話番号にSMSを送信する際は+81が必要です
SMS送信が失敗したときのためにtry catchを使ってClientErrorの時にエラーメッセージを返すようにします

views.py
from application.models import Customer
from botocore.exceptions import ClientError
from django.conf import settings
from django.http import JsonResponse
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import ModelViewSet


class CustomerViewSet(ModelViewSet):
    queryset = Customer.objects.all()
    permission_classes = [IsAuthenticated]
    serializer_class = None

    @action(methods=["post"], detail=True)
    def send_sms(self, request, pk):
        customer = self.get_object()
        message = f"{customer.name}\n問い合わせありがとうございます"
        try:
            settings.SNS_CLIENT.publish(
                PhoneNumber="+81" + customer.phone_no, Message=message
            )
            return JsonResponse({"msg": "SMSの送信に成功しました"},)
        except ClientError as e:
            return JsonResponse(
                {"msg": "SMSを送信できませんでした"},
                status=status.HTTP_400_BAD_REQUEST,
            )

実際に送信してみよう!

先ほど作成したAPIにお客様のPKを入れてPOSTします
以下のようにSMSを送信できたら成功です

スクリーンショット 2024-01-17 17.37.04.png
スクリーンショット 2024-01-17 17.37.32.png

以下のようにLocalStackのlogから送信が成功したことを確認できました

2024-01-17 17:36:55 2024-01-17T08:36:55.533 DEBUG --- [   asgi_gw_0] l.services.sns.publisher   : Publishing '66c16f50-ee4f-4c69-b2f6-865385453f57' to phone number '+8108011112222' with protocol 'sms'
2024-01-17 17:36:55 2024-01-17T08:36:55.535  INFO --- [   asgi_gw_0] localstack.request.aws     : AWS sns.Publish => 200
2024-01-17 17:36:55 2024-01-17T08:36:55.535  INFO --- [   sns_pub_0] l.services.sns.publisher   : Delivering SMS message to +8108011112222: 大阪太郎様
2024-01-17 17:36:55 問い合わせありがとうございます

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?