【发布时间】:2017-11-15 20:05:08
【问题描述】:
确实在为此苦苦挣扎,而且看起来应该非常直截了当。基本上,我只是尝试将产品与用户关联,然后将这些产品中的每一个的short_name 呈现在 FE 上。
我有一张包含user_id 和prod_id 的表。该表可能如下所示:
user_id | prod_id
-----------------
2 | 42
2 | 2
2 | 21
13 | 7
13 | 17
13 | 2
user_id 是 models.ForeignKey 到 User 表,prod_id 是 models.ForeignKey 到 Products 表。更好的是,这里是模型:
# ./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)
从那里,它应该只是拉出与它们相关的产品列表,然后从Product 模型中读取short_name,或者实际上只是一个我可以解析出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)
这会导致:KeyError: 'prod_name'
无论如何,我在这方面花费的时间比我愿意承认的要多。这是一些非常基本的东西。我已经尝试了几十种变化。我会继续努力并发布我尝试过的内容和错误。
另外,这是我阅读了几十遍的参考文档:
http://www.django-rest-framework.org/api-guide/relations/
http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/
也参考了无数其他关于此的 SO 问题/答案,但不起作用。
编辑:可能已经尝试了几十件事,最终能够从服务器获得序列化响应;但是,它没有引入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。但是,它确实在print(prod) 中列出了short_name。
【问题讨论】:
-
UserToProduct 是多对多关系的直通表,应该这样声明。
标签: django django-models django-rest-framework django-views