Home > Enterprise >  serialize self-referential foreign key
serialize self-referential foreign key

Time:07-06

Lets say I want to create an article that links via slug to one or multiple other articles (for now one). A post request comes in giving me some article-info and the related slug. I want to

  1. validate the data and the related slug
  2. create an article in the db
  3. return the article (with the slug)

models.py

class Article(models.Model):
        heading = models.CharField(max_length=2550)
        slug = models.SlugField(null=True, default=None, unique=True, max_length=255)
        article_previous = models.ForeignKey('self', to_field='slug', blank=True, null=True, 
        related_name='subcategories', on_delete=models.DO_NOTHING)

serializers.py

class ArticleSerializer(serializers.ModelSerializer):

    class Meta:
        model = Article
        fields = (
            "heading",
            "slug",
            "article_previous",

    def create(self, validated_data):
        try:
            article_previous = Article.objects.get(slug=d['value'])
            article_previous_slug = article_previous.slug
        except Article.DoesNotExist:
            raise serializers.ValidationError(f'No Article with the slug {d["value"]}')
        
        article=Article.objects.create(**validated_data,article_previous_id=article_previous_slug)
        return validated_data

This solution gives:

article_previous = serializers.CharField()

ValueError: Cannot assign "'test_1'": "Article.article_previous" must be a "Article" instance.

This solution gives:

article_previous = serializers.CharField('article.article_previous')

TypeError: Article() got an unexpected keyword argument 'article'

If I use serializer.validated_data in views.py:

return Response(serializer.validated_data, status=status.HTTP_201_CREATED, headers=headers)
response = serializer.save()
return Response(response, status=status.HTTP_201_CREATED, headers=headers)

TypeError: Object of type Article is not JSON serializable.

CodePudding user response:

You can serialize the slug by working with the article_previous_id field:

class ArticleSerializer(serializers.ModelSerializer):
    article_previous = serializers.CharField(source='article_previous_id')

    class Meta:
        model = Article
        fields = ('heading', 'slug', 'article_previous')

    # …
  • Related