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