0

in debug tool bar, I can tell there are duplicate queries pointing to source and target and also workflow, which are foreign keys of my model Flow. And in the serializer I use SlugRelatedField for creation with the argument queryset.

enter image description here

So I decide to make those two fields read_only=True and remove the queryset argument. And things work perfectly.

enter image description here

my code looks like:

# model

class Activity(models.Model):
    class Meta:
        db_table = "activity"
    uuid = serializers.UUIDField(read_only=True)
    some fields ...


class Flow(models.Model):
    class Meta:
        db_table = "workflow_flow"

    objects = FlowManager()
    source = models.ForeignKey(
        "Activity",
        db_index=True,
        related_name="outgoing",
        to_field='uuid',
        db_constraint=False,
        on_delete=models.CASCADE,
        max_length=32,
        null=True,
        blank=True,
        default=""
    )

    target = models.ForeignKey(
        "Activity",
        db_index=True,
        related_name="incoming",
        to_field='uuid',
        db_constraint=False,
        on_delete=models.CASCADE,
        max_length=32,
        null=True,
        blank=True,
        default=""
    )

    workflow = models.ForeignKey(
        "WorkFlow",
        db_index=True,
        related_name="flows",
        to_field='uuid',
        db_constraint=False,
        on_delete=models.CASCADE,
        max_length=32,
    )
    
# serializer

class FlowSerializer(ModelSerializer):
    class Meta:
        fields = "__all__"
        model = Flow

    condition = serializers.CharField(
        default="",
        required=False,
        allow_null=True,
        allow_blank=True,
        write_only=True
)

    # foreign key
    source = serializers.SlugRelatedField(
        queryset=api_models.Activity.objects.all(),
        slug_field="uuid",
    )

    target = serializers.SlugRelatedField(
        slug_field="uuid",
        queryset=api_models.Activity.objects.all()
    )
    workflow = serializers.SlugRelatedField(slug_field="uuid", queryset=api_models.WorkFlow.objects.all())


# viewset
class FlowViewSet(ModelViewSet):
    queryset = api_models.Flow.objects.all().select_related("source", "target", "workflow").all()
    lookup_field = 'uuid'
    serializer_class = api_serializers.FlowSerializer

But I need to create those two fields any idea? I know I can change them to CharField Instead But I want a correct way to handle this.

By reading the source code of the SlugRelatedField queryset is used for creation:

    def to_internal_value(self, data):
        queryset = self.get_queryset()
        try:
            return queryset.get(**{self.slug_field: data})
        except ObjectDoesNotExist:
            self.fail('does_not_exist', slug_name=self.slug_field, value=smart_str(data))
        except (TypeError, ValueError):
            self.fail('invalid')

and for representation it's as simple as:

    def to_representation(self, obj):
        return getattr(obj, self.slug_field)

so I don't get why making a get request would trigger duplicate queries. Any help would be appreciated.

0 Answers0