如何将Django服务端变量传入React JSX文件?
在Django中向React JSX传递上下文变量的方案
你现在的场景是:Django的RestaurantListView已经能通过模板变量传递数据给前端,但要切换到React渲染,而且不想在模板里写业务JS,想让静态打包的React代码拿到这些上下文变量对吧?这里有几个实用的方案:
方案1:模板注入全局上下文变量(适合简单场景)
这是最直接的方式,不用改太多现有代码,只需要在模板里加一小段脚本,把Django的上下文变量转成浏览器全局可访问的JS对象,同时做好安全处理:
- 在
restodetails.html里添加:
<!-- 用Django的json_script过滤器把复杂列表转成安全的JSON,避免XSS风险 --> {% json_script "restaurants-data" restaurants %} <!-- 注入简单变量和全局上下文入口 --> <script> window.djangoContext = { order: "{{ order|escapejs }}", getRestaurants: function() { return JSON.parse(document.getElementById('restaurants-data').textContent); } }; </script> <!-- 引入你打包好的React脚本 --> <script src="{% static 'path/to/your/bundled/react-app.js' %}"></script>
这里的json_script和escapejs都是为了避免前端注入风险,比直接输出原始字符串更安全。
- 在你的React代码里,直接读取这个全局变量:
import { useState, useEffect } from 'react'; function RestaurantApp() { const [order, setOrder] = useState(window.djangoContext.order); const [restaurants, setRestaurants] = useState([]); useEffect(() => { const fetchedRestaurants = window.djangoContext.getRestaurants(); setRestaurants(fetchedRestaurants); }, []); // 用拿到的变量渲染组件 return ( <div> <h1>当前排序:{order}</h1> {/* 渲染餐厅列表逻辑 */} </div> ); } export default RestaurantApp;
方案2:用Django API提供数据(适合复杂SPA场景)
如果之后想逐步转向前后端分离,这个方案更具长远性。把原来的ListView改成API接口,React通过HTTP请求获取数据:
- 先安装Django REST Framework(如果还没装),然后写一个API视图:
from rest_framework.views import APIView from rest_framework.response import Response from .models import Restaurant from .serializers import RestaurantSerializer # 需要你自己编写序列化器 class RestaurantListAPI(APIView): def get(self, request, order): pids = request.session['place_ids'] ordering_dict = { 'rating-asc': 'rating', 'rating-desc': '-rating', 'name-asc': 'name', 'name-desc': '-name', 'distance-asc': 'distance_from_route', 'distance-desc': '-distance_from_route' } if order == 'default': queryset = Restaurant.objects.filter(place_id__in=pids) else: queryset = Restaurant.objects.filter(place_id__in=pids).order_by(ordering_dict[order]) serializer = RestaurantSerializer(queryset, many=True) return Response({ 'restaurants': serializer.data, 'order': order })
别忘了在urls.py里配置API路由,比如path('api/restaurants/<str:order>/', RestaurantListAPI.as_view())。
- 在React代码里用
fetch请求API:
import { useState, useEffect } from 'react'; function RestaurantApp() { const [order, setOrder] = useState(''); const [restaurants, setRestaurants] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { // 从URL参数或其他渠道获取order值 const currentOrder = window.location.pathname.split('/').pop() || 'default'; fetch(`/api/restaurants/${currentOrder}/`) .then(response => response.json()) .then(data => { setRestaurants(data.restaurants); setOrder(data.order); setLoading(false); }) .catch(error => console.error('获取数据失败:', error)); }, []); if (loading) return <div>加载中...</div>; return ( <div> <h1>当前排序:{order}</h1> {/* 渲染餐厅列表逻辑 */} </div> ); } export default RestaurantApp;
这种方式下Django只负责提供数据,React完全接管前端渲染,扩展性更强。
方案3:通过DOM元素属性传递简单变量
如果只是传递少量简单的字符串变量(比如order),可以把变量放在React挂载根元素的data属性里:
- 在模板里:
<div id="react-root" data-order="{{ order|escapejs }}"></div> <script src="{% static 'path/to/your/bundled/react-app.js' %}"></script>
- 在React入口文件里读取这个属性:
import React from 'react'; import ReactDOM from 'react-dom/client'; import RestaurantApp from './RestaurantApp'; const rootElement = document.getElementById('react-root'); const order = rootElement.dataset.order; const root = ReactDOM.createRoot(rootElement); root.render(<RestaurantApp order={order} />);
然后在RestaurantApp组件里直接通过props.order使用变量即可。这个方案适合变量少且简单的场景,复杂数据还是推荐前两个方案。
内容的提问来源于stack exchange,提问作者Sidharth Samant
相关产品推荐
相关产品推荐

