序列化Django对象:如何输出清除列表

时间:2019-07-15 16:08:04

标签: python django django-rest-framework

我有一个Django应用,其中包含一组市场,这些市场通过外键连接到价格历史记录,该价格历史记录在models.py中定义如下:

class Market(models.Model):
    title = models.CharField(max_length=50, default="")
    current_price = models.DecimalField(max_digits=5, decimal_places=2)
    description = models.TextField(default="")
    shares_yes = models.IntegerField(default=0)
    shares_no = models.IntegerField(default=0)
    b = models.IntegerField(default=100)
    cost_function = models.IntegerField(default=0)

    def __str__(self):
        return self.title[:50]

    def get_absolute_url(self):
        return reverse('market_detail', args=[str(self.id)])

class Price(models.Model):
    market = models.ForeignKey(
        Market, 
        on_delete=models.CASCADE,
        related_name='prices', 
        default=None)
    price = models.DecimalField(
        max_digits=5, 
        decimal_places=2, 
        default=None)

    def __str__(self):
        return str(self.price)

    def get_absolute_url(self):
        return reverse('market_list')

在模板中,用户可以查看当前市场价格,并可以买卖与该市场有关的股票。他们还应该看到一个价格图,我正尝试通过将其从market.prices序列化为price_items的方式来填充价格图(从views.py开始,忽略labels中的玩具值) :

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

   def get(self, request, pk):
        market = Market.objects.get(pk=pk)
        price_items = serializers.serialize('json', market.prices.get_queryset(), fields=('price'))
        labels = [1, 2, 3, 4] # Toy labels
        data = {
            "labels": labels,
            "prices": price_items}
        return Response(data)

urls.py的相关部分如下:

urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
    path('list/', MarketListView.as_view(), name='market_list'),
    path('<int:pk>/', MarketDetailView.as_view(), name='market_detail'),
    path('<int:pk>/buy/', views.buy, name='buy'),
    path('<int:pk>/sell/', views.sell, name='sell'),
    # url(r'^api/chart/data/$', ChartData.as_view()),
    path('<int:pk>/api/chart/data/', ChartData.as_view(), name='chart_data'),

]

我的问题是:我无法弄清楚如何简单地获得输出端价格的干净清单,以将其输入到位于data.prices的折线图中:

<script>
        {% block jquery %}
            var endpoint = "{% url 'chart_data' market.id %}"
            var defaultData = []
            var labels = []
            $.ajax({
                method: "GET",
                url: endpoint,
                success: function(data){
                    labels = data.labels
                    defaultData = data.prices
                    var ctx = document.getElementById('myChart').getContext('2d');
                    var myChart = new Chart(ctx, {
                        type: 'line',
                        data: {
                            labels: labels,
                            datasets : [{
                                label: 'Market price',
                                data: defaultData
                            }]
                        },
                        options: {
                            scales: {
                                yAxes: [{
                                    ticks: {
                                        suggestedMin: 0,
                                        suggestedMax: 1
                                    }
                                }]
                            }
                        }
                    })
                }
            })
        {% endblock %}
</script>

这是我在相关<int:pk>/api/chart/data/网址中的json中获取的内容:

{"labels":[1,2,3,4],"prices":"[{\"model\": \"markets.price\", \"pk\": 4, \"fields\": {\"price\": \"0.90\"}}, {\"model\": \"markets.price\", \"pk\": 5, \"fields\": {\"price\": \"0.91\"}}, {\"model\": \"markets.price\", \"pk\": 6, \"fields\": {\"price\": \"0.92\"}}, {\"model\": \"markets.price\", \"pk\": 7, \"fields\": {\"price\": \"0.92\"}}, {\"model\": \"markets.price\", \"pk\": 8, \"fields\": {\"price\": \"0.93\"}}, {\"model\": \"markets.price\", \"pk\": 12, \"fields\": {\"price\": \"0.92\"}}, {\"model\": \"markets.price\", \"pk\": 13, \"fields\": {\"price\": \"0.93\"}}, {\"model\": \"markets.price\", \"pk\": 14, \"fields\": {\"price\": \"0.88\"}}, {\"model\": \"markets.price\", \"pk\": 15, \"fields\": {\"price\": \"0.87\"}}, {\"model\": \"markets.price\", \"pk\": 16, \"fields\": {\"price\": \"0.86\"}}, {\"model\": \"markets.price\", \"pk\": 17, \"fields\": {\"price\": \"0.85\"}}, {\"model\": \"markets.price\", \"pk\": 18, \"fields\": {\"price\": \"0.86\"}}, {\"model\": \"markets.price\", \"pk\": 19, \"fields\": {\"price\": \"0.87\"}}, {\"model\": \"markets.price\", \"pk\": 20, \"fields\": {\"price\": \"0.86\"}}, {\"model\": \"markets.price\", \"pk\": 26, \"fields\": {\"price\": \"0.87\"}}, {\"model\": \"markets.price\", \"pk\": 27, \"fields\": {\"price\": \"0.88\"}}, {\"model\": \"markets.price\", \"pk\": 28, \"fields\": {\"price\": \"0.87\"}}, {\"model\": \"markets.price\", \"pk\": 29, \"fields\": {\"price\": \"0.86\"}}, {\"model\": \"markets.price\", \"pk\": 30, \"fields\": {\"price\": \"0.85\"}}, {\"model\": \"markets.price\", \"pk\": 31, \"fields\": {\"price\": \"0.83\"}}, {\"model\": \"markets.price\", \"pk\": 32, \"fields\": {\"price\": \"0.85\"}}, {\"model\": \"markets.price\", \"pk\": 33, \"fields\": {\"price\": \"0.86\"}}, {\"model\": \"markets.price\", \"pk\": 34, \"fields\": {\"price\": \"0.85\"}}, {\"model\": \"markets.price\", \"pk\": 35, \"fields\": {\"price\": \"0.86\"}}, {\"model\": \"markets.price\", \"pk\": 36, \"fields\": {\"price\": \"0.87\"}}, {\"model\": \"markets.price\", \"pk\": 37, \"fields\": {\"price\": \"0.88\"}}, {\"model\": \"markets.price\", \"pk\": 38, \"fields\": {\"price\": \"0.89\"}}]"}

我在做什么错了?

2 个答案:

答案 0 :(得分:0)

之所以得到结果,是因为您两次对price_items进行了序列化。如果使用的是django序列化程序,则应仅使用HttpResponse并返回数据。

price_items = serializers.serialize('json', market.prices.get_queryset(), fields=('price'))
return HttpResponse(price_items,content_type='application/json')

如果您也想在响应中返回标签,那么我认为这应该可行:

price_items = market.prices.get_queryset().values()   #include the fields you want to display in .values() as strings eg .values('prices')
labels = [1,2,3,4]
data = {
            "labels": labels,
            "prices": price_items}
return JsonResponse(data)

您可能需要根据Django模型修改price_items查询

答案 1 :(得分:0)

您可以/应该使用序列化器:

from rest_framework import serializers


class MySerializer(serializers.Serializer):
    labels = serializers.ListField(default=[1, 2, 3, 4])
    prices = serializers.SerializerMethodField()

    def get_prices(self, obj):
        return obj.prices.values_list('price', flat=True)


class ChartData(RetrieveAPIView):
    queryset = Market.objects.all()
    authentication_classes = []
    permission_classes = []
    serializer_class = MySerializer