折腾:
【未解决】剧本编写系统中优化全部剧本列表页
期间,想要给当前:

添加一列 剧本组,结果发现还有点点麻烦:
因为此处从后台返回的数据中:
serializer = ScriptSerializer(queryset, many=True)
logger.info("serializer=%s", serializer)
serializedData = serializer.data
logger.info("serializedData=%s", serializedData)
respData = None
if page is not None:
respData = self.get_paginated_response(serializedData)
else:
respData = Response(serializedData)
logger.info("respData=%s", respData)
return respData是通过ScriptSerializer:
class ScriptSerializer(serializers.ModelSerializer):
author = serializers.CharField(source='author.username', read_only=True)
topic = serializers.CharField(source='topic.name', read_only=False)
second_level_topic = serializers.SerializerMethodField()
publish_status = serializers.SerializerMethodField()
edit_status = serializers.SerializerMethodField()
review = ReviewSerializer(many=False, read_only=True)
dialog_count = serializers.SerializerMethodField()
class Meta:
model = Script
fields = ('id', 'place', 'title', 'topic', 'second_level_topic',
'age_start', 'version', 'age_end', 'author',
'publish_status', 'edit_status', 'review', 'dialog_count',
'created_at', 'updated_at')很明显,其中只有author的名字,而没有author所在的script的function group
需要去加上这个字段,才可以返回给前端。
而参考:
review = ReviewSerializer(many=False, read_only=True)
class ReviewSerializer(serializers.ModelSerializer):
reviewer = serializers.CharField(source='reviewer.username',
read_only=True)
result = serializers.SerializerMethodField()
class Meta:
model = Review
fields = ('id', 'reviewer', 'remark', 'result')
read_only_fields = ('id', 'created_at', 'updated_at')
def get_result(self, obj):
return obj.get_result_display()好像是可以通过把author去改为:
author = UserSerializer(many=False, read_only=True)
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'mobile_phone_number', 'email', 'password', 'username',
'name', 'is_superuser', 'is_active', 'date_joined')
read_only_fields = ('id', 'is_superuser', 'date_joined')
extra_kwargs = {'password': {'write_only': True}}但是发现此处的user,并不能很好的找到其所加入的scritp function group
貌似可以用其中的自定义的RelatedField去实现:
从script的author找到其是否有加入script的function group,然后返回对应的group的id和name
结果试了半天:
class ScriptFuctionGroup(serializers.RelatedField):
def to_representation(self, value):
logger.info("ScriptFuctionGroup to_representation: self=%s, value=%s", self, value)
# find current script author joined script function group
return {
"groupId": "",
"groupName": "",
}
class ScriptSerializer(serializers.ModelSerializer):
author = serializers.CharField(source='author.username', read_only=True)
# author = UserSerializer(many=False, read_only=True)
joinedScriptGroup = ScriptFuctionGroup(many=False, read_only=True)不起效果:to_representation都运行不到。
但是对于ScriptFuctionGroup倒是可以看到的:
INFO|20180802 11:08:12|views:list:150|after ScriptSerializer serializer=ScriptSerializer(<QuerySet [<Script: 儿歌>, <Script: 儿歌>, <Script: 儿歌>, <Script: 1>, <Script: 1>, <Script: 1>, <Script: wer>]>, many=True):
id = UUIDField(read_only=True)
place = CharField(max_length=128)
title = CharField(max_length=128)
topic = CharField(read_only=False, source='topic.name')
second_level_topic = SerializerMethodField()
age_start = IntegerField(max_value=2147483647, min_value=-2147483648, required=False)
version = IntegerField(read_only=True)
age_end = IntegerField(max_value=2147483647, min_value=-2147483648, required=False)
author = CharField(read_only=True, source='author.username')
joinedScriptGroup = ScriptFuctionGroup(read_only=True)
publish_status = SerializerMethodField()
edit_status = SerializerMethodField()
review = ReviewSerializer(read_only=True):
id = UUIDField(read_only=True)
reviewer = CharField(read_only=True, source='reviewer.username')
remark = CharField(style={'base_template': 'textarea.html'})
result = SerializerMethodField()
dialog_count = SerializerMethodField()
created_at = DateTimeField(read_only=True)
updated_at = DateTimeField(read_only=True)而此处看到:
class User(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
is_active = models.BooleanField(default=False)
name = models.CharField(blank=True, max_length=128)
mobile_phone_number = models.CharField(blank=False, null=False,
max_length=11, unique=True)
class FunctionGroup(TimestampedModel):
TYPE_VALUE_ADMIN = "0"
TYPE_VALUE_SCRIPT = "1"
TYPE_NAME_ADMIN = "admin_function_group"
TYPE_NAME_SCRIPT = "script_function_group"
CHOICES = {
(TYPE_VALUE_ADMIN, TYPE_NAME_ADMIN),
(TYPE_VALUE_SCRIPT, TYPE_NAME_SCRIPT),
}
owner = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
related_name='user_function_group')
name = models.CharField(null=False, blank=False, max_length=128)
function = models.CharField(
null=False, blank=False,
# choices=FUNCTION_GROUP_CHOICES,
choices=CHOICES,
max_length=128,
# default=FUNCTION_GROUP_CHOICES_DEFAULT
default=TYPE_VALUE_SCRIPT
)
description = models.CharField(null=True, blank=True, max_length=128)
members = models.ManyToManyField(User)User中没有直接可以获取到FunctionGroup
但是貌似FunctionGroup中有间接的user_function_group,或许可以获取到?
去试试
另外同时看到了:

script_script中有:
author_id
history_id
review_id
好像都可以直接在:
ScriptSerializer中直接用类似于:
review = ReviewSerializer(many=False, read_only=True)
直接调用到别的serializer的感觉
那或许author也可以
然后author再去用user_function_group,找到function group?
去试试:
class UserFunctionGroupSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'name', 'user_function_group', 'is_active')
read_only_fields = ('id', 'username', 'name', 'user_function_group', 'is_active')
from apps.user.serializers import UserFunctionGroupSerializer
class ScriptSerializer(serializers.ModelSerializer):
author = serializers.CharField(source='author.username', read_only=True)
# author = UserSerializer(many=False, read_only=True)
# joinedScriptGroup = ScriptFuctionGroup(many=False, read_only=True)
authorObj = UserFunctionGroupSerializer(many=False, read_only=True)结果
没用。去加上source:
authorObj = UserFunctionGroupSerializer(source='author', many=False, read_only=True)
结果:
是可以获得group数据了:

但是很明显:
只有group的id,缺少我们要的group的name,且没有完全排除掉 非script的function group
所以还要去想办法,自定义
试试:
class ScriptFuctionGroup(serializers.RelatedField):
def to_representation(self, value):
logger.info("ScriptFuctionGroup to_representation: self=%s, value=%s", self, value)
# find current script author joined script function group
return {
"groupId": "",
"groupName": "",
}
class UserFunctionGroupSerializer(serializers.ModelSerializer):
user_function_group = ScriptFuctionGroup(many=False, read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'name', 'user_function_group', 'is_active')
read_only_fields = ('id', 'username', 'name', 'user_function_group', 'is_active')能否运行到to_representation
前端显示的效果是:

表示执行到了,所以去看Django的log
INFO|20180802 11:34:03|serializers:to_representation:27|ScriptFuctionGroup to_representation: self=ScriptFuctionGroup(read_only=True), value=user.FunctionGroup.None
value不是我们以为的之前的function group的id的list:
[4,3]
而是None
django serializer Custom fields
去试试serializers.SerializerMethodField()
class UserFunctionGroupSerializer(serializers.ModelSerializer):
# user_function_group = ScriptFuctionGroup(many=False, read_only=True)
# user_function_group = FunctionGroupSimpleSerializer(many=True, read_only=True)
user_function_group = serializers.SerializerMethodField()
class Meta:
model = User
fields = ('id', 'username', 'name', 'user_function_group', 'is_active')
read_only_fields = ('id', 'username', 'name', 'user_function_group', 'is_active')
def get_user_function_group(self, obj):
logger.info("ScriptFuctionGroup to_representation: self=%s, obj=%s", self, obj)
return {
"groupId": obj,
}结果:
还是不行。
后来试了:
# class ScriptFuctionGroup(serializers.RelatedField):
# def to_representation(self, value):
# logger.info("ScriptFuctionGroup to_representation: self=%s, value=%s", self, value)
# # find current script author joined script function group
# return {
# "groupId": "",
# "groupName": "",
# }
class ScriptSerializer(serializers.ModelSerializer):
author = serializers.CharField(source='author.username', read_only=True)
# author = UserSerializer(many=False, read_only=True)
# joinedScriptGroup = ScriptFuctionGroup(many=False, read_only=True)
authorObj = UserFunctionGroupSerializer(source='author', many=False, read_only=True)
topic = serializers.CharField(source='topic.name', read_only=False)
second_level_topic = serializers.SerializerMethodField()
publish_status = serializers.SerializerMethodField()
edit_status = serializers.SerializerMethodField()
review = ReviewSerializer(many=False, read_only=True)
dialog_count = serializers.SerializerMethodField()
class Meta:
model = Script
fields = ('id', 'place', 'title', 'topic', 'second_level_topic',
'age_start', 'version', 'age_end', 'author',
'authorObj',
'publish_status', 'edit_status', 'review', 'dialog_count',
'created_at', 'updated_at')
read_only_fields = ('id', 'version', 'publish_status', 'edit_status',
'authorObj',
'created_at', 'updated_at')
def get_publish_status(self, obj):
return obj.get_publish_status_display()
def get_edit_status(self, obj):
return obj.get_edit_status_display()
def get_dialog_count(self, obj):
return obj.script_dialogs.all().count()
def get_second_level_topic(self, obj):
if obj.second_level_topic_id:
return obj.second_level_topic.name
else:
return ''
class FunctionGroupSimpleSerializer(serializers.ModelSerializer):
function = serializers.SerializerMethodField()
class Meta:
model = FunctionGroup
fields = ('id', 'name', 'function')
read_only_fields = ('id', 'name', 'function')
def get_function(self, obj):
return obj.get_function_display()
class UserFunctionGroupSerializer(serializers.ModelSerializer):
# user_function_group = ScriptFuctionGroup(many=False, read_only=True)
# user_function_group = FunctionGroupSimpleSerializer(source="user_function_group", many=True, read_only=True)
user_function_group = FunctionGroupSimpleSerializer(many=True, read_only=True)
# user_function_group = serializers.SerializerMethodField()
class Meta:
model = User
fields = ('id', 'username', 'name', 'user_function_group', 'is_active')
read_only_fields = ('id', 'username', 'name', 'user_function_group', 'is_active')
# def get_user_function_group(self, obj):
# logger.info("UserFunctionGroupSerializer get_user_function_group: self=%s, obj=%s", self, obj)
# functionGroupIdList = obj.user_function_group
# logger.info("functionGroupIdList=%s", functionGroupIdList)
# return {
# "groupId": functionGroupIdList,
# }可以得到我们要的多个group了:

但是别的账号,却找不到user_function_group

所以还是有问题。
期间,遇到:
【已解决】Django中查询model中字段是数组对象出错:django.core.exceptions.FieldError: Related Field got invalid lookup: contains
【总结】
至此,是通过序列化Script中author的字段,单独去处理,解析和获取对应的所加入的script的fucntion group,去实现找到对应的一个剧本的作者所加入的(唯一的一个)剧本组:
# class ScriptFuctionGroup(serializers.RelatedField):
class ScriptFuctionGroup(serializers.Field):
def to_representation(self, value):
logger.info("ScriptFuctionGroup to_representation: self=%s, value=%s", self, value)
# find current script author joined script function group
curUser = value
logger.info("curUser=%s", curUser)
# joinedScriptGroup = FunctionGroup.objects.get(members__contains=curUser, function=FunctionGroup.TYPE_VALUE_SCRIPT)
joinedScriptGroup = FunctionGroup.objects.get(members__id=curUser.id, function=FunctionGroup.TYPE_VALUE_SCRIPT)
logger.info("joinedScriptGroup=%s", joinedScriptGroup)
return {
"groupId": joinedScriptGroup.id,
"groupName": joinedScriptGroup.name,
}
class ScriptSerializer(serializers.ModelSerializer):
author = serializers.CharField(source='author.username', read_only=True)
# author = UserSerializer(many=False, read_only=True)
# authorObj = UserFunctionGroupSerializer(many=False, read_only=True)
joinedScriptGroup = ScriptFuctionGroup(source='author')
# joinedScriptGroup = ScriptFuctionGroup(many=False, read_only=True)
# authorObj = UserFunctionGroupSerializer(source='author', many=False, read_only=True)
topic = serializers.CharField(source='topic.name', read_only=False)
second_level_topic = serializers.SerializerMethodField()
publish_status = serializers.SerializerMethodField()
edit_status = serializers.SerializerMethodField()
review = ReviewSerializer(many=False, read_only=True)
dialog_count = serializers.SerializerMethodField()
class Meta:
model = Script
fields = ('id', 'place', 'title', 'topic', 'second_level_topic',
'age_start', 'version', 'age_end', 'author',
# 'authorObj',
'joinedScriptGroup',
'publish_status', 'edit_status', 'review', 'dialog_count',
'created_at', 'updated_at')
read_only_fields = ('id', 'version', 'publish_status', 'edit_status',
# 'authorObj',
'joinedScriptGroup',
'created_at', 'updated_at')
def get_publish_status(self, obj):
return obj.get_publish_status_display()
def get_edit_status(self, obj):
return obj.get_edit_status_display()
def get_dialog_count(self, obj):
return obj.script_dialogs.all().count()
def get_second_level_topic(self, obj):
if obj.second_level_topic_id:
return obj.second_level_topic.name
else:
return ''从而使得前端返回的script中,可以有多余的字段能保存当前作者已加入的功能组:

转载请注明:在路上 » 【已解决】Django的Serializer中如何序列化Script中的Author的Function Group