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

添加一列 剧本组,结果发现还有点点麻烦:
因为此处从后台返回的数据中:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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
需要去加上这个字段,才可以返回给前端。
而参考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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去改为:
1 2 3 4 5 6 7 8 9 10 | 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
结果试了半天:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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倒是可以看到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 ) |
而此处看到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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?
去试试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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:
1 | authorObj = UserFunctionGroupSerializer( source = 'author' , many=False, read_only=True) |
结果:
是可以获得group数据了:

但是很明显:
只有group的id,缺少我们要的group的name,且没有完全排除掉 非script的function group
所以还要去想办法,自定义
试试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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
1 | 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()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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, } |
结果:
还是不行。
后来试了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | # 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,去实现找到对应的一个剧本的作者所加入的(唯一的一个)剧本组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | # 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