使用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>

做完了!

广告
将在 10 秒后关闭
bannerAds