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
.
So I decide to make those two fields read_only=True
and remove the queryset
argument. And things work perfectly.
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.