admin管理员组文章数量:1291218
I am using Django as a backend and I am trying to pass some data into a Vue table ponent that I made. I set it up using this tutorial The ponent is showing up fine while using a webpack. I am trying to set the data to a javascript constant and then pass it into the ponent. The data does not appear to be passing through. Here is how my scripts are laid out.
index.html
{% block content %}
<script>
const gridData = {{json_data|safe}};
console.log(gridData)
</script>
<div id="app">
<table_ponent
v-bind:tableData=this.gridData
>
</table_ponent>
</div>
{% end block %}
myComponent.vue script seciton
export default {
name: 'table_ponent',
props: {
tableData: Array
},
data() {
return {
}
},
ponents: {
Grid,
ButtonModal
},
created(){
console.log(this.tableData)
},
}
When I look at the console, it is not showing any data. It just says undefined.
view.py
class CurrentClassroomView(LoginRequiredMixin, CreateView):
template_name = 'home/index.html'
def get(self, request, *args, **kwargs):
db_data = list(myData.objects.all().values())
my_json_data = json.dumps(db_data)
return render(request, self.template_name, {'json_data':my_json_data})
I am getting this in the console that I am not sure what that means and why it is making everything lowercase even though I'm passing it with upper case letters.
[Vue tip]: Prop "griddata" is passed to ponent <Anonymous>, but the declared prop name is "gridData". Note that HTML attributes are case-insensitive and camelCased props need to use their kebab-case equivalents when using in-DOM templates. You should probably use "grid-data" instead of "GridData".
tip @ vue.js:639
extractPropsFromVNodeData @ vue.js:2294
createComponent @ vue.js:3233
_createElement @ vue.js:3427
createElement @ vue.js:3359
vm._c @ vue.js:3496
eval @ VM1553:3
Vue._render @ vue.js:3550
updateComponent @ vue.js:4066
get @ vue.js:4477
Watcher @ vue.js:4466
mountComponent @ vue.js:4073
Vue.$mount @ vue.js:9043
Vue.$mount @ vue.js:11943
Vue._init @ vue.js:5011
Vue @ vue.js:5077
eval @ index.js:14
./assets/js/index.js @ app.js:409
__webpack_require__ @ app.js:20
(anonymous) @ app.js:84
(anonymous) @ app.js:87
Any help on this would be greatly appreciated. I am not sure where I am going wrong
I am using Django as a backend and I am trying to pass some data into a Vue table ponent that I made. I set it up using this tutorial The ponent is showing up fine while using a webpack. I am trying to set the data to a javascript constant and then pass it into the ponent. The data does not appear to be passing through. Here is how my scripts are laid out.
index.html
{% block content %}
<script>
const gridData = {{json_data|safe}};
console.log(gridData)
</script>
<div id="app">
<table_ponent
v-bind:tableData=this.gridData
>
</table_ponent>
</div>
{% end block %}
myComponent.vue script seciton
export default {
name: 'table_ponent',
props: {
tableData: Array
},
data() {
return {
}
},
ponents: {
Grid,
ButtonModal
},
created(){
console.log(this.tableData)
},
}
When I look at the console, it is not showing any data. It just says undefined.
view.py
class CurrentClassroomView(LoginRequiredMixin, CreateView):
template_name = 'home/index.html'
def get(self, request, *args, **kwargs):
db_data = list(myData.objects.all().values())
my_json_data = json.dumps(db_data)
return render(request, self.template_name, {'json_data':my_json_data})
I am getting this in the console that I am not sure what that means and why it is making everything lowercase even though I'm passing it with upper case letters.
[Vue tip]: Prop "griddata" is passed to ponent <Anonymous>, but the declared prop name is "gridData". Note that HTML attributes are case-insensitive and camelCased props need to use their kebab-case equivalents when using in-DOM templates. You should probably use "grid-data" instead of "GridData".
tip @ vue.js:639
extractPropsFromVNodeData @ vue.js:2294
createComponent @ vue.js:3233
_createElement @ vue.js:3427
createElement @ vue.js:3359
vm._c @ vue.js:3496
eval @ VM1553:3
Vue._render @ vue.js:3550
updateComponent @ vue.js:4066
get @ vue.js:4477
Watcher @ vue.js:4466
mountComponent @ vue.js:4073
Vue.$mount @ vue.js:9043
Vue.$mount @ vue.js:11943
Vue._init @ vue.js:5011
Vue @ vue.js:5077
eval @ index.js:14
./assets/js/index.js @ app.js:409
__webpack_require__ @ app.js:20
(anonymous) @ app.js:84
(anonymous) @ app.js:87
Any help on this would be greatly appreciated. I am not sure where I am going wrong
Share Improve this question asked Feb 28, 2020 at 23:15 laxerlaxer 76013 silver badges44 bronze badges 1- I'm also using Django as backend and vuejs as frontend. My advice is the following : use an API and query it from vuejs. You can use graphene-django (the graphql implementation for django) to build an API alongside with apollo to query the graphql endpoint (that's what I'm actually doing) or DRF (Django Rest Framework). Otherwise I don't know how to directly pass data from django to vuejs. – lbris Commented Feb 29, 2020 at 1:09
3 Answers
Reset to default 10When you set gridData
and try to bind it to a Vue ponent it is not working because they have different contexts. When you dealing with Vue ponents you can only access data defined inside the Vue instance. Additionally, {{json_data|safe}}
is vulnerable to XSS-type attacks.
However, it is very easy to safely pass data from Django to a Vue ponent, we just have to use the json_script
filter and load the data in Vue's mounted
hook.
In views.py just pass the list to the template, no need to use json.dumps()
:
class CurrentClassroomView(LoginRequiredMixin, CreateView):
template_name = 'home/index.html'
def get(self, request, *args, **kwargs):
db_data = list(myData.objects.all().values())
return render(request, self.template_name, {'json_data':db_data})
In index.html, we will use the json_script
template tag to create a JSON formatted representation of json_data
variable:
{% block content %}
{{ json_data|json_script:"json_data" }}
<div id="app">
<table_ponent></table_ponent>
</div>
{% end block %}
This will create a <script>
block, e.g.:
<script id="json_data" type="application/json">{"hello": "world"}</script>
And finally, in myComponent.vue, we load, JSON-decode and set the data in the mounted
hook:
export default {
data() {
return {
tableData
}
},
ponents: {
Grid,
ButtonModal
},
mounted() {
this.tableData = JSON.parse(document.getElementById('json_data').textContent)
},
}
I think you could just pass Django's server-side props straight into a child ponent that uses it. Mine's set up like this:
{% extends "ExpenseTracker/layout.html" %}
{% load static %}
{% block content %}
<div id="transactionlabeling_view"
>
<transactions-table
:cached_items = "{{transactions}}"
:account_types = "{{account_types}}"
></transactions-table>
</div>
{% endblock content %}
where there's a Vue ponent that is mounted on "#transactionlabeling_view". There, I imported the child ponent transactions-table
where I passed on the server side props from Django view ({{transactions}} & {{account_types}}) into props inside transactions-table
ponent (:cached_items & :account_types):
props:{
cached_items:null,
account_types:null
},
It's convenient that you don't have to JSON.parse those two props, vue got that job done for you. But you do need to use JSON.dump on {{transactions}} & {{account_types}} before passing it as context in the html. works like a charm, I use vue 3.2.6 and Django 4.1.6 and have vue installed inside django.
If you're using Vue 3 with SFC (single file ponent) syntax, the .provide()
method (on createApp()
) works really well for this purpose. In the Django template, pass your variables from the template (via Django context).
I'm using a hidden (and disabled) <input
element within the div where the app will be mounted. I'm not sure if this is best practice, but it seems more secure to me...
What I like most about this approach is that the mounted ponent replaces the data-provider DOM element (the hidden input)!
<!-- This is the Django template file -->
<!-- vue_ponent_block.html -->
<div name="vue-ponent-mount-point">
<input
disabled
type="hidden"
data-url="{{ url_from_django_context }}"
data-text="{{ link_text_from_django_context }}"
/>
</div>
<!-- This is the TS/JS bundle, it'll need to be included somewhere as well (after the above template content) -->
<script src="path/to/your/dist/folder/my_piled_script.js"></script>
// This is a TS (can be JS) file piled into the Django app
import { createApp } from "vue";
import MyLinkComponent from "./MyLinkComponent.vue";
const mountPoints: [HTMLElement] = document.querySelectorAll('[name="vue-ponent-mount-point"]')
mountPoints.forEach((mountPoint: HTMLElement) => {
const children: HTMLCollection = mountPoint.children
const dataInput: HTMLElement = children[0] as HTMLInputElement
const dataset: Object = dataInput.dataset
createApp(MyLinkComponent)
.provide('dataset', dataset)
.mount(mountPoint);
})
Then, in the ponent's .vue
file, I'll use inject()
to grab the data from the provider (using the same dataset
key).
<template>
<MyLinkComponent
:href="dataset['url']"
>{{ dataset['text'] }}</MyLinkComponent>
</template>
<script setup lang="ts">
import { inject } from 'vue'
const dataset = inject('dataset')
</script>
本文标签: javascriptPass Django Data into Vue componentStack Overflow
版权声明:本文标题:javascript - Pass Django Data into Vue component - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741509338a2382514.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论