I'm trying to link multiple items (subdomains) to an item being created (evidence).
My form submits okay - but I'm trying to figure out the 'best' way to go about this.
According to the docs I have to override the create method - but their example shows them 'creating' the related objects.
I don't want to do that. I want to just just add those related items to the piece of evidence I am creating (to create the relationship)
Here are my serializers:
class SubdomainSerializer(serializers.ModelSerializer):
class Meta:
model = Subdomain
fields = [
"id",
"domain",
"short_description",
"long_description",
"character_code",
]
class EvidenceSerializer(serializers.ModelSerializer):
"""
"""
created_by = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
updated_by = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
absolute_url = serializers.SerializerMethodField()
created_by_name = serializers.SerializerMethodField()
updated_by_name = serializers.SerializerMethodField()
subdomains = SubdomainSerializer(many=True)
class Meta:
model = Evidence
fields = "__all__"
extra_kwargs = {
"subdomains": {
"error_messages": {
"null": "This field is required.",
"blank": "This field is required.",
}
},
}
def get_absolute_url(self, obj):
return obj.get_absolute_url()
def get_created_by_name(self, obj):
return obj.created_by.full_name
def get_updated_by_name(self, obj):
return obj.updated_by.full_name
def create(self, validated_data):
subdomains_data = validated_data.pop("subdomains")
evidence = Evidence.objects.create(**validated_data)
for subdomain in subdomains_data:
# This is where I want to add the subdomains to the evidence - not create ones - how best to accomplish that?
Subdomain.objects.create(**subdomain)
return evidence
def update(self, instance, validated_data):
# Add the requestor as the updater in a PATCH request
request = self.context["request"]
validated_data["updated_by"] = request.user
return super().update(instance, validated_data)
Is there a better way to setup my serializers? Should I be doing something different to make this more achievable?
Edited to add my models:
class Subdomain(CreateUpdateMixin):
"""
"""
domain = models.ForeignKey(Domain, on_delete=models.PROTECT)
short_description = models.CharField(max_length=100)
long_description = models.CharField(max_length=250)
character_code = models.CharField(max_length=5)
proficiency_levels = models.ManyToManyField(SubdomainProficiencyLevel)
class Meta:
verbose_name = "Subdomain"
verbose_name_plural = "Subdomains"
def __str__(self):
"""Unicode representation of Subdomain."""
return f"{self.character_code}"
class Evidence(CreateUpdateMixin, CreateUpdateUserMixin, SoftDeletionModel):
"""
"""
subdomains = models.ManyToManyField(Subdomain, related_name="evidences")
evaluation = models.ForeignKey(
Evaluation, related_name="evidences", on_delete=models.PROTECT
)
published = models.BooleanField(default=False)
comments = models.CharField(max_length=500)
class Meta:
ordering = ["-created_at"]
verbose_name = "Evidence"
verbose_name_plural = "Evidence"
def __str__(self):
"""Unicode representation of Evidence."""
return f"{self.subdomain} : {self.comments}"
def get_absolute_url(self):
"""Return absolute url for Evidence."""
return reverse("evidence-detail", args=[str(self.id)])