I have two Django 1.8 models that represent lists and items in lists. I also have a view that uses the Django REST framework to act as a REST endpoint and a template containing an jQuery Ajax block that calls this endpoint. This view gets all the lists owned by a particular user and looks to see if a given item is in any of the lists. Whenever it finds such an item, it should add an 'in_list' attribute to the data being passed back to the template. The problem I'm having is that while I can add this extra 'in_list' attribute to the list, it doesn't get picked up by the serializer and added to the serialized data. Here's the code:
# views.py
def get_viewer_lists_checked(request, *args, **kwargs):
user = User.objects.get(id=kwargs['viewer_id'])
lists = List.objects.filter(user=user, type=type)
item = Item.objects.get(value=kwargs['viewed_id'])
if item:
for list in lists:
if List.contains_item(item, list):
list.in_list = True
else:
list.in_list = False
serializer = MemberListsSerializer(lists, many=True)
return JSONResponse(serializer.data)
# models.py
class List(models.Model):
user = models.ForeignKey(User)
name = models.CharField(_('list'), max_length=128)
@classmethod
def contains_item(cls, item, list, *args, **kwargs):
try:
item.lists.get(id=list.id)
return True
except List.DoesNotExist:
return False
class Item(models.Model):
lists = models.ManyToManyField(List, related_name='items')
value = models.IntegerField(_('value'))
# serializer.py
class MemberListsSerializer(serializers.ModelSerializer):
class Meta:
model = List
fields = ('id', 'user', 'name')
If I run the view through the Python debugger and examine the 'lists' query set right before the serializer variable is set, I can see that an 'in_lists' attribute has been added to each element in the lists query set. But when I execute the call to MemberListsSerializer and examine 'serializer.data', the 'in_list' attribute isn't there. I thought to try adding 'in_list' to the serializer class's 'fields' list, but that doesn't work because 'in_list' isn't a field in the List model (and I don't want to add it to the model as this bit of information doesn't really belong there). I also looked at adding an extra argument to the call to the serializer method, "context={'in_list': in_list}", but this doesn't work as it only adds 'in_list' to the context returned to the template, not to each individual list. What's the correct way to insert this 'in_list' attribute such that it will get picked up by the serializer and inserted into its output?
答案 0 :(得分:1)
您可以将项目传递到上下文并使用SerializerMethodField
检查当前列表中的项目是否为
def get_viewer_lists_checked(request, *args, **kwargs):
...
item = Item.objects.get(value=kwargs['viewed_id'])
serializer = MemberListsSerializer(lists, many=True, context={'item': item})
return JSONResponse(serializer.data)
class MemberListsSerializer(serializers.ModelSerializer):
in_list = serializers.SerializerMethodField('get_in_list')
class Meta:
model = List
fields = ('id', 'user', 'name', 'in_list')
def get_in_list(self, obj):
item = self.context['item']
if List.contains_item(item, obj):
return True
else:
return False