【问题标题】:serialize model to use with Chart.js in Django序列化模型以在 Django 中与 Chart.js 一起使用
【发布时间】:2020-07-13 05:16:45
【问题描述】:

尽管我已经看到很多关于类似主题的资源,但没有任何东西能够解决我的问题。最接近的是How do I JSON serialize a Python dictionary?django model serialization

我正在尝试使用 Chart.js 从我的前端模型绘制图表,但我无法让我的视图被序列化并且无法拟合图表的参数。我附上了我的 model.py、view.py 和 htlm 页面以及我得到的错误。

models.py

class Classification(models.Model):
    Class = models.CharField(max_length=10, primary_key=True)
    inventory_dollars = models.FloatField(default=0)

    def __str__(self):
        return self.Class


class ClassificationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Classification
        fields = "__all"

views.py

class HomeView(View):
    def get(self, request, *args, **kwargs):
        return render(request, 'dashboard/charts.html', {})



class ChartData(APIView):
    authentification_classes = []
    permission_classes = []

    def get(self, request, format=None):
        labels = Classification.Class
        default_items = Classification.inventory_dollars
        data = {
            "labels" : labels,
            "default": default_items
        }

        return HttpResponse(json.dumps(data), content_type = 'application/javascript; charset=utf8')

html

{%  extends 'dashboard/base.html' %}

<script>
{% block jquery %}
var endpoint = '/api/chart/data'
var defaultData = []
var labels = [];
$.ajax({
    method: "GET",
    url: endpoint,
    success: function(data1){
        labels = data1.labels
        defaultData = data1.default
        setChart()


    },
    error: function(error_data){

        console.log(error_data)
    }}
)

function setChart(){

    var ctx = document.getElementById('myChart').getContext('2d');
    var ctx2 = document.getElementById('myChart2').getContext('2d');

    var mychart2 = new Chart(ctx2, {
        type: 'polarArea',
        data: {
            labels: labels,
            datasets: [{
                label: '# of Votes',
                data: defaultData,
                backgroundColor: [
                    'rgba(255, 99, 132, 0.2)',
                    'rgba(54, 162, 235, 0.2)',
                    'rgba(255, 206, 86, 0.2)',
                    'rgba(75, 192, 192, 0.2)',
                    'rgba(153, 102, 255, 0.2)',
                    'rgba(255, 159, 64, 0.2)'
                ],
                borderColor: [
                    'rgba(255, 99, 132, 1)',
                    'rgba(54, 162, 235, 1)',
                    'rgba(255, 206, 86, 1)',
                    'rgba(75, 192, 192, 1)',
                    'rgba(153, 102, 255, 1)',
                    'rgba(255, 159, 64, 1)'
                ],
                borderWidth: 1
            }],
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true
                        }
                    }]
                }
            }


        }
    })


    var myChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: labels,
            datasets: [{
                label: '# of Votes',
                data: defaultData,
                backgroundColor: [
                    'rgba(255, 99, 132, 0.2)',
                    'rgba(54, 162, 235, 0.2)',
                    'rgba(255, 206, 86, 0.2)',
                    'rgba(75, 192, 192, 0.2)',
                    'rgba(153, 102, 255, 0.2)',
                    'rgba(255, 159, 64, 0.2)'
                ],
                borderColor: [
                    'rgba(255, 99, 132, 1)',
                    'rgba(54, 162, 235, 1)',
                    'rgba(255, 206, 86, 1)',
                    'rgba(75, 192, 192, 1)',
                    'rgba(153, 102, 255, 1)',
                    'rgba(255, 159, 64, 1)'
                ],
                borderWidth: 1
            }],
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true
                        }
                    }]
                }
            }
        }
    })}

{% endblock %}
</script>

{% block content %}



<div class ='row'>
    <div class="clo-sm-12">
        <h1>Inventory Management Dashboard</h1>
        <canvas id="myChart" width="400" height="100"></canvas>
        <canvas id="myChart2" width="400" height="100"></canvas>
    </div>
</div>

{% endblock content %}

如您所见,我需要找到一种方法来在我的视图中指定“标签”和“默认”,以便随后在 html 文件中进行绘制。这是我到目前为止得到的错误:

Request Method: GET
Request URL: http://127.0.0.1:8000/api/chart/data
Django Version: 3.0.4
Python Executable: /Users/pierre/Desktop/Django-app/bin/python
Python Version: 3.7.1
...

Traceback (most recent call last):
  ...
  File "/Users/pierre/Desktop/inventory3/dashboard/views.py", line 67, in get
    return HttpResponse(json.dumps(data), content_type = 'application/javascript; charset=utf8')
  File "/Users/pierre/anaconda3/lib/python3.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  ...

Exception Type: TypeError at /api/chart/data
Exception Value: Object of type Manager is not JSON serializable
Request information:
USER: AnonymousUser

GET: No GET data

POST: No POST data

FILES: No FILES data

我该如何解决这个问题?感谢您的帮助

我是 Django 新手,我真的不知道该做什么了。

更新:感谢@dirkgroten 的建议,我改变了看法:

class ChartData(APIView):
    authentification_classes = []
    permission_classes = []

    def get(self, request, format=None):
        labels = Classification.objects.all().values_list('Class', flat=True)
        default_items = Classification.objects.all().values_list('inventory_dollars', flat=True)
        data = {
            "labels" : labels,
            "default": default_items
        }

        return HttpResponse(json.dumps(data), content_type = 'application/javascript; charset=utf8')

现在给了我错误:

TypeError: Object of type QuerySet is not JSON serializable

【问题讨论】:

  • 不清楚这个错误究竟发生在哪里,您需要显示告诉我们错误发生在哪一行代码的部分或错误跟踪。 Classification.ClassClassification.inventory_dollars 也是类属性,而不是数据库中的值。而且你没有在任何地方使用你的ClassificationSerializer,这似乎是合适的事情,因为你正在使用 django-rest-framework。
  • 好的,我用回溯更新了我的问题。关于序列化程序,这是我没有得到的,如何在尊重图形参数的同时使用序列化程序
  • 好吧,公平点,如果您只需要发回两个值列表,那么您不一定需要序列化程序。但是您仍然需要进行查询以获取数据库中的对象并创建列表。喜欢labels = Classification.objects.all().values_list('Class', flat=True)
  • 知道了,谢谢您的建议 + 修改 return 语句以简单地 'return Response(data) 做到了。谢谢!如果你想把它作为答案,我很乐意接受它
  • 它对你有用吗?因为我可能看到你的 json 数据有什么问题

标签: python django


【解决方案1】:

json.dumps() 将只接受 python list 或 python dict。此外,在dictlist 中,您只能使用dictlist 和原始python 类型strintfloat

所以你不能只传递你的模型实例,除非你先序列化它们(这就是你的ClassificationSerializer 所做的)。但实际上,您的图形 API 似乎只需要两个值列表,因此您应该使用 labels = Classification.objects.values_list('Class', flat=True) 获取它们。

最后,这会返回一个QuerySet (labels),因此您需要先将其设为listlist(labels)

注意:我强烈建议您将字段 Class 重命名为其他小写字母。事实上你不能称它为class,因为它是一个保留关键字,但python中的属性应该是小写的。您的命名使代码难以阅读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-17
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    相关资源
    最近更新 更多