Cannot successfully pass foreign_key reference to PUT request in Django REST

I am getting into Django REST and I am trying to use it for a backend of type of crypto currency tracker for my use. However I have been stuck on an issue for a few days..

I have the following models.py:

class Coin(models.Model):
    sign = models.CharField(max_length=50, primary_key=True)    # capitalize all entries
    name = models.CharField(max_length=50, null=False)
    amount = models.DecimalField(max_digits=20, decimal_places=2, null=False)
    price_each = models.DecimalField(max_digits=20, decimal_places=2, null=False)
    purchased_on = models.DateField(null=True)

    def __str__(self):
        return self.sign

    def save(self, *args, **kwargs):
        self.sign = self.sign.upper()
        return super(Coin, self).save(*args, **kwargs)

class Price(models.Model):
    coin = models.ForeignKey(Coin, related_name="prices", on_delete=models.CASCADE)
    day_date = models.DateField(null=False)
    current_price = models.DecimalField(max_digits=20, decimal_places=2, null=False)

    def __str__(self):
        timestamp = self.day_date.strftime("%d-%b-%Y")

        return timestamp

and serializers.py:

class PriceSerializer(serializers.ModelSerializer):
    coin_sign = serializers.PrimaryKeyRelatedField(queryset=Coin.objects.all(), source='coin.sign')

    class Meta:
        model = Price
        fields = ['id', 'day_date', 'current_price', 'coin_sign']
    
    def create(self, validated_data):
        return Price.objects.create(**validated_data)


class CoinSerializer(serializers.ModelSerializer):
    prices = PriceSerializer(many=True, read_only=False)

    class Meta:
        model = Coin
        fields = ['sign', 'name', 'amount', 'price_each', 'purchased_on', 'prices']

    def create(self, validated_data):
        return Coin.objects.create(**validated_data)

I am having trouble defining a view with PUT to create a new price entry in view.py:

class AddPrice(APIView):
    def put(self, request, sign, format=None):
        coin = get_object_or_404(Coin, sign=sign.upper())
        request.data['coin_sign'] = coin
        serializer = PriceSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Here is the URL where I try to hit the PUT endpoint: http://127.0.0.1:8000/crypto/coins/cro/add_price/ with following body: { "day_date": "2021-12-04", "current_price": "420.69" }

and the urlpattern from my_app/urls.py:

path('', views.index, name='index'),    # http://127.0.0.1:8000/crypto/
path('coins/', views.Coins.as_view(), name='all_coins'),
path('coins/<str:sign>/', views.CoinInfo.as_view(), name='coin_info'),
path('coins/<str:sign>/add_price/', views.AddPrice.as_view(), name='add_price'),

I understand that I am passing a an object's representation of itself with that instead of the actual object and I cannot link the Price to the Coin properly because of that:

Cannot assign "{'sign': <Coin: CRO>}": "Price.coin" must be a "Coin" instance.

How do I create a Price entity from the endpoint successfully?

Thank you for reading!

Back to Top