1

I've got three models, Product, ProductRelease, and ReleaseNote that all inherit from an abstract model factory (with common fields) with the following relationships:

class Product(abstract_base_model_factory()):
    <additional fields>

class ProductRelease(abstract_base_model_factory()):
    <additional fields>
    product = models.ForeignKey(Product, on_delete=models.CASCADE,
                                related_name='product_releases')

class ReleaseNote(abstract_base_model_factory()):
    <additional fields>
    product_release = models.ForeignKey(ProductRelease, on_delete=models.CASCADE,
                                        related_name='release_notes')

I've followed the documentation to serialize these for returning JSON. I used the docs here to set up serialization of natural keys.

I can add the additional code, if needed, but it's mostly boilerplate and works with two models in play (ProductRelease and Product or ReleaseNote and ProductRelease). But it's not working with three models in play.

For example, if I serialize ProductRelease objects, I can see the Product and fields I specify:

{
  "product_releases": [
    {
      "model": "products.productrelease", 
      "pk": 7, 
      "fields": {
          "name": "Product Release A",
          "product": "prod1"
      }
    },
    { . . . },
  ]
}

However, I want to be able to serialize ReleaseNote objects, but then show the ProductRelease (first foreign key relation) and the Product (second foreign key relation) objects.

Can this be done in a single JSON response without using a package like Django REST Framework? I'd like to achieve this without requiring additional packages.

UPDATE

After some time, I realized that @oleksii was right. I ended up implementing Django REST Framework and got the nesting I needed. Works great.

nicorellius
  • 3,715
  • 4
  • 48
  • 79

1 Answers1

1

You can use nested model serializers for your purposes like this:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = "__all__"

class ProductReleaseSerializer(serializers.ModelSerializer):
    product = ProductSerializer(many=True)

    class Meta:
        model = ProductRelease
        fields = "__all__"


class ReleaseNoteSerializer(serializers.ModelSerializer):
    product_release = ProductReleaseSerializer()

    class Meta:
        model = ReleaseNote
        fields = "__all__"

release_note_model_instance = ReleaseNote.objects.all()
print(ReleaseNoteSerializer(release_note_model_instance, many=True).data)
Oleksii Tambovtsev
  • 2,666
  • 1
  • 3
  • 21
  • Do I want `many=True` on each, `ProductSerializer` and `ProductReleaseSerializer`, since there are potentially many for each of those relationships? Also, it seems `serializers.ModelSerializer` is part of Django REST Framework, no? I'm not using that package... – nicorellius Jan 13 '22 at 21:08
  • In your case, every `ReleaseNote` instance contains only one `ProductRelease` because `product_release` is a foreign key. Same for `ProductRelease` and `Product`. But in general, yes, you can use `many=True`. And yes, `ModelSerializer` is part of Django REST Framework. You can find documentation [here](https://www.django-rest-framework.org/api-guide/serializers/#modelserializer) – Oleksii Tambovtsev Jan 13 '22 at 22:58
  • Thanks. Since I'm not using Django REST Framework, your answer does not apply here. Do you know how to achieve what I'm after without DRF? I've considered using it, but right now I'm looking for a solution without requiring additional packages. – nicorellius Jan 14 '22 at 00:42
  • I suppose, the only solution for you then is to use [natural keys](https://docs.djangoproject.com/en/4.0/topics/serialization/#natural-keys). But I recommend to use Django REST Framework, it is the classic way to serialize complex structure objects in Django. – Oleksii Tambovtsev Jan 14 '22 at 00:56
  • As was stated in my original questions, I am using natural keys and followed the docs to get to where I'm at. I can use natural keys in the two-model scenario just fine (which is what the docs outline), but when I throw in a third, it gets complicated. I understand that Django REST Framework is the *de facto* method for serializing complex data, but I was hoping to get an answer to this without additional packages. Any advice is appreciated but I understand that this might be a tough one, as it's unusual to do with DRF. Thanks again for your time. – nicorellius Jan 14 '22 at 17:09