thevengefulco
thevengefulco

Reputation: 309

Django Rest creating Nested-Objects (ManyToMany)

I looked for an answer to this question specifically for Django Rest, but I haven't found one anywhere, although I think a lot of people have this issue. I'm trying to create an object with multiple nested relationships but something is keeping this from happening. Here are my models for reference:

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True, null=True)
    tmp_password = models.CharField(max_length=32)
    photo = models.ImageField(upload_to='media/', blank=True, null=True)
    likes = models.IntegerField(blank=True, null=True)
    dislikes = models.IntegerField(blank=True, null=True)

    def __unicode__(self):
        return unicode(self.user.username)

class Item(models.Model):
"""Item Object Class"""
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=125, blank=True)
    price = models.FloatField(default=0, blank=True)
    rating = models.IntegerField(default=0, blank=True)
    description = models.TextField(max_length=300, blank=True)
    photo = models.ImageField(upload_to="media/", blank=True)
    barcode = models.CharField(max_length=20, blank=True)
    photo_url = models.URLField(max_length=200, blank=True)
    item_url = models.URLField(max_length=200, blank=True)

    def __unicode__(self):
        return unicode(self.name)


class Favorite(models.Model):
    user = models.OneToOneField(User, null=True)
    items = models.ManyToManyField(Item)

    def __unicode__(self):
        return unicode(self.user.username)

    def admin_names(self):
        return '\n'.join([a.name for a in self.items.all()])

And here are my serializers:

class ItemSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Item
        fields = ('id', 'name', 'price', 'description', 'rating', 'photo', 'barcode', 'photo_url','item_url' )


class FavoriteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Favorite
        exclude = ('id', 'user')


class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = UserProfile
        fields = ('likes', 'dislikes', 'photo', 'tmp_password')


class UserSerializer(serializers.HyperlinkedModelSerializer):
    userprofile = UserProfileSerializer()
    favorite = FavoriteSerializer()
    class Meta:
        model = User
        fields = (
            'id', 'username', 'url',
             'email', 'is_staff', 'password',
             'userprofile', 'favorite'
             )

    def create(self, validated_data):
        profile_data = validated_data.pop('userprofile')
        favorites_data = validated_data.pop('favorite')
        user = User.objects.create_user(**validated_data)
        user_profile = UserProfile.objects.create(user=user, **profile_data)
        favorite = Favorite(user=user)
        favorite.save()
        print favorite.items
        for item in favorites_data:
            favorite.items.add(item)
        print favorite.items
        return user

What I am having trouble with is the create() method on UserSerializer. What's happening is I can't .add() the data from favorites_data to the favorite object. I get an error saying invalid literal for int() with base 10: 'items'. I guess this makes sense, but if I try this instead of using the for loop:

favorite.items.add(**favorites_data)

I just get an error saying add() got an unexpected keyword argument 'items'. Finally, If I try this:

favorite.items.add(favorites_data)

I just get this error: unhashable type: 'OrderedDict'

What am I doing wrong in this approach? Obviously, favorites_data exist, but I'm not inserting it properly. Thanks for any help!

Upvotes: 2

Views: 1327

Answers (1)

ArtOfWarfare
ArtOfWarfare

Reputation: 21478

I think favorite.items.add expects you to pass in a single instance of an Item, so you should replace this:

for item in favorites_data:
    favorite.items.add(item)

With this:

for key in favorites_data:
    for item in favorites_data[key]:
        favorite.items.add(item)

Upvotes: 1

Related Questions