[英]Splitting model instance for serializer into 3 different fields
Tom Christie has helped me a bunch in gear me to the right direction of using REST framework, but I have another problem, now: 汤姆克里斯蒂帮助我帮助我使用REST框架的正确方向,但我现在有另一个问题:
NOTE: This is using a viewsets.ModelViewSet 注意:这是使用viewsets.ModelViewSet
In my original code, I can return coordinate JSON data by using zip() with split() on the model instance xyz (which holds coordinate data like "20x40x50"). 在我的原始代码中,我可以通过在模型实例xyz上使用带有split()的zip()来返回坐标JSON数据(它保存坐标数据,如“20x40x50”)。 I called my own toJSON() function to make JSON-ready ouput of everything i need.
我调用了自己的toJSON()函数来使JSON-ready输出我需要的一切。 It comes out something like:
它出现了类似于:
[
{
"id" : "4"
"x" : "500",
"Y" : "80",
"z" : "150"
"color" : "yellow"
},
...
]
The problem with using REST Framework serializers is that I only know how to do the serializers.Field(source"xyz") thing. 使用REST Framework序列化程序的问题是我只知道如何执行serializers.Field(源“xyz”)的事情。 I do not know how to return "x" "y" "z" as separate fields, instead of return "xyz" as one big field.
我不知道如何将“x”“y”“z”作为单独的字段返回,而不是将“xyz”作为一个大字段返回。
Here's my code: 这是我的代码:
serializers.py:
---------------
class NoteSerializer(serializers.ModelSerializer):
owner = serializers.Field(source='owner.username')
firstname = serializers.Field(source='owner.first_name')
lastname = serializers.Field(source='owner.last_name')
x = ???
y = ???
z = ???
class Meta:
model = Note
fields = ('id','owner','firstname','lastname','text','color', 'x', 'y, 'z', 'time')
And here's the view: 以下是观点:
views.py:
---------
def list(self, request, format=None):
if request.method == 'GET':
queryset = Note.objects.filter(owner=request.user)
serializer = NoteSerializer(queryset, many=True)
if 'text' in request.GET:
if self.is_numeric(request.GET['id']) and self.is_numeric(request.GET['x']) and self.is_numeric(request.GET['y']) and self.is_numeric(request.GET['z']):
serializer = NoteSerializer(data=request.QUERY_PARAMS)
intx = int(float(request.GET['x']))
inty = int(float(request.GET['y']))
intz = int(float(request.GET['z']))
serializer.object.xyz = str(intx) +'x'+ str(inty) +'x'+ str(intz)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
def create(self, request, format=None):
serializer = NoteSerializer(data=request.DATA)
if serializer.is_valid():
serializer.object.owner = request.user
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Here's my model: 这是我的模特:
from django.db import models
import datetime
import json
from django.utils import timezone
from django.core.urlresolvers import reverse
from django.core import serializers
from django.contrib.auth.models import User
class Note(models.Model):
owner = models.ForeignKey('auth.User', null=True)
text = models.CharField(max_length=500)
color = models.CharField(max_length=20)
xyz = models.CharField(max_length=20)
time = models.DateTimeField((u"Note Creation Date and Time"), auto_now_add=True, blank=True)
def __unicode__(self):
return unicode(self.owner)
Thanks a lot for the help! 非常感谢您的帮助! I'm new to Python/Django/REST.
我是Python / Django / REST的新手。 This seems very interesting, but just has been frustrating me for days.
这看起来非常有趣,但几天让我感到沮丧。
UPDATE: 更新:
It seems I cannot access xyz through the views.py with serializer.object.xyz. 看来我无法通过使用serializer.object.xyz的views.py访问xyz。 It says the same error "Nonetype has no attribute xyz"
它说同样的错误“Nonetype没有属性xyz”
serializer = NoteSerializer(data=request.QUERY_PARAMS)
intx = int(float(request.GET['x']))
inty = int(float(request.GET['y']))
intz = int(float(request.GET['z']))
serializer.object.xyz = str(intx) +'x'+ str(inty) +'x'+ str(intz)
serializer.save()
You can try sending your x,y,z to the serializer using the get_serializer_context so something like... 您可以尝试使用get_serializer_context将x,y,z发送到序列化程序,这样就像......
from core import models
from rest_framework import generics
from rest_framework import serializers
class BloopModelSerializer(serializers.ModelSerializer):
x_coord = serializers.SerializerMethodField('get_x')
def get_x(self, instance):
return self.context['x']
class Meta:
model = models.Bloop
class BloopAPIView(generics.ListCreateAPIView):
serializer_class = BloopModelSerializer
queryset = models.Bloop.objects.all()
def get_serializer_context(self):
context = super(BloopAPIView, self).get_serializer_context()
# you have access to self.request here
context.update({
'x': 1111,
'y': 2222
})
return context
This way you don't have to override the list and create functions anymore. 这样您就不必重写列表并再创建函数。
On a side note, you can also try putting your coords into its own serializer and group them within the serializer. 另外,您还可以尝试将coords放入自己的序列化程序中,并将它们分组到序列化程序中。 rest_framework can nest serializers, so you can add a
CoordinatesSerializer
class and your Model Serializer would look something like this rest_framework可以嵌套序列化器,因此你可以添加一个
CoordinatesSerializer
类,你的Model Serializer看起来像这样
class CoordinateSerializer(serializers.Serializer):
x = models.Field()
y = models.Field()
# ...
class BloopModelSerializer(serializers.ModelSerializer):
coordinates = CoordinateSerializer('get_coords')
def get_coords(self, instance):
return self.context['coords']
class Meta:
model = models.Bloop
My approach on this: 我的方法是:
COORD = dict(x=0, y=1, z=2)
class CoordinateField(serializers.Field):
def field_to_native(self, obj, field_name):
# retrieve and split coordinates
coor = obj.content.split('x')
# get coordinate value depending on coordinate key (x,y,z)
return int(coor[COORD[field_name]])
def field_from_native(self, data, files, field_name, into):
into['xyz'] = u'{x}x{y}x{z}'.format(**data)
super(CoordinateField, self).field_from_native(data, files, field_name, into)
class BloopModelSerializer(serializers.ModelSerializer):
x = CoordinateField()
y = CoordinateField()
z = CoordinateField()
class Meta:
model = Bloop
and this is what I get as result: 这就是我得到的结果:
{
"x": 10,
"y": 20,
"z": 30,
"content": "10x20x30"
},
EDIT: 编辑:
views.py views.py
class BloopList(generics.ListCreateAPIView):
queryset = Bloop.objects.all()
serializer_class = BloopModelSerializer
bloop_list = Bloop.as_view()
urls.py urls.py
url(r'^api/bloops/$', 'myapp.views.bloop_list', name='bloop-list'),
SUGGESTION 建议
You should not use list GET method to change/add object, DRF has built-in classes to make it very easy and makes you follow correct REST standards. 您不应该使用list GET方法来更改/添加对象,DRF具有内置类以使其非常简单并使您遵循正确的REST标准。
For example, your list method takes request data using GET params, which is a bad idea, whenever you update or add new object you should provide data inside request body using POST or PUT. 例如,你的list方法使用GET参数获取请求数据,这是一个坏主意,每当你更新或添加新对象时,你应该使用POST或PUT在请求体内提供数据。 DRF assumes, that is the way data is provided and takes care of everything.
DRF假设,这是提供数据的方式并处理所有事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.