LoginSignup
1
2

More than 3 years have passed since last update.

DjangoのQuerySetをJSON形式に変換してVue.jsで受け取る

Last updated at Posted at 2021-03-29

はじめに

Vue.jsが気に入ってしまったので、DjangoのQuerySetをJSON形式に変換してVue.js内で扱える様にしました。忘れっぽい自分のために、備忘録的に残します。

前提条件

Django: version 3.1.7
Vue.js: version 2.6.12(CDN)
axios等は使用しません

コード

Djangoにアプリ追加したところで各モジュールを書きかえます。

urls.py
from django.urls import path
from . import views

app_name= 'app'

urlpatterns = [
    path('list/', views.ListData, name= 'list'),
]
models.py
import uuid

from django.db import models

class Book(models.Model):

    id= models.UUIDField(primary_key=True, default= uuid.uuid4, editable= False)
    title= models.CharField(verbose_name= 'タイトル', max_length=40)

ここでは、JSONが知らない特別なタイプの型をとるために、idをUUIDにしておきます。

views.py
import json, uuid

class ListDataView(ListView):
    template_name= "app/listdata.html"
    model= Book

    def get_context_data(self, **kwargs):
        def cnvDataToJson(object):
            if(isinstance(object, uuid.UUID)):
                return str(object)

        context= super().get_context_data(**kwargs)
        books= self.object_list.values('id', 'title')
        bookList= json.dumps(list(books), ensure_ascii=False, default=cnvDataToJson)
        context["bookList"]= bookList

        return context

ListData= ListDataView.as_view()

Bookモデルからデータを得る時に、values()クエリを使って「辞書のリスト」に変換しておきます。
その後、この辞書リストをjson.dumps()でJSON形式の配列に変換しますが、default=cnvDataToJsonのところで、jsonが知らない型を文字列に変換してあげるためのコールバックを設定します。
なお、ensure_ascii=Falseは文字バケ対策です。

listdata.html
 <div id="v-app">
        <button @click="get_books()">GetBooks</button>
        <div>
            <table>
                <tr>
                    <th>No.</th>
                    <th>タイトル</th>
                </tr>
                <tr v-for="(book, index) in books">
                    <td>[[index]]</td>
                    <td>[[book.id]]</td>
                    <td>[[book.title]]</td>
                </tr>
            </table>
        </div>
    </div>

    <script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
    <script>

        Vue.options.delimiters = ['[[',']]']

        const vm = new Vue({
            el: "#v-app",
            data: function(){
                return{
                    books:[],
                }
            },
            methods:{
                get_books: function(){
                    this.books.splice(0);
                    this.books= {{bookList|safe}};  //Djangoから受け取るデータを配列にセットする。
                },
            },
        })
    </script>

Vue.options.delimiters = ['[[',']]']
DjangoとVue.jsはデフォルトではテンプレート内で使用する{{ }}が衝突してしまうため、Vue.js側でデリミタを再定義してあげます。

this.books= {{bookList|safe}}
JSON配列となったデータをVue.js(javaScript)側の配列に移します。このときsafeでフィルタすることで、エクケープ処理をします。(細かいことは解りませんが、これがないとダメでした。)

あとがき

javaScriptからDjangoの{{ }}を扱う時にずっと" "で囲うことをしていたために欲しい結果が得られずにいました。
Djangoのテンプレートなので" "は要らないことが判りました。
あと、Htmlタグに仕掛けをすることが出きるVue.jsって素晴らしく便利だと思った。(CLIの方は敬遠します)

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2