折腾:
【未解决】剧本编写系统中优化全部剧本列表页
期间,想要给当前:
添加一列 剧本组,结果发现还有点点麻烦:
因为此处从后台返回的数据中:
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