Windowsに正しくPythonをインストールする方法

WindowsにPythonを正しくインストールする方法

今日はWindowsにPythonを正しくインストールする方法を説明します。 Windowsには複数のバージョンのPythonをインストールすることができます。しかし、Windowsの環境変数にどのバージョンのPythonをどの名称で使うようにするか教えてあげないといけないのがかなり面倒になることがあります。この理由から、MacやLinuxを使いやすいと言っている人もいるくらいです。 しかし!一度やり方を覚えてしまえばよいので是非試してください。 Pythonをダウンロードする 下記のPythonの公式リンクからPythonをダウンロードしてください。 もしリンクが怪しいと思った人は自分で検索してpython.orgのサイトからダウンロードしましょう。本題とはそれますがインターネットの脅威を避ける癖はとても重要になります。 https://www.python.org/downloads/ このPythonの公式サイトにいったら、最新のバージョンをダウンロードしましょう。 ちなみにPythonのバージョン2とバージョン3ではシンタックスが違ってきます。つまり、Python2で書かれたコードをPython3で実行するとエラーになることがあるという事です。 Python2は2020年にサポートが終了しているので理由がない限りインストールする必要はありません。 Pythonインストーラーを実行する ではダウンロードしたPythonインストーラーをダブルクリックしてインストールを進めていきましょう。 重要!!!!! ここで注意してほしいのが”PythonをPATHに登録する”のチェックボックスをクリックしておく必要があることです。 チェックしてください。 これをチェックしないとコマンドプロンプトでpythonのコマンドが使えません。 後から登録することができますが、ちょっと面倒です。 これができたら、Install Nowのボタンからインストールしていきます。 この場合だとWindowsユーザーのProgramsにPythonが保存されるようになります。 管理者の権限を聞かれるのでOKを押してください。 インストールが開始されます。 これでインストールが完了しました。 では、コマンドプロンプトを開いてPythonが使えるか確認してみましょう。 私の場合は英語ですが、これを開きましょう。 ではインストールされたPythonのバージョンが正しいか見てみましょう。 コマンドプロンプトに下記のコマンドを書いてエンターを押します。 私の場合はPythonの3.10.7をインストールしたのに3.10.0が表示されました。 これはすでにPython3.10.0が環境変数に登録されているからです。 もし、今回が初めてのインストールの場合は問題はないと思います。 ちなみにPythonで使うPIP(Pythonのパッケージマネージャー)も一緒にインストールされるのでご安心を。

Django RESTクイックスタート

今日はシンプルなAPIを作成し、アドミンユーザーがブラウザから実際にAPIを見れるようにするところまで紹介したいと思います。

始める前に。。。Django REST APIはDjangoの基礎を理解していることを前提に学ぶことをお勧めします。

プロジェクトのセットアップ

 tutorialという名前のプロジェクトを作成し、 quickstartという名前でアプリを作成します。

# Create the project directory
mkdir tutorial
cd tutorial

# Create a virtual environment to isolate our package dependencies locally
python3 -m venv env
source env/bin/activate  # On Windows use `env\Scripts\activate`

# Install Django and Django REST framework into the virtual environment
pip install django
pip install djangorestframework

# Set up a new project with a single application
django-admin startproject tutorial .  # Note the trailing '.' character
cd tutorial
django-admin startapp quickstart
cd ..

プロジェクトのファイル構成はこんな感じになります。

$ pwd
<some path>/tutorial
$ find .
.
./manage.py
./tutorial
./tutorial/__init__.py
./tutorial/quickstart
./tutorial/quickstart/__init__.py
./tutorial/quickstart/admin.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/migrations
./tutorial/quickstart/migrations/__init__.py
./tutorial/quickstart/models.py
./tutorial/quickstart/tests.py
./tutorial/quickstart/views.py
./tutorial/asgi.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py

ではデータベースを更新しましょう。

python manage.py migrate

次にDjango側のアドミンを作成します。例として、名前は admin でパスワードはpassword123にしましょう。このユーザーを後からAuthenticate(認証)で使います。

python manage.py createsuperuser --email admin@example.com --username admin

これで初期の設定はOKです。では早速ロジックを作るべく、コーディングにとりかかりましょう。

Serializers(シリアル化)

まずは、Serializersの設定をおこないます。慣習としてserializers.pyというファイル名を使うようにしましょう。では、 tutorial/quickstart/serializers.pyのファイルを作成し、データベースのデータをシリアル化させる役目をここで指示します。

from django.contrib.auth.models import User, Group
from rest_framework import serializers


class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['url', 'username', 'email', 'groups']


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ['url', 'name']

今回は例としてHyperlinkedModelSerializerを使用しています。これはModelSerializerに似ているものです。違いは、primary keyがModelSerializerになるのですが、HyperlinkedModelSerializerはurlがpライマリーキーフィールドとして設定されます。ハイパーリンクはRESTfulのデザインとして良い慣習とされているので覚えておきましょう。

Views

Viewsでは、ユーザーからリクエストがあった際にどのような動きをさせるか指示させるファイルでしたね。通常のDjangoならHTMLのテンプレートを返したりしますが、今回はAPIを返すように指示します。

では、次の tutorial/quickstart/views.pyを開きコーディングしましょう。

from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]


class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    permission_classes = [permissions.IsAuthenticated]

ここでViewSetsの登場です。ViewSetsはCRUDのすべてのリクエストに対応できるスーパーセットです。これで、いちいちDELETEのリクエストやPUTのリクエストがあった動きを毎回書く必要がなくなりました。

もちろん、何か特別な動きをさせたいときはこれを上書きすることもできます。

今はこのロジックを使ってクリーンなコードのままにしておきます。

URLs

では次の tutorial/urls.pyからAPIのエンドポイントとなるURI(URL)を設定していきます。

from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

ここで覚えておきたいのが、ViewSetsはひとつのURLでCRUDのすべてのリクエストを受け取ることができることです。

なので、ここでは単純に先ほど作成したViewSetsと登録するだけでOKです。

繰り返しになりますが、単純にGETリクエストだけを受け付けたい場合は普通のクラスベースのViewを設定することでできます。

最後に、Djangoでついてくるログインとログアウトのロジックを追加することができることを紹介します。例えば顧客情報などの重要な情報は認証されたユーザーしかアクセスできないようにしたいですよね。

他にもいろいろなやり方でAPIを守る方法があるのでこれから学んでいきましょう。

Pagination(ページ)

ページネーションでは、1つのリクエストに対して返すデータの数を制限することができます。

これは tutorial/settings.pyで設定することができます。

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

Settings

次に、'rest_framework' をINSTALLED_APPSに追加してDjango側でライブライが追加されたことを登録してあげます。このセッティングのファイルはtutorial/settings.pyになります。

INSTALLED_APPS = [
    ...
    'rest_framework',
]

いいですね。


APIをテストする

では早速テストサーバーを起動してAPIを確認してみましょう。

python manage.py runserver

コマンドラインやcurlのようなツールを使ってAPIをテストすることもできます。

bash: curl -H 'Accept: application/json; indent=4' -u admin:password123 http://127.0.0.1:8000/users/
{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "email": "admin@example.com",
            "groups": [],
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin"
        },
    ]
}

もしくはhttpieでもこのようにテストできます。

bash: http -a admin:password123 http://127.0.0.1:8000/users/

HTTP/1.1 200 OK
...
{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "email": "admin@example.com",
            "groups": [],
            "url": "http://localhost:8000/users/1/",
            "username": "paul"
        },
    ]
}

一番手っ取り早いのがDjangoのブラウザで確認することですね。URL http://127.0.0.1:8000/users/

Quick start image

もし、ブラウザからAPIを確認したい場合はDjangoアプリケーションにログインしていることを忘れずに確認してください。

では、これでDjango REST Frameworkのクイックスタートの説明を終了します。

Django Rest Framework (DRF)でトークン認証の際にユーザー名を取得する方法

準備するもの

・Django RESTFrameworkのプロジェクト

・Python

イントロ

通常、Djangoのプロジェクトならログインしているユーザー情報をHTMLテンプレートに出力することは簡単ですね。

ではAPIでクライアント側にDjangoのユーザー情報を渡したい場合はどうすればよいでしょうか。

今日は、これを解決するためにDjango REST Frameworkのトークン認証のメソッドを上書きしていきます。

準備するもの

GitHubから完成したサンプルコードを参考にしてください。

詳しい公式ドキュメンテーションがあるのでこれも参考にしてください。

https://www.django-rest-framework.org/api-guide/authentication/

CustomAuthTokenクラスを作成する

これからアプリのViews.pyにCustomAuthTokenのクラスをコピペしてそのリスポンスに返したいデータを追加するだけです。

from rest_framework.authtoken.views import ObtainAuthToken

from rest_framework.authtoken.models import Token

from rest_framework.response import Response



class CustomAuthToken(ObtainAuthToken):



    def post(self, request, *args, **kwargs):

        serializer = self.serializer_class(data=request.data,

                                           context={'request': request})

        serializer.is_valid(raise_exception=True)

        user = serializer.validated_data['user']

        token, created = Token.objects.get_or_create(user=user)

        return Response({

            'token': token.key,

            'user_id': user.pk,

            'email': user.email

        })

urls.pyでURLも更新する

では、トークンを取得するURLも更新しましょう。

urlpatterns += [

    path('api-token-auth/', CustomAuthToken.as_view())

]

検証する

http POST http://127.0.0.1:8000/api-token-auth/ username="admin@gmail.com" password="admin"

ではコマンドラインからHTTPリクエストを送ってみましょう。

ちなみに通常のusernameの箇所にはユーザー名が入りますが、今回使用しているDjangoアプリはEmailでトークンが取得できるように変更しています。

OKっすね。

ちなみにEmailだけではなくでユーザー名も取得したい場合はこんな感じです。

        return Response({

            'token': token.key,

            'user_id': user.pk,

            'user_name': user.user_name

            # 'email': user.email

        })

お疲れ様です。

Djangoのユーザーモデルとアドミンパネルをカスタムしよう

準備するもの

・Python3

・Djangoの基礎知識

イントロ

DjangoでデフォルトでついてくるユーザーモデルはEmailと名前くらいのシンプルなものですね。

今日は、Djangoについてくるユーザーモデルにこれから使う、従業員管理に合わせてモデルを追加していきます。

今日紹介する内容はこのリンクからも公式ドキュメントで確認できます。

https://docs.djangoproject.com/en/4.0/topics/auth/customizing/

解決できる課題

Djangoのユーザーモデルに従業員の電話番号などの情報を追加できるようになる。

Djangoのアドミンパネルで検索機能を付ける。

Djangoのアドミンパネルに表示するデータを増やす。

下準備

今回は、従業員のチケット管理アプリのバックエンドを想定したサンプルコードを紹介します。

下から完成したサンプルコードをダウンロードしてください。

https://github.com/TraitOtaku/djangoAPI/tree/9_CustomUserModel

ではいつものようにgitのコマンドを使ってリポジトリをクローンしましょう。

Gitの使い方はこちらの動画で説明しています。

git clone https://github.com/TraitOtaku/djangoAPI.git

cd DjangoAPI

git branch -a

git checkout 9_CustomuserModel

バーチャル環境を設定しましょう。

pip install virtualenv

virtualenv env

env\Scripts\activate

pip install -r requirements.txt

Djangoを設定していきます。

python manage.py makemigrations

python manage.py migrate

python manage.py createsuperuser

python manage.py runserver

カスタムUserモデルを作ろう

まずは、デフォルトのDjangoのユーザーモデルをインポートして上書きしていく作業になります。

下記のモジュールをインポートしています。

from django.utils.translation import gettext_lazy as _

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager

ユーザーモデル

では、下記のモデルを見てみましょう。

AbstractBseUserからDjangoのUserモデルを引っ張ってきています。

class Member(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(_('email address'), unique=True)

    user_name = models.CharField(max_length=150, unique=True)

    first_name = models.CharField(max_length=150, blank=True)

    last_name = models.CharField(max_length=150, blank=True)

    phone = models.CharField(max_length=150, blank=True)

    about = models.TextField(_(

        'about'), max_length=500, blank=True)

    is_staff = models.BooleanField(default=False)

    is_active = models.BooleanField(default=False)



    objects = CustomAccountManager()



    USERNAME_FIELD = 'email'

    REQUIRED_FIELDS = ['user_name', 'first_name']



    def __str__(self):

        return self.user_name

USERNAME_FIELD = ’email’ でログインする際のユーザーネームの代わりにEmailとパスワードでログインできるようになります。

REQUIRED_FIELDSはユーザーを作成する際に必須な項目の事です。

objects = CustomAccountManager()でアドミンの権限のあるユーザーの設定を上書きします。

BaseUserManager

今度は、アドミン権限のあるユーザーの設定を上書きしていきます。

class CustomAccountManager(BaseUserManager):



    def create_superuser(self, email, user_name, first_name, password, **other_fields):



        other_fields.setdefault('is_staff', True)

        other_fields.setdefault('is_superuser', True)

        other_fields.setdefault('is_active', True)



        if other_fields.get('is_staff') is not True:

            raise ValueError(

                'Superuser must be assigned to is_staff=True.')

        if other_fields.get('is_superuser') is not True:

            raise ValueError(

                'Superuser must be assigned to is_superuser=True.')



        return self.create_user(email, user_name, first_name, password, **other_fields)



    def create_user(self, email, user_name, first_name, password, **other_fields):



        if not email:

            raise ValueError(_('You must provide an email address'))



        email = self.normalize_email(email)

        user = self.model(email=email, user_name=user_name,

                          first_name=first_name, **other_fields)

        user.set_password(password)

        user.save()

        return user

Settings.pyの設定

このファイルのどこかに下記のラインを追加しましょう。

これでDjangoがMemberモデルを使ってユーザー認証をするように指示できます。

AUTH_USER_MODEL = 'members.Member'

Admin.pyの設定

ではアドミンパネルの表示をカスタマイズしていきます。

from django.contrib import admin

from .models import Member, Office

from django.contrib.auth.admin import UserAdmin



class UserAdminConfig(UserAdmin):

    model = Member

    search_fields = ('email', 'user_name', 'first_name',)

    list_filter = ('email', 'user_name', 'first_name', 'is_active', 'is_staff')

    ordering = ('email',)

    list_display = ('email', 'user_name', 'first_name',

                    'is_active', 'is_staff')

    fieldsets = (

        (None, {'fields': ('email', 'user_name',

         'first_name', 'last_name', 'phone', 'password')}),

        ('Permissions', {'fields': ('is_staff', 'is_active')}),

    )

    # formfield_overrides = {

    #     NewUser.about: {'widget': Textarea(attrs={'rows': 10, 'cols': 40})},

    # }

    add_fieldsets = (

        (None, {

            'classes': ('wide',),

            'fields': ('email', 'user_name', 'first_name', 'phone', 'password1', 'password2', 'is_active', 'is_staff')}

         ),

    )



admin.site.register(Office)

admin.site.register(Member, UserAdminConfig)

見たままの感じですがこれをもとにするとアドミンパネルももっと使いやすくなりますね。

ではおつかれさまです。

Vueアプリでトークン認証のログインシステムを作る

準備するもの

・Django RESTとToken Authができている環境

・Vueのアプリ

アプリ紹介

今回は、フロントエンドがVueでバックエンドがDjangoでできているチケット管理システムのログインのシステムを作成します。

例として、従業員がお客様からの問い合わせに対してチケットを作成していくようなイメージです。

Vueがフロントエンド(クライアント側)でDjangoのAPIのエンドポイントからデータを発信しています。

しかし、このAPIが公共に垂れ流しの状態なのでURI(URL)にアクセスできる人誰でもこのデータにアクセスできてしまいます。

前回はDjango RESTFramewrokを使ってトークンAuthでこのトークンがある人だけデータにアクセスできる人だけAPIのリクエストにデータをリスポンスとして返すことができました。

今日はそれをVueのアプリから行っていきたいと思います。

アプリの準備

DjangoアプリはこちらのURLのGitHubからクローンしてください。

https://github.com/TraitOtaku/djangoAPI/tree/8_AuthReady

Vueのアプリはこちらからダウンロードしてください。

https://github.com/TraitOtaku/VueApp/tree/4_AuthReady

Gitのコマンドを使ったことがない人は面倒でも必須のスキルですので必ず覚えておくようにしましょう。

Gitのコマンドです。

git clone URL

cd /to/repo/

git branch -a

Git checkout <branch_name> 

Djangoの準備の仕方は他の動画でも説明しているので今回は飛ばします。

Vueもnpmかyarnでライブラリをインストールして準備完了です。

npm i

EventService.js

まずは、ログインする際にDjangoにユーザー名とパスワードをJSONファイルで送りつけます。この際POSTリクエストになっていることに注意しましょう。

で、正しいクレデンシャル(ログイン情報)が遅れた後にDjangoからTokenが返されます。

const loginClient = axios.create({

  baseURL: "http://127.0.0.1:8000/",

  withCredentials: false,

  headers: {

    Accept: "application/json",

    "Content-Type": "application/json",

  },

});
  submitLogin(logininfo) {

    return loginClient.post("api-token-auth/", logininfo);

  },

ちなみにapiClientというファンクションでDjangoのTokenAuthに必要なTokenをリクエストの際に送るヘッダーに付けてあげるようにしています。

const apiClient = axios.create({

  baseURL: "http://127.0.0.1:8000/api",

  headers: {

    Authorization: `Token ${localStorage.getItem('token')}`,

    "Content-Type": "application/json",

  },

});

では、このJavaScriptをエキスポートして、LoginView.vueのコンポーネントを作成します。

LoginView.vue

このページ(コンポーネント)でログインに関連するシステムを構築しています。

AntDesignのUIライブラリからコピペしたフォームと、そのサブミットボタンにクリックイベントを付けてます。

    const submitLogin = () => {

      EventService.submitLogin(toRaw(formState))

        .then((response) => {

          console.log(response.data);

          localStorage.setItem('token', response.data.token)

          router.push({ name: 'home' })



        })

        .catch((error) => {

          console.log("Error" + error);



        });

    }

で、ここで、Django から返ってきたトークンをブラウザのストレージにtokenというキーで保管しておきます。

これでログインができたらrouter.pushでホーム画面にジャンプするように設定しています。

本来なら、ログインしない限りhomeのページへのアクセスはできないようにするのがベストですが、今回は割愛しています。

もしするのであればv-ifとvuexでState managementを使うのがベストだと思います。

また、ログインのエラーがあった場合のロジックもここに追加できますね、。

では、ログインができたらHomeViewに行くのでそこにログアウトのボタンも作成しましょう。

HomeViews.vue

ログアウトのロジックは下記のようなコードでできます。

単純にlocalStorageに保管されているtokenアイテムを取り除き、router.pushのコマンドでログイン画面に誘導してあげます。

    const logOut = () => {

      localStorage.removeItem('token')

      router.push({ name: 'login' })

    }

まとめ

まあ、全体的に煩雑なコードですが、これでVueアプリからDjangoのToken AuthのAPIにアクセスすることができました。

バックエンドのテクノロジーとAuth(認証)のやり方によって、ヘッダーの書き方が変わることに注意しましょう。

あとはサインアップと、パスワードを忘れた際の再設定のロジックもDjango側と一緒に作成していけばプロダクションで使えそうですね。

お疲れ様です。

Django – ネスト化されたAPI

準備するもの

・Django REST Frameworkのコード

チケットシステムの例

今日はこのチケット管理システムもモデルを元に説明します。

Djangoのアプリという概念で、このDjnagoプロジェクトに下記の3つのアプリが設定されております。

  • Customers
  • Members
  • Tickets

では、それぞれもモデルを見ると、アプリに必要なデータベースのモデルがあることが分かりますね。

Foregin KeyがPKで表示される

通常、ViewSetやAPIViewで作成したForeignKeyの項目はそのキーのPK(プライマリーキー)で表示されます。これはデータベースを見ると分かりますが、DB自体がこの外部キーをPKとして保管しているからです。

これだとせっかくAPIにしてもクライアント側のアプリでは使い物になりませんね。

StringRelatedFieldの使い方

その問題を簡単に解決できるのがStringRelatedFieldです。

これはモデルで設定した__Str__の値を返してくれます。

    def __str__(self):

        return self.inquiry

ただしこの問題は、これらのStringRelatedFieldを使うとReadOnlyのAPIになり、いざユーザー側からPOST(データの投稿)をしたい場合にエラーが発生します。

DjangoRESTのエンドポイントのHTMLフォームからも項目が削除されたことでも確認できますね。

ネスト化されたAPIモデル

ほかに、depthメタを使用してforeign keyの一階層下まで参照することができます。

この画像のようにモデルをシリアル化する際にforeign Keyでリファレンス(参照)しているキーをどの階層まで出力されるか設定することができます。

これも便利ですがReadOnlyです。

    class Meta:

        model = Ticket

        fields = '__all__'

        # depth = 1

APIでForeignKeyを受け付ける方法

Django RESTフレームワークでも、外部キー(Foregin Key)の扱いは我々デベロッパーに任されており、魔法のようなソリューションはありません。と記載されております。

色々試した結果、このオープンソースのライブラリが一番簡単な解決方法だと思ったので紹介します。

このライブラリはBeda Sotwareというロシアの医療ソフト開発会社が提供しているようですね。

https://github.com/beda-software/drf-writable-nested

ではこのライブラリをインストールしましょう。

pip install drf-writable-nested

その後に単純にシリアライザーのパラメーターを下のように変えるだけです。

class TicketSerializer(WritableNestedModelSerializer):

    # category = CategorySerializer()

    # staff = MemberSerializer()

    # store = StoreSerializer()

で、それぞれのシリアライザーをインポートすればCRUDレディーのAPIが完成です。

実際に試してください。

お疲れ様です。

Django API Authってなに?Token Authenticationを使ってみよう

サマリー

APIのエンドポイントを守れ!
 

準備するもの

  • Pythonとpip
  • Django RESTFrameworkのプロジェクト

Authってなに?

Authは認証のことで、Autheniticationの事を意味します。ここで、Authorizationと間違える事が多いですがこの2つは全くの別ものなのでちゃんと理解をしておきましょう。

Authentication(認証)→誰かを証明すること

Authorization(権限を与える)→特定のデータへのアクセスを許可するか

なのでAuth(認証)された人がどのPermissionがあるのかを判断する方法になり、それから、認証された人が特定のデータにアクセスできるかをAuthorizeするわけですね。

例でいうと会社のセキュリティカードを持っていればそのカードのステータスによってアクセスできる場所が決まってくるような感じでしょうか。

Authはなぜ必要か

APIのエンドポイントのURI(URL)にアクセスできる誰もがその情報を手に入れることができます。その情報を守るために認証された人だけにデータのアクセス権限を与えるためです。

特にデータの更新や削除ができる権限は限られた人だけに与えたいですよね。

Authの種類について

Djangoで主流なAuthシステムを紹介します。

  1. Basic Authentication→ログインIDとPWだけの簡単なものです。
  2. Token Authentication→トークンを使ってHTTP認証をします。クライアント・サーバーセットアップのデスクトップアプリやモバイルアプリに最適です。
  3. SessionAuthentication→DjangoについてくるセッションAuthのシステムを使えます。時間が経つとログアウトされる仕組みとかも作れます。
  4. JWT(JSON Web Toekn)→ ここ数年で人気になったJSONウェブトークンでの認証システムです。

BasicAuthenticationを使おう

他にJWTとDjoserのライブラリもお勧めです。

まずは公式ドキュメンテーションを読みましょう。

https://www.django-rest-framework.org/api-guide/authentication/

settings.pyの設定

ではプロジェクトディレクトリ内のsettings.pyに下記のラインを追加しましょう。

REST_FRAMEWORK = {

    'DEFAULT_AUTHENTICATION_CLASSES': [

        'rest_framework.authentication.BasicAuthentication',

        'rest_framework.authentication.SessionAuthentication',

    ]

}

Views.pyの設定

ここでAiuthenticationに必要なモジュールをインポートします。

from rest_framework.authentication import SessionAuthentication, BasicAuthentication

from rest_framework.permissions import IsAuthenticated

あとは、クラスを貼り付けるだけ!

from .models import Member

from .serializers import MemberSerializer

from rest_framework import viewsets

#これを追加

from rest_framework.authentication import SessionAuthentication, BasicAuthentication

#これを追加

from rest_framework.permissions import IsAuthenticated




class MemberViewSet(viewsets.ReadOnlyModelViewSet):

    #これを追加

    authentication_classes = [SessionAuthentication, BasicAuthentication]

    #これを追加

    permission_classes = [IsAuthenticated]



    queryset = Member.objects.filter(status="Employed")

    # queryset = Member.objects.all()

    serializer_class = MemberSerializer

APIのエンドポイントの確認

では、DjangoのユーザーでログインしていないブラウザでURIにアクセスしましょう。

このように、APIのデータが出力されなくなりましたね。

ここで重要なのが、APIの発信元がHTTPSでないとログイン情報が盗まれることがあるので必ずHttps://を使うようにしましょう。

しかし、これだとDjangoのアドミンパネルからログインしていないとAPIが見れないのでクライアント側では使えなさそうですね。

(※このログインページはカスタマイズできますが次の方法で試してみましょう。)

TokenAuthを使おう

ではAuthのイメージが沸いたところでTokenAuthの設定をしていきます。

settings.pyの設定

では、REST_FRAMEWORKの項目を下記のように更新しましょう。

REST_FRAMEWORK = {

    'DEFAULT_AUTHENTICATION_CLASSES': [

        'rest_framework.authentication.TokenAuthentication'

    ],

    'DEFAULT_PERMISSION_CLASSES': [

        'rest_framework.permissions.IsAuthenticated'

    ]

}

では、Views.pyのAuthも項目は一旦削除しましょう。

で、APIのエンドポイントに行くとデータが見れなくなったことがわかりましたね。

http://127.0.0.1:8000/api/?format=api

このAPIのルートから全てTokenがないとアクセスが制限されます。

ちなみにこれをなくして、viewごとでauth設定をすることもでき、一部のapiだけにauthをかけられます。

Tokenを取得するURLを作成

まずはsettings.pyに下記のtokenアプリを追加します。

INSTALLED_APPS = [

    ...

    'rest_framework.authtoken'

]

ではurls.pyにTokenを作成するURLを作成します。

from rest_framework.authtoken import views




urlpatterns = [

    path('api-token-auth/', views.obtain_auth_token, name='api-token-auth')

]

URLの名前はなんでもよいです。

アプリを登録した後にDBのマイグレーションを忘れないようにしてください。

これでToeknテーブルがアドミンパネルに表示されました。

これでユーザーがログインしたときに生成されるトークンと照らし合わせてアクセス権限を判断できるようになります。

ログイン情報を作成

もし、ログインする情報がない人は先にスーパーユーザーを作っておきましょう。

python manage.py createsuperuser

テストでリクエストを送ってみる

では下記のURLにアクセスしてみます。

http://127.0.0.1:8000/api-token-auth/

下記のようにGETリクエストが拒否されました。

ではログイン情報と一緒にPOSTメソッドでリクエストを送ってみます。

HttpieでURLにPOSTリクエストを送る

では下記のコマンドでテストツールのhttpieをインストールします。

pip instal httpie

で、先ほど作成したapi-token-authのURLにPOSTリクエストを送ります。

http POST http://127.0.0.1:8000/api-token-auth/ username="admin" password="admin"

これでTokenが作成されればOKです。

トークンを使ってAPIにアクセスする

では先ほど作成されたTokenを使ってAPIにアクセスできるか試してみましょう。

http http://127.0.0.1:8000/api/tickets/ “Authorization: Token 330b6d34c6ac24a3606b14495e9311e0681821c2”

問題なくレスポンスがかえってきましたね。

※同じようにHTTPSを使うようにしましょう。

DjangoをPostgreSQLに接続しよう

DjangoアプリをPostgreSQLに接続しよう

PostgreSQLのインストール

では自分が使っているPCにPostgresをインストールしましょう。

本番環境ではUbuntuとかのLinuxのサーバーにPostgresを入れなおすことになりますが、テスト環境として入れておいたら後からコードも書き直さなくてよいので準備しておきます。

Postgresの公式サイト

https://www.postgresql.org/

インストールはここから

https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

この際にDB名とユーザー名、そのPWを保管しておきましょう。

 psycopg2のインストール

ではDjangoがPostgreSQLのデータベースとコミュニケーションを取るためのアダプターをインストールします。

pip install psycopg2

https://github.com/psycopg/psycopg2

Settings.pyの設定

ではSSQLiteの設定をコメントアウトして下記の用に設定していきます。

DATABASES = {

   'default': {

       'ENGINE': 'django.db.backends.postgresql',

       'NAME': '<database_name>',

       'USER': '<database_username>',

       'PASSWORD': '<password>',

       'HOST': '<database_hostname_or_ip>',

       'PORT': '<database_port>',

   }

}

あとはいつも通りにDBのマイグレーションを行います。

python manage.py makemigrations

python manage.py migrate

python manage.py createsuperuser

http://127.0.0.1:8000/admin/

Django REST API COR Headersの使い方

Django CORSとは

Django CORSはホスト側のAPIリソースを取り扱う、そしてセキュリティのメカニズムのことです。

このCORSが設定されていないと、アプリからDjangoAPIとコミュニケーションをしようとしてもエラーになってしまいます。

CORSをインストール

python -m pip install django-cors-headers

Settings,.pyの更新

INSTALLED_APPS = [

...

'corsheaders',

...

]

ミドルウェアの更新

ここで注意したいのはCORSのラインが他のミドルウェアよりも先(上)に来るようにします。

MIDDLEWARE = [

...,

'corsheaders.middleware.CorsMiddleware',

'django.middleware.common.CommonMiddleware',

...,

]

Allowed Originの設定

CORS_ALLOWED_ORIGINS = [

"https://domain.com",

"https://api.domain.com",

"http://localhost:8080",

"http://127.0.0.1:9000"

]

CORS_ALLOW_METHODS

必要に応じてHTTPのリクエストのメソッドも制限できます。

CORS_ALLOW_METHODS = [

'DELETE',

'GET',

'OPTIONS',

'PATCH',

'POST',

'PUT',

]

CORS_ALLOW_HEADERS

これも必要に応じてHTTPリクエストのヘッダーを制限できます。

CORS_ALLOW_HEADERS = [

'accept',

'accept-encoding',

'authorization',

'content-type',

'dnt',

'origin',

'user-agent',

'x-csrftoken',

'x-requested-with',

]

Django API ViewsetとForeginKeyの使い方

必要な環境

・Python 3

・pip

・git(※無くても良い)

イントロ

前回はPythonのフレームワークDjangoとDjango Rest Frameworkを使ってクラスベースとファンクションベースのView(views.py)でAPIを作りました。

前回カバーしたのはHTTPのGETリクエストに対してのレスポンスとしてデータを出力しただけです。

まずは、主なHTTPのリクエストを簡単に紹介します。

GETリクエスト➡データ取得

POSTリクエスト➡フォームのサブミット、ログイン、記事の投稿など

PUT➡データの更新、書き換え

DELETE➡既存のデータの削除

詳しくはこちらを参考にしてください。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods

では、前回やったAPIViewでも同じようにそれぞれのHTTPでリクエストが来たときにどうやってDjango側がリクエストを扱うかコードで指示できます。

詳しくはこちらを参照。

https://www.django-rest-framework.org/api-guide/views/

しかし、DjangoのREST Frameworkでviewsetという全部のリクエストをカバーしたメソッドがあるのでそれを今日紹介していきます。

環境の設定

まずは下記のGitHubリポジトリからコードをダウンロードしてください。

https://github.com/TraitOtaku/djangoAPI.git

Gitを使ったことがない人はZIPファイルでもダンロードできます。

ではGitのコマンドです。

cdでファイルを作成したい所に行き、

git clone -b 2_Viewset https://github.com/TraitOtaku/djangoAPI.git

で、virtualenvが入っていない人はグローバルに入れます。

pip install virtualenv
virutalenv ENV

ENV\Scripts\activate.bat

(ENV)でアクティベートされていることを確認して、requirements.txtnのパッケージを全部インストールします。

pip install -r requirements.txt

pip list
python manage.py makemigrations

python manage.py migrate

​​​​​​​python manage.py createsuperuser

VSCodeを使っている人はこれでテキストエディタを開きましょう。

code .

python manage.py runserver

コンセプトの紹介

まずは、今日使用するアプリの例を紹介します。例として、コールセンターをイメージしましょう。

この画像のように、Djangoで3つアプリを別々に作成しました。

1.会社で従業員を管理するmembers app

2.顧客を管理するcustomers app

3.顧客からの問い合わせを管理するTicket app

Djangoの良いところはこのアプリを連携されてスケーリングが簡単にできることです。

ではこのアプリがどのように連携されるかデータベースのモデルを見てみましょう。

モデルの理解

members.models.py

従業員のデータモデルです。

Customers.models.py

顧客情報のモデルです。

Tickets.models.py

チケットのモデルです。

ForeignKeyで他のモデルのデータを参照していることに注目してください。

アドミンパネルでサンプルデータを作成

ではアドミンパネルで適当にデータを作成します。

データベースの中身を見る

では、DB Browserという無料のソフトウェアを使ってデータベースの中身を見てみましょう。

TicketのテーブルのForeignKeyで他のテーブルのIDを参照していることに注目してください。

ツールはここからダウンロードできます。

https://sqlitebrowser.org/

Serializerを見る

特に重要なのがこのForeingKeyをどうやってAPIで出力するかです。

もし、Readオンリーであればソース源をそのまま出力できますが、

CRUDオペレーションをしたい場合、(データの作成、読み込み、更新、削除)ちょっとした工夫が必要になりそうです。

Views.pyを見る

ここで今日の本題のviewsetの紹介に入ります。ViewsetはこのCRUDで使うAPIを全部セットで使えるようになった便利なメソッドの事です。これを使うことでいちいちGET、PUT、DELETE、POSTのコードを書かなくても良いようにあります。

もちろん、カスタマイズが必要な場日は、コードを上書きすることもできます。

では、viewsetを見てみます。

今回のアプリでは、membersとcustomersは会社のマネージャーがDjangoのアドミンパネル(サーバー側)から編集すると考えます。

それで、従業員がブラウザ上でチケットを管理するような流れです。

なので、membersとcustomersのデーターはReadOnlyModelViewSetはGETメソッドだけ用に絞ってクライアント側ではリードオンリーのデータした提供されません。

Router.pyを見る

今までのDjangoアプリはurls.pyでURLをそれぞれのアプリから提供していました。APIもこのやり方でも良いのですが、どんどなプリが増えてくるとどのURL(URI)がAPI化されているか煩雑になります。

そこで、プロジェクト側のディレクトリにrouter.pyファイルを作成してAPIのエンドポイントを一つにまとめます。このファイルはプロジェクト側のurls.pyから呼び出されていることを忘れずに。

APIを見てみよう。

では実際に提供されたAPIでCRUD操作ができるか試してみましょう。

次回

では、これで、従業員がAPIを使ってブラウザ側からDjangoアプリにデータをやり取りすることができました。しかし、このままだとAPIが垂れ流しでURL(URI)にアクセスで切る人が誰でもデータをみたり編集できてしましますね。

ですので次回はAuthentication(認証、ログイン)システムを使ってAPIのセキュリティ強化をしてみたいと思います。

ではお疲れさまでした。