使用Django REST Framework + Vue以异步方式获取并显示与所选择标签相关的帖子
触发
我认为通过获取和显示仅需要的数据,而无需进行页面转换更加智能。在Github上查看代码。
开发环境
- 
- Python 3.7.3
 
- 
- Django 3.0.5
 
- 
- Django REST Framework 3.11.0
 
- 
- Vue.js 2.6.11 (CDN)
 
- Axios 0.19.2 (CDN)
※Django会采用基于类的方法进行开发。
先从准备开始。
1. 进入适当的位置创建的虚拟环境。(由于每个环境的命令不同,暂不提供)
2. 安装所需的库。
pip install django
pip install djangorestframework
创建一个Django项目。
# 適当な場所にプロジェクト用ディレクトリを作成
mkdir your_project_name
# 作成したディレクトリに移動し以下のコマンドを打つ
django-admin startproject config .
# 作成されるプロジェクトの中身
└── your_project_name
    │
    ├── config
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    │
    └── manage.py
通过下面的命令,可以将设置目录名称与项目名称分开。
django-admin startproject config .
假设你在命令行中正常地输入了django-admin startproject your_project_name。
# 作成されるプロジェクトの中身
└── your_project_name  # ここと
    │
    ├── your_project_name  # ここが一緒の名前になるのでややこしい
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    │
    └── manage.py
创建Tags应用程序。
# manage.py があるディレクトリまで移動
# 移動したら以下のコマンドを打つ
python manage.py startapp tags
# プロジェクトの中身
└── your_project_name
    │
    ├── config
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    │
    ├── tags  # 新しく作成したTagsアプリ
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    │
    └── manage.py
将Tags应用程序添加到配置文件中。
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'tags.apps.TagsConfig',  # ここにTagsアプリを登録
    'rest_framework',  # 最初にインストールしたdjango-rest-frameworkも一緒に登録
]
...
现在开始开发(与普通的Django应用开发没有任何区别)。
1.建立Tag模型
from django.db import models
class Tag(models.Model):
    """タグモデル"""
    name = models.CharField(max_length=10)  # 名前フィールドを追加(最大文字数10文字)
    def __str__(self):  # 管理画面上で各オブジェクトの識別をし易くするための設定
        return self.name  # オブジェクト自身の名前フィールドの値を返すように設定
接下来,使用命令创建迁移文件,并通过迁移将其反映到数据库中。
python manage.py makemigrations
python manage.py migrate
最后,将创建的标签模型注册到管理网站中。
from django.contrib import admin
from .models import Tag
admin.site.register(Tag)
2. 添加视图
from django.views import generic
from .models import Tag
class IndexView(generic.ListView):  # 一覧表示に特化したViewを作成
    model = Tag
    template_name = 'index.html'
创建模板
cd tags  # Tagアプリのディレクトリに移動
mkdir templates
# プロジェクトの中身
└── your_project_name
    │
    ├── config
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    │
    ├── tags
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── templates  # 新しくTemplate用のディレクトリを作成
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    │
    └── manage.py
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Index</title>
</head>
<body>
  {% for tag in tag_list %}
    <p>{{ tag.name }}</p>
  {% endfor %}
</body>
</html>
首先,我已经使用for循环列出了Tag对象的名称。
现在,让我们立即登录管理界面并尝试添加标签。
创建管理员账号以登录管理界面,然后添加标签。
python manage.py createsuperuser
ユーザー名:
パスワード:
尽管公式文档强烈推荐首先创建自定义用户模型,但由于此次仅为试验性开发,我们将省略此步骤。
创建管理员账户后,输入命令启动服务器。
python manage.py runserver
如果服务器成功启动,请从http:// 127.0.0.1:8000/admin 访问管理界面,并尝试添加标签。
添加常规事务
from django.contrib import admin
from django.urls import path, include  # includeを追加でインポート
urlpatterns = [
    path('admin/', admin.site.urls),  # 管理サイトへのルーティン
    path('', include('tags.urls')),  # トップページアクセスでTagsアプリに飛ぶように設定
]
接下来,在Tags应用程序内,新建一个urls.py文件。
from django.urls import path
from . import views  # 同ディレクトリからViews.pyをインポート
app_name = 'tags'  # アプリ識別用の名前を設定(オプション)
urlpatterns = [
    path('', views.IndexView.as_view(), name="index"),  # 先ほど追加したIndexViewを指定
]
通过连接到http://127.0.0.1:8000,应该能够在先前的管理站点中添加的标签以列表形式显示出来。
终于开始使用 REST 框架进行开发
创建Posts应用程序
python manage.py startapp posts
# プロジェクトの中身
└── your_project_name
    │
    ├── config
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    │
    ├── posts  # 新しく作成したPostsアプリ
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    │
    ├── tags
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── templates
    │   │   └── index.html
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   ├── urls.py
    │   └── views.py
    │
    └── manage.py
将新建的Posts应用程序添加到配置文件中注册。
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'tags.apps.TagsConfig',
    'posts.apps.PostsConfig'  # ここにPostsアプリを登録
    'rest_framework',
]
...
创建一个名为“Post”的模型
from django.db import models
from tags.models import Tag  # Tagモデルをインポート
class Post(models.Model):
    """投稿モデル"""
    body = models.TextField(max_length=150)
    tag = models.ForeignKey(Tag, on_delete=models.PROTECT)  # Tagモデルとのリレーション設定
    created_at = models.DateTimeField(auto_now_add=True)  # 作成日時を自動追加するよう設定
    updated_at = models.DateTimeField(auto_now=True)  # 更新されたら日時を更新するよう設定
输入指令
python manage.py makemigrations
python manage.py migrate
注册进管理网站
from django.contrib import admin
from .models import Post
admin.site.register(Post)
添加序列化器
从这里开始,与常规的Django应用程序开发有些不同。
这个名为Serializers的文件是用来将Django的模型对象转换为Json格式的工具。
既然一开始就没有准备好,那么我们在Posts应用程序内新建一个serializes.py文件吧。
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('body', )  # Json形式に変換させたいフィールドを追加
增加视图
from rest_framework import generics
from .models import Post
from .serializers import PostSerializer  # 先ほど作成したシリアライザをインポート
class PostAPIView(generics.ListAPIView):
    serializer_class = PostSerializer  # シリアライザを指定
    queryset = Post.objects.all()  # Postモデルの全オブジェクトをVue.jsに渡すよう設定
增加日常事务的部分
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('tags.urls')),
    path('api/', include('posts.urls')),  # api/ アクセス時にPostsアプリに飛ぶように設定
]
接下来,在Posts应用程序内创建一个新的urls.py文件。
from django.urls import path
from . import views
urlpatterns = [
    path('', views.PostAPIView.as_view()),  # 先ほど作成したPostAPIViewを指定
]
当连接到http://127.0.0.1:8000/api时,Django REST Framework会自动将收到的JSON格式数据转换为Post模型对象,并以列表形式呈现。这些模板是Django REST Framework最初就提供的。
让我们立即实现标题中所写的功能吧!
1.日程的修改
from django.urls import path
from . import views
urlpatterns = [
    path('<int:tag>/', views.PostAPIView.as_view()),  # TagモデルのIDをパラメータで受け取るように変更
]
2.编辑视图
from rest_framework import generics
from .models import Post
from .serializers import PostSerializer
class PostAPIView(generics.ListAPIView):
    serializer_class = PostSerializer
    # queryset = Post.objects.all() を以下に変更
    def get_queryset(self):
        tag = self.kwargs['tag']  # 渡されたパラメータの値をtagに代入
        if tag == 0:  # tagで条件分岐
            # order_by('-created_at') で最新の投稿順に配列に格納されるように設定
            queryset = Post.objects.all().order_by('-created_at')
        else:
            queryset = Post.objects.filter(tag=tag).order_by('-created_at')
        return queryset
3.编辑模板
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Index</title>
  <!-- CDNでVue.jsとAxiosをインポート -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
  <!-- タグをセレクトタグで表示 -->
  <select v-model="tag">
    <option value="0">全てのポスト</option>
    {% for tag in tag_list %}
      <option value="{{ tag.id }}">{{ tag.name }}に関するポスト</option>
    {% endfor %}
  </select>
  <!-- 選択したタグに関連する投稿を表示 -->
  <div v-if="posts">
    <p v-for="post in posts">[[ post.body ]]</p>
  </div>
</div>
<script>
  new Vue({
    el: '#app',
    data: {
      tag: null,
      posts: null,
    },
    watch: {
      // 選択されたタグのIDをパラメータに追加し、APIにリクエスト
      tag: function() {
        if (this.tag) {
          getUrl = 'api/' + this.tag + '/'
          // 返ってきたデータをthis.postsに代入
          axios.get(getUrl).then(res => (this.posts = res.data))
        }
      },
    },
    // Vueデフォルトの "{{ }}" ではDjangoのそれと被ってしまい
    // うまく識別されないので "[[ ]]" に変更
    delimiters: ['[[', ']]'],
  })
</script>
</body>
</html>
 
    