🐥

Djangoにおけるmodel,viewの役割

2024/05/29に公開

はじめに

仕事でC#を使って開発をしていることもあり、DjangoにおけるMVC(実際にはMVT)はどのような構造となっていて、どのようにデータがクライアントに返されるかについて触れた記事になります。
また、記事で触れているコードは以下の記事で作成したAPIのものを使用しています。
https://zenn.dev/nihiru/articles/47bb11c1282ab5
様々な言語を扱う上でこの考えは非常に大事だと思いますし、言語モデルを体系的に理解することで本質を理解することにも繋がると思うので、記事にしてみました。

全体の構造

通常、Djangoプロジェクトは以下の構造を持ちます。

book_management/
    ├── book_management/
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   ├── asgi.py
    │   └── wsgi.py
    ├── books/
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── serializers.py
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    └── manage.py

C#のASP.NET MVCのディレクトリ構造は以下の構造を持ちます。

MyMvcApp/
    ├── Controllers/
    │   ├── HomeController.cs
    ├── Models/
    │   ├── Book.cs
    ├── Views/
    │   ├── Home/
    │       ├── Index.cshtml
    ├── appsettings.json
    ├── Program.cs
    ├── Startup.cs

モデル

モデルはデータベースのテーブル構造を定義します。DjangoとASP.NET MVCのモデル定義の違いを見てみましょう。
■Djangoのモデル

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    published_year = models.IntegerField()

    def __str__(self):
        return self.title

Django: モデルはmodels.Modelを継承して定義します。フィールドはDjangoのフィールドクラスを使用して定義します。
■ASP.NET MVCのモデル

using System.ComponentModel.DataAnnotations;

public class Book
{
    public int Id { get; set; }

    [StringLength(100)]
    public string Title { get; set; }

    [StringLength(100)]
    public string Author { get; set; }

    public int PublishedYear { get; set; }
}

ASP.NET MVC: モデルは単なるC#クラスとして定義され、データ注釈属性を使用してバリデーションや制約を指定します。

シリアライザー(Django)とViewModel(ASP.NET MVC)

Djangoでは、シリアライザーを使用してモデルインスタンスをJSONなどのフォーマットに変換します。ASP.NET MVCでは、ViewModelを使用してビューに渡すデータを整形します。
■Djangoのシリアライザー

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

Django: シリアライザーはDjango REST frameworkのserializers.ModelSerializerを継承して定義します。シリアライザーはモデルと連携し、データのシリアル化とデシリアル化を行います。
■ASP.NET MVCのViewModel

public class BookViewModel
{
    public int Id { get; set; }

    [StringLength(100)]
    public string Title { get; set; }

    [StringLength(100)]
    public string Author { get; set; }

    public int PublishedYear { get; set; }
}

ASP.NET MVC: ViewModelは単なるC#クラスとして定義され、必要に応じてデータ注釈属性を使用します。ViewModelは、コントローラからビューにデータを渡すために使用されます。

ビュー

Djangoのビューはリクエストを処理し、適切なレスポンスを返します。ASP.NET MVCのコントローラと同様の役割を果たします。
■Djangoのビュー

from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

Django: ビューはDjango REST frameworkのviewsets.ModelViewSetを継承し、CRUD操作を提供します。querysetとserializer_classを定義します。
■ASP.NET MVCのコントローラ

using Microsoft.AspNetCore.Mvc;

public class BooksController : Controller
{
    public IActionResult Index()
    {
        var books = GetBooksFromDatabase();
        return View(books);
    }

    public IActionResult Create(BookViewModel model)
    {
        if (ModelState.IsValid)
        {
            SaveBookToDatabase(model);
            return RedirectToAction("Index");
        }
        return View(model);
    }
}

ASP.NET MVC: コントローラはControllerを継承し、アクションメソッドを定義します。アクションメソッドはリクエストを処理し、ビューを返します。

URLルーティング

DjangoのURLルーティングとASP.NET MVCのルーティングは、リクエストURLを対応するビューまたはコントローラにマッピングします。
■DjangoのURLルーティング

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BookViewSet

router = DefaultRouter()
router.register(r'books', BookViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

Django: urls.pyでルートを定義し、ルーターを使用してビューセットを登録します。
■ASP.NET MVCのルーティン

public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

ASP.NET MVC: Startup.csでルートを定義し、コントローラとアクションを指定します。

処理フロー

DjangoとASP.NET MVCの処理の流れは以下の通りです。
1.リクエスト:クライアントがリクエストを送信。
2.URLルーティング:ルーティングがリクエストを対応するビューまたはコントローラにディスパッチ。
3.ビュー/コントローラ:ビューまたはコントローラがリクエストを処理し、必要なデータを取得。
4.シリアライザー/ViewModel:データをシリアライザーまたはViewModelを使用して整形。
5.レスポンス:整形されたデータがレスポンスとしてクライアントに返される。

以下の図は、DjangoとASP.NET MVCの処理の流れを比較したものです。

Django:
  +-----------------------+
  |    Client (Browser)   |
  +-----------+-----------+
              |
              v
  +-----------+-----------+
  |   URL Routing (urls.py)|
  +-----------+-----------+
              |
              v
  +-----------+-----------+
  |    View (views.py)    |
  +-----------+-----------+
              |
              v
  +-----------+-----------+
  |  Serializer (serializers.py) |
  +-----------+-----------+
              |
              v
  +-----------+-----------+
  |    Model (models.py)  |
  +-----------------------+

ASP.NET MVC:
  +-----------------------+
  |    Client (Browser)   |
  +-----------+-----------+
              |
              v
  +-----------+-----------+
  |   URL Routing (Startup.cs)|
  +-----------+-----------+
              |
              v
  +-----------+-----------+
  |  Controller (BooksController.cs) |
  +-----------+-----------+
              |
              v
  +-----------+-----------+
  |  ViewModel (BookViewModel.cs) |
  +-----------+-----------+
              |
              v
  +-----------+-----------+
  |    Model (Book.cs)    |
  +-----------------------+

まとめ

DjangoとASP.NET MVCの両方でリクエストがどのように処理されるかについてまとめてみました。
大きな違いとしては、Controllerとしての役割がDjangoではViewに値することでしょうか。他にも細かい違いはたくさんありそうですが、沼にはまりそうなので今回はここまでにします。

Discussion