見出し画像

Django/REST frameworkプロジェクトの作成


1.環境設定

1.1 LNMPインストール 

1.2 Conda インストール 

システムに応じて、必要なバージョンをインストール

Linuxの場合

sudo wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh
bash ./Anaconda3-2024.06-1-Linux-x86_64.sh -b

もし「conda: command not found」が出ったら、Anaconda がインストールされているようだが、conda コマンドが環境変数で正しく構成されていないからだ。

cd anaconda3
sudo vim  .bashrc

ファイルの末尾に次の行を追加する (Anaconda が ~/anaconda3 にインストールされていると仮定)。

export PATH="$HOME/anaconda3/bin:$PATH"

シェルを更新する

source ~/.bashrc
conda init
conda --version

1.3 環境作成

  • Conda アップデート

conda update conda
  • 環境作成

conda create --name env_name python=3.12
  • 環境削除

conda remove --name env_name --all
  • 環境アクティベート

conda activate env_name
python --version
  • 環境ディアクティベート

conda deactivate
  • 環境確認

conda info --envs
conda env list
  • パッケージ確認

conda list
  • パッケージ検索

conda search package_name
  • パッケージ インストール

conda install package_name
  • パッケージ アップデート

conda update package_name
  • パッケージ 削除

conda remove package_name
  • 環境導出

conda env export > environment.yml
  • 環境導入

conda env create -f environment.yml
  • パッケージの依存関係確認

conda list --show-channel-urls

1.4 Django インストール

conda install django 
# or
pip install django

2.プロジェクト作成

django-admin startproject <projectname>

任意のIDEで作成したプロジェクトを開き、実行させてみると、ポートは8000で、ホストは127.0.0.1

3.タイムゾーンと言語を変更

settings.pyにおいて、「LANGUAGE_CODE」及び「TIME_ZONE」に対し

# 英語
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'

# 中国語
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'

# 日本語
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'

4.インポートパッケージのパスを追加

django_app/django_appにおいて、「apps」というディレクトリを作成し、それをMark Directory as  Sources Root

次に、settings.pyにおいて、インポート パッケージのパスを追加し、アプリケーションのルート ディレクトリとして「apps」を使用

import sys
sys.path.insert(0, os.path.join(BASE_DIR, 'django_app/apps'))

5.ログ

settings.pyに次の設定を記述し、ルート ディレクトリにログ ストレージとして 「logs」 フォルダーを作成

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # 既存のロガーを無効にするかどうか 是否禁用已经存在的日志器
    'formatters': {  # ログ情報の表示形式 日志信息显示的格式
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {  # ログのフィルタリング 对日志进行过滤
        'require_debug_true': {  # Django はデバッグモードでのみログを出力 django在debug模式下才输出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {  # ログ処理方法 日志处理方法
        'console': {  # ターミナルにログを出力 向终端中输出日志
            'level': 'DEBUG',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {  # ログをファイルに出力 向文件中输出日志
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(BASE_DIR, "logs/api.log"),  # ログファイルの場所 日志文件的位置
            'maxBytes': 300 * 1024 * 1024,
            'backupCount': 10,
            'formatter': 'verbose'
        },
    },
    'loggers': {  # ロガー 日志器
        'django': {  # django という名前のロガーを定義 定义了一个名为django的日志器
            'handlers': ['console', 'file'],  # ログを端末とファイルに同時に出力可能 可以同时向终端与文件中输出日志
            'propagate': True,  # ログ情報の送信を継続するかどうか 是否继续传递日志信息
            'level': 'INFO',  # ロガーが受信する最小ログレベル 日志器接收的最低日志级别
        },
    }
}

6.Rest Framework インストール

  • Rest Framework インストール

pip install djangorestframework

settings.pyのINSTALLED_APPSにおて、

INSTALLED_APPS = [
    ...

    'rest_framework',
]

7. Mysql インストール

既にLNMP用意できたら、「7」をスキップ

7.1 MacOS インストール

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
brew --version

brew install mysql
mysql --version
brew services start mysql
brew services restart mysql
brew services stop mysql
mysql_secure_installation
mysql -u root

7.2 Ubantu インストール

sudo apt update
sudo apt install mysql-server mysql-client 
sudo start mysql
sudo stop mysql
sudo mysql_secure_installation 

パスワードの初期化時にエラーが報告された場合は、手動でパスワードを設定してください。

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password by '<password>';

8.Mysql ドライバーをインストール

pip install pymysql

8.1 ドライバー導入

ルート ディレクトリの __init__.py にドライバー仕様をインポート

import pymysql

pymysql.install_as_MySQLdb()

8.2 データベース作成

create database <name>; # 作成
drop database <name>; # 削除

8.3 Mysql 設定変更

settings.pyにおいて、「DATABASES」を次のように変更、「sqlite」を「mysql」へ変更

# pip install pymysql 
DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.mysql',
    'HOST': '127.0.0.1',  # ホスト
    'PORT': 3306,  # ポート
    'USER': 'root',  # ユーザー
    'PASSWORD': 'password',  # パスワード
    'NAME': 'database_name'# データベース名
    }
}

8.4 アクセス テスト

先ほど自動生成した「db.sqlite3」はもう必要ないので、削除する。

9.Redis インストール

9.1 MacOS インストール

  • Homebrew を使用して Redis をインストール

brew install redis
  • Redis サービスを開始

brew services start redis
  • Redis が正常にインストールされているかどうかを確認

redis-cli ping

PONGが返された場合は、Redis が正常にインストールされたことを意味する

  • Redis サービスを停止

brew services stop redis

9.2 Ubantu インストール

  • Redis インストール

sudo apt install redis-server 
  • Redis テスト

redis-cli # 测试
sudo systemctl status redis 
  • すべてのデータを表示する

keys*

9.3 Redisドライバーをインストール

pip install django-redis

9.4 Redis 設定変更

settings.pyにおいて、「CACHES」を追加

CACHES = {
    "default": {
            "BACKEND": "django_redis.cache.RedisCache", 
            "LOCATION": "redis://127.0.0.1:6379/0",
            "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}},
            "session": {
                    "BACKEND": "django_redis.cache.RedisCache",
                    "LOCATION": "redis://127.0.0.1:6379/1",
                    "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}
                    }
    }
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

10.アプリ作成

Django では、アプリケーションは、特定のビジネス ロジックを実装するために使用される関連関数のコレクション。各アプリケーションには、複数のモデル、ビュー、テンプレート、およびその他の必要なファイルを含めることができる

cd django_app/django_app/apps
python ../../manage.py startapp yourapp

作成したappをインストールしなくちゃいけない

INSTALLED_APPS = [
    'rest_framework',
    'yourapp.apps.YourappConfig'
]

11.CORSクロスドメインホワイトリスト

CORS は、Cross-Origin Resource Sharing の略語で、ブラウザーが異なるオリジン (ドメイン、プロトコル、またはポート) のサーバーに対してクロスドメイン リクエストを開始できるようにする。 Django で CORS を使用するには、django-cors-headers パッケージをインストールする必要がある。 django-cors-headers を使用して CORS を実装する手順は次のとおり。

11.1 django-cors-headers インストール

pip install django-cors-headers

11.2 Django プロジェクトの settings.py に corsheaders アプリを追加

INSTALLED_APPS = [
    'corsheaders',
]

11.3 corsheaders.middleware.CorsMiddleware を MIDDLEWARE に追加

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

11.4 settings.py で CORS_ORIGIN_ALLOW_ALL を True に設定するか、アクセスを許可するソースを指定

# アクセスを許可するソースを指定 指定允许访问的源
CORS_ORIGIN_WHITELIST = (
    'http://127.0.0.1',
    'http://localhost',
    '...',
    '...'
)
# Cookie を許可 允许携带cookie
CORS_ALLOW_CREDENTIALS = True  

# すべてのソースを許可 允许所有源
CORS_ORIGIN_ALLOW_ALL = True

11.5 views.py では、django-cors-headers によって提供される @cors_headers.allow_cors を使用して、クロスドメイン アクセスを許可するビュー関数をマークで。

from corsheaders.decorators import cors_headers

@cors_headers.allow_cors(methods=['GET'])
def my_view(request):
    ...

または、view 関数で応答の CORS ヘッダー情報を直接設定

from django.http import JsonResponse

def my_view(request):
    response = JsonResponse({'foo': 'bar'})
    response['Access-Control-Allow-Origin'] = '*'
    return response

上記の手順により、Django で django-cors-headers を使用してクロスドメイン アクセスを実現できる。

12. データベース 移行

Django のデータベース 移行は、アプリケーションの開発中にデータベース スキーマを簡単に変更できるメカニズム。Django の移行を使用すると、データベース テーブル構造を手動で変更しなくても、モデルの定義を簡単に変更できる。

12.1 makemigrations

モデルを定義したら、データベース テーブル構造の変更方法を Django に指示するマイグレーションを作成する必要がある。ターミナルで次のコマンドを実行してマイグレーションを作成する。

python ../../manage.py makemigrations

12.2 migrate

マイグレーションを作成したら、データベースに適用できる。ターミナルで次のコマンドを実行して、移行を適用する。

python ../../manage.py migrate

13.admin サイト

Django SimpleUI は、Bootstrap に基づくオープン ソースのバックエンド管理インターフェイス フレームワークであり、Django 開発者が美しい管理インターフェイスを迅速に構築するのに役立つ。

13.1 スーパーアドミニストレーター作成

「12. データベース 移行」を行わないと、スーパーアドミニストレーターを作成するのはできない

python ../../manage.py createsuperuser

プロンプトに従って、スーパーアドミニストレーターのユーザー名、電子メール、およびパスワードを入力する。例:

Username: admin
Email address: admin@example.com
Password:
Password (again):

入力が完了し、すべてがうまくいけば、次の出力が表示される。

Superuser created successfully.

Django スーパーアドミニストレーターアカウントが正常に作成されたので、このアカウントを使用して Django 管理バックエンドにログインできる。

13.2 simpleui インストール

pip install django-simpleui

SimpleUI アプリケーションを追加し、Django プロジェクトの settings.pyで静的ファイルを有効にして、ルート ディレクトリーで「static」ディレクトリーを作成する。

INSTALLED_APPS = [
    'simpleui',
    ...
    ...
]

# 静的ファイルを有効にする 启用静态文件
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

SimpleUI アプリケーションを「INSTALLED_APPS」リストの先頭に追加する必要があり、静的ファイル ディレクトリの場所を指定するように「STATICFILES_DIRS」オプションを設定する必要がある。

13.3 Common Configuration

  • Language

「3.タイムゾーンと言語を変更」と同様に

# 英語
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'

# 中国語
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'

# 日本語
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'

13.4 Theme

SimpleUI にはさまざまなテーマが用意されており、ニーズに合ったものを選択できる。たとえば、settings.py に次の設定を追加して、ダーク テーマを使用できる。

SIMPLEUI_THEME = 'dark'
SIMPLEUI_DEFAULT_THEME = 'purple.css'
SIMPLEUI_DEFAULT_THEME = 'admin.lte.css'

13.5 Menu

SimpleUI には、必要に応じてメニュー項目を追加、編集、削除するための構成可能なメニュー項目が用意されている。例:

import time
SIMPLEUI_CONFIG = {
    'system_keep': False,
    'menu_display': ['Simpleui', '测试', '权限认证', '动态菜单测试'],      # 开启排序和过滤功能, 不填此字段为默认排序和全部显示, 空列表[] 为全部不显示.
    'dynamic': True,    # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容
    'menus': [{
        'name': 'Simpleui',
        'icon': 'fas fa-code',
        'url': 'https://gitee.com/tompeppa/simpleui',
        # 浏览器新标签中打开
        'newTab': True,
    }, {
        'app': 'auth',
        'name': '权限认证',
        'icon': 'fas fa-user-shield',
        'models': [{
            'name': '用户',
            'icon': 'fa fa-user',
            'url': 'auth/user/'
        }]
    }, {
        # 自2021.02.01+ 支持多级菜单,models 为子菜单名
        'name': '多级菜单测试',
        'icon': 'fa fa-file',
      	# 二级菜单
        'models': [{
            'name': 'Baidu',
            'icon': 'far fa-surprise',
            # 第三级菜单 ,
            'models': [
                {
                  'name': '爱奇艺',
                  'url': 'https://www.iqiyi.com/dianshiju/'
                  # 第四级就不支持了,element只支持了3级
                }, {
                    'name': '百度问答',
                    'icon': 'far fa-surprise',
                    'url': 'https://zhidao.baidu.com/'
                }
            ]
        }, {
            'name': '内网穿透',
            'url': 'https://www.wezoz.com',
            'icon': 'fab fa-github'
        }]
    }, {
        'name': '动态菜单测试' ,
        'icon': 'fa fa-desktop',
        'models': [{
            'name': time.time(),
            'url': 'http://baidu.com',
            'icon': 'far fa-surprise'
        }]
    }]
}

13.6  Logo Image

settings.pyで「SIMPLEUI_LOGO」を指定

SIMPLEUI_LOGO = 'logo_url' 

13.7 Icon

14.例外処理

14.1 exceptions.py

Django プロジェクトのルートに utils というフォルダーを作成し、そのフォルダー内に exceptions.py というファイルを作成する。

import logging
from django.core.exceptions import ValidationError, PermissionDenied
from django.db import DatabaseError
from redis.exceptions import RedisError
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from rest_framework import status
from rest_framework.exceptions import NotAuthenticated, AuthenticationFailed

# 获取在配置文件中定义的logger,用来记录日志
logger = logging.getLogger('django')

def custom_exception_handler(exc, context):
    """
    自定义异常处理
    :param exc: 异常
    :param context: 抛出异常的上下文
    :return: Response响应对象
    """
    # 调用drf框架原生的异常处理方法
    response = drf_exception_handler(exc, context)

    # 如果response为空,则意味着异常不是由REST framework处理的
    if response is None:
        view = context['view']
        if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
            # 数据库异常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
        elif isinstance(exc, ValidationError):
            # 验证异常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': '数据验证错误', 'detail': str(exc)}, status=status.HTTP_400_BAD_REQUEST)
        elif isinstance(exc, PermissionDenied):
            # 权限拒绝异常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': '权限不足'}, status=status.HTTP_403_FORBIDDEN)
        elif isinstance(exc, NotAuthenticated) or isinstance(exc, AuthenticationFailed):
            # 认证异常
            logger.error('[%s] %s' % (view, exc))
            response = Response({'message': '认证失败'}, status=status.HTTP_401_UNAUTHORIZED)
        else:
            # 处理其他未捕获的异常
            logger.error('[%s] %s' % (view, exc))
            response = Response({
                'detail': 'An unexpected error occurred.',
                'message': str(exc)
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    else:
        # 在这里可以自定义返回的内容
        if response.status_code == 404:
            response.data = {
                'detail': 'Resource not found.',
                'message': str(exc)
            }

        if response.status_code == 500:
            response.data = {
                'detail': 'A server error occurred.',
                'message': str(exc)
            }

    return response

14.2 settings.py

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'utils.exceptions.custom_exception_handler'
}

これらの手順を通じて、統合されたカスタム例外ハンドラーは、データベース、Redis、検証、アクセス許可の拒否、認証などの一般的な例外を処理および記録できるようになり、キャッチされなかった例外に対してわかりやすい応答情報を提供できるようになる。ニーズに応じて、例外処理ロジックをさらに拡張およびカスタマイズできる。

15.AbstractUser

AbstractUser は、Django フレームワークでユーザー モデルを作成するために使用される基本クラス。これは django.contrib.auth.models モジュールの一部であり、ユーザー認証システムの基本的な構造と機能を提供している。 AbstractUser クラスを継承すると、ユーザー名、パスワード、電子メール、電話番号などのフィールドを含むユーザー モデルをニーズに応じてカスタマイズできる。

apps % python ../../manage.py startapp users

INSTALLED_APPS = [
    'users.apps.UsersConfig'
]

apps/users/Model.pyにおいて、

class User(AbstractUser):
    Male = '男'
    Female = '女'
    GENDER_CHOICES = [
        (Male, '男'),
        (Female, '女'),
    ]
    gender = models.CharField(verbose_name='性別', max_length=1, choices=GENDER_CHOICES, default=Male, blank=False, null=False, help_text='必須')
    date_of_birth = models.DateField(verbose_name='生日', blank=False, null=False, help_text='必須')

    class Meta:
        db_table = 'tb_users'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

上の例では、AbstractUser クラスから継承した User というカスタム ユーザー モデルを作成した。

カスタム ユーザー モデルを使用するには、Django プロジェクトの settings.py ファイルでそれを適切に構成する必要がある。 「AUTH_USER_MODEL」設定でカスタム ユーザー モデルを指定する。

AUTH_USER_MODEL = 'users.User'

上記のコード用意できたら、ターミナルで、データベース移行を行う。

 python ../../manage.py makemigrations

もし「RuntimeError: 'cryptography' package is required for sha256_password or caching_sha2_password auth methods」が現れたら、

pip install cryptography
 python ../../manage.py migrate    



この記事が気に入ったらサポートをしてみませんか?