Home > Software design >  Why does React Native receive attributes that are `models.TextChoices` from Django as a tuple conver
Why does React Native receive attributes that are `models.TextChoices` from Django as a tuple conver

Time:11-03

I have this text choices model

models.py

class PostType(models.TextChoices):
    DECLARE = 'DECLARE'
    UPDATE = 'UPDATE'
    SUCCESS = 'SUCCESS'


class Post(models.Model):
    # ulid does ordered uuid creation
    uuid = models.UUIDField(primary_key=True, default=generate_ulid_as_uuid, editable=False)
    created = models.DateTimeField('Created at', auto_now_add=True)
    updated_at = models.DateTimeField('Last updated at', auto_now=True, blank=True, null=True)
    creator = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="post_creator")
    join_goal = models.ForeignKey(JoinGoal, on_delete=models.CASCADE)
    body = models.CharField(max_length=511, validators=[MinLengthValidator(5)])
    hash_tags = models.ManyToManyField(HashTag)
    type = models.CharField(
        choices=PostType.choices,
        max_length=50,
    )

for some reason on the mobile front-end it's returning as:

React Native Code

console.log(response[0].type)
console.log(typeof(response[0].type))

Console

 LOG  ('UPDATE', 'Update')
 LOG  string

The above were produced by console.log the response and console.log typeof on the key in the response as well. This tells me that Django is sending it as a tuple of ('<type all caps>', '<type camel case>') and then React Native is converting it to a string and printing is as such. Why is this happening? What can I do on Django to ensure just 'Declare', 'UPDATE' or 'SUCCESS' is returned to the react native?

view.py

@api_view(['GET'])
def get_initial_posts(request, count):
    serializer = full_post_data_serializer(Post.objects.order_by('-uuid')[:count])
    return Response(serializer.data, status=status.HTTP_200_OK)

helper.py

def full_post_data_serializer(post_query_set: QuerySet):
    query_set_annotated = post_query_set.annotate(
        creator_username=F('creator__username'),
        goal_description=F('join_goal__goal__description'),
        goal_uuid=F('join_goal__goal__uuid'),
        reply_count=Count('replypost', distinct=True),
        cheer_count=Count('cheerpost', distinct=True)
    )
    return FullPostDataSerializer(query_set_annotated, many=True)

serializer.py

class FullPostDataSerializer(serializers.ModelSerializer):
    goal_uuid = serializers.SlugField()
    creator_username = serializers.SlugField()
    reply_count = serializers.IntegerField()
    cheer_count = serializers.IntegerField()
    goal_description = serializers.SlugField()

    class Meta:
        model = Post
        fields = (
            'body', 'join_goal', 'created', 'creator_username', 'goal_description', 'reply_count', 'cheer_count',
            'images', 'uuid', 'type', 'creator', 'videos', 'goal_uuid'
        )

CodePudding user response:

You can find an answer here: https://stackoverflow.com/a/28954424/1935069

This is slightly dependent on which version of DRF and Django you are using. What I would do is to be explicit and modify the serializer to use a serializers.SerializerMethodField and get the display value for the choices field like so:

class FullPostDataSerializer(serializers.ModelSerializer):
    ... # your existing code goes here
    type = serializers.SerializerMethodField()

    def get_type(instance):
        return instance.type.value

    ...

This should return the proper value in the serializer.

Another thing to note is that type is a reserved keyword in python. You can use it like this, but really should not, so I suggest a rename of the variable if possible

  • Related