Django serializer.save() gives back a HTTP 500 error response

Question:

I have the following straightforward setup: a folder order with a models.py file,

from django.contrib.auth.models import User
from django.db import models
from product.models import Product

class Order(models.Model):
  user = models.ForeignKey(User, related_name='orders', on_delete=models.CASCADE)
  first_name = models.CharField(max_length=100)
  last_name = models.CharField(max_length=100)
  email = models.CharField(max_length=100)
  address = models.CharField(max_length=100)
  zipcode = models.CharField(max_length=100)
  place = models.CharField(max_length=100)
  phone = models.CharField(max_length=100)
  created_at = models.DateTimeField(auto_now_add=True)
  paid_amount = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
  stripe_token = models.CharField(max_length=100)

  class Meta:
    ordering = ['-created_at',]

  def __str__(self):
    return self.first_name

class OrderItem(models.Model):
  order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE)
  product = models.ForeignKey(Product, related_name='items', on_delete=models.CASCADE)
  price = models.DecimalField(max_digits=8, decimal_places=2)
  quantity = models.IntegerField(default=1)

  def __str__(self):
    return '%s' % self.id

a serializers.py file

from rest_framework import serializers
from .models import Order, OrderItem

class OrderItemSerializer(serializers.ModelSerializer):
  class Meta:
    model = OrderItem
    fields = [
      "price",
      "product",
      "quantity",
    ]

class OrderSerializer(serializers.ModelSerializer):
  items = OrderItemSerializer(many=True)

  class Meta:
    model = Order
    fields = [
      "id",
      "first_name",
      "last_name",
      "email",
      "address",
      "zipcode",
      "place",
      "phone",
      "stripe_token",
      "items",
    ]

  def create(self, validated_data):
    items_data = validated_data.pop('items')
    order = Order.objects.create(**validated_data)

    for item_data in items_data:
      OrderItem.objects.create(order=order, **item_data)

    return order

and finally, a views.py file

import stripe

from django.conf import settings # get secret key
from rest_framework import status, authentication, permissions
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.response import Response

from .serializers import OrderSerializer

@api_view(['POST'])
@authentication_classes([authentication.TokenAuthentication])
@permission_classes([permissions.IsAuthenticated])
def checkout(request):

  serializer = OrderSerializer(data=request.data)

  if serializer.is_valid():
    stripe.api_key = settings.STRIPE_SECRET_KEY
    paid_amount = sum(item.get('quantity') * item.get('product').price for item in serializer.validated_data['items'])

    charge = stripe.Charge.create(
    amount=int(paid_amount * 100),
    currency='USD',
    description='Charge from Djackets',
    source=serializer.validated_data['stripe_token']
    )

    serializer.save(user=request.user, paid_amount=paid_amount) 
    return Response(serializer.data, status=status.HTTP_201_CREATED)

  return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Now trying to post to checkout gives the 500 response with the following error trace:

Traceback (most recent call last):
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbbackendsutils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbbackendssqlite3base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: table order_order has no column named paid_amount

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangocorehandlersexception.py", line 55, in inner
    response = get_response(request)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangocorehandlersbase.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangoviewsdecoratorscsrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangoviewsgenericbase.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesrest_frameworkviews.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesrest_frameworkviews.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesrest_frameworkviews.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesrest_frameworkviews.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesrest_frameworkdecorators.py", line 50, in handler
    return func(*args, **kwargs)
  File "C:Larrydjango-vue-tutorialdjackets_djangoorderviews.py", line 35, in checkout      
    serializer.save(user=request.user, paid_amount=paid_amount)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesrest_frameworkserializers.py", line 212, in save
    self.instance = self.create(validated_data)
  File "C:Larrydjango-vue-tutorialdjackets_djangoorderserializers.py", line 37, in create  
    order = Order.objects.create(**validated_data)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbmodelsmanager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbmodelsquery.py", line 514, in create
    obj.save(force_insert=True, using=self.db)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbmodelsbase.py", line 806, in save
    self.save_base(
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbmodelsbase.py", line 857, in save_base
    updated = self._save_table(
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbmodelssqlcompiler.py", line 1621, in execute_sql
    cursor.execute(sql, params)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbbackendsutils.py", line 103, in execute
    return super().execute(sql, params)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbbackendsutils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbbackendsutils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbbackendsutils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbutils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbbackendsutils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "C:Larrydjango-vue-tutorialmyenvlibsite-packagesdjangodbbackendssqlite3base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: table order_order has no column named paid_amount[27/Jul/2022 12:34:17] "POST /api/v1/checkout/ HTTP/1.1" 500 206511

This code originates from a Youtube tutorial that does not explain a whole lot of what is going on. My question is: How to resolve this error?

Thanks in advance!

Asked By: Larry

||

Answers:

As the error message says, you don’t have paid_amount column in the order_order table. If you changed the DB model definition, you need to make a migration and apply it first.

python manage.py makemigrations && python manage.py migrate

Answered By: abcdn

So as stated in the comments running:
python manage.py makemigrations and python manage.py migrate did not resolve my problem. It simple gives back that there are no migrations.

I did solve the problem by, similar to switching the on/off button, commenting out the paid_amount column on my model and doing the proper migrations. Then, I uncommented the paid_amount column did the migrations and then it suddenly worked. I did not change anything to the code so I have no idea why he gave back an error in the first place.

Thanks to all who tried to help, kind of feel bad since in the end a single on/off switch (to the order table) did the trick. But as I said, I’m still learning.

Answered By: Larry