在Django REST Framework中读取外键关系表中的相关数据

时间:2017-11-15 20:05:09

标签: django django-models django-rest-framework django-views

真的很挣扎,看起来应该是非常直接的。基本上,我只是尝试与用户关联的产品,然后在FE上呈现每个产品的short_name

我有一张包含user_idprod_id的表格。该表可能如下所示:

user_id | prod_id
-----------------
2       | 42
2       | 2
2       | 21
13      | 7
13      | 17
13      | 2

user_idmodels.ForeignKey表的Userprod_idmodels.ForeignKeyProducts表。更好的是,这是模型:

# ./home/models.py
from django.contrib.auth import get_user_model
from django.db import models

User = get_user_model()

class Product(models.Model):
    id = models.AutoField(primary_key=True)
    code = models.CharField(unique=True, max_length=16)
    name = models.CharField(max_length=255, blank=True, null=True)
    short_name = models.CharField(max_length=128)
    updated = models.DateTimeField(blank=True, null=True)
    created = models.DateTimeField(blank=True, null=True)   

    def __str__(self):
        return self.short_name

    class Meta:
        db_table = 'Product'

class UserToProduct(models.Model):
    user = models.ForeignKey(User, related_name='user_name', db_column='user_id', null=True)
    prod = models.ForeignKey(Product, related_name='prod_name', db_column='prod_id', null=True)

    class Meta:
        db_table = 'User_to_Product'
        unique_together = ('user', 'prod')

应该发生的是React前端基于谁登录到Django / DRF后端发送user_id。这种情况发生得很好。以下是相关视图:

# ./home/views.py
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST
from rest_framework.views import APIView

from .serializers import GetProductSerializer
from .models import Home

class GetHomeAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        serializer = GetProductSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            return Response(serializer.data, status=HTTP_200_OK)
        return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)

从那里,它应该只是拉出与它们相关的产品列表,然后从short_name模型中读取Product,或者实际上只是我可以解析{{}的对象1}}。

这是序列化器:

short_name

此特定变体会导致:# ./home/serializers.py from rest_framework.serializers import ( IntegerField, ModelSerializer, SerializerMethodField, StringRelatedField, ) from .models import * class GetProductSerializer(ModelSerializer): prod_name = StringRelatedField(many=True, required=False) product = SerializerMethodField('get_products') class Meta: model = UserToProduct fields = ('user', 'prod', 'prod_name') def get_products(self, obj): products = UserToProduct.objects.filter(user=data['user']) return products

NameError: name 'data' is not defined更改为:

get_products()

这导致:# for testing reasons products = UserToProduct.objects.filter(user=2)

无论如何,我花了更多时间在这上面,而不是承认。这是一些非常基本的东西。我尝试过几十种变体。我将继续努力并发布我尝试过的内容和错误。

此外,这是我引用的文档,我已阅读了数十次:

http://www.django-rest-framework.org/api-guide/relations/

http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/

参考了无数其他有关这方面的问题/答案而且没有工作。

编辑:可能已经尝试了几十件事情,最终能够从服务器获得序列化响应;但是,它没有引入KeyError: 'prod_name'。我只做了一些修改:

short_name
# ./home/models.py
class Product(models.Model)
    ...
    users = models.ManyToManyField(User, through='UserToProduct')

另外,需要注意的是将# ./home/serializers.py class GetProductSerializer(ModelSerializer): user = IntegerField() # have to do this otherwise it returns the username and not the id prod = SerializerMethodField() class Meta: model = UserToProduct fields = [ 'user', 'prod', ] def get_prod(self, obj): prod = UserToProduct.objects.filter(user=obj['user']).values('prod') print(prod) return prod 留作:

get_prod()

结果:prod = UserToProduct.objects.filter(user=obj['user']) 。但是,它会列出TypeError: Object of type 'UserToProduct' is not JSON serializable中的short_name

1 个答案:

答案 0 :(得分:0)

好的,终于认为我搞定了。虽然速度非常慢,但需要大约5秒才能返回真正看起来不对的信息。这对于数据量来说太长了。

无论如何,这是让它为我工作的原因:

# ./home/serializers.py
class GetProductSerializer(ModelSerializer):
    prod = CharField() # otherwise it was using prod_id number

    class Meta:
        model = UserToProduct
        fields = [
            'prod'
        ]
UserToProduct.objects.filter(user=user).prefetch_related('prod')

比我尝试的方式更简单...刚刚解决速度问题。

编辑:由于这篇SO帖子的帮助,修正了速度问题:

Optimizing database queries in Django REST framework

将我的查询修改为以下内容:

setOpacityTo(value: number, duration: number)

它从4.75秒下降到1.5秒。绮山楂。