Reputation: 177
I am trying to create a user object in my Cart class in my models.py file. And I am receiving the following error:
user = models.ForeignKey(User, null=True, blank=True)
TypeError: __init__() missing 1 required positional argument: 'on_delete'
Can you help me add the required positional argument: on_delete in a proper way in oder to use the user object later while creating a cart session?
Thanks in advance.
In my carts app models.py I have the following code:
from django.conf import settings
from django.db import models
from django.db.models.signals import pre_save, post_save, m2m_changed
from products.models import Product
User = settings.AUTH_USER_MODEL
class CartManager(models.Manager):
def new_or_get(self, request):
cart_id = request.session.get("cart_id", None)
qs = self.get_queryset().filter(id=cart_id)
if qs.count() == 1:
new_obj = False
cart_obj = qs.first()
if request.user.is_authenticated and cart_obj.user is None:
cart_obj.user = request.user
cart_obj.save()
else:
cart_obj = Cart.objects.new(user=request.user)
new_obj = True
request.session['card_id'] = cart_obj.id
return cart_obj, new_obj
def new(self, user=None):
user_obj = None
if user is not None:
if user.is_authenticated:
user_obj = user
return self.model.objects.create(user=user_obj)
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True)
products = models.ManyToManyField(Product, blank=True)
subtotal = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
total = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = CartManager()
def __str__(self):
return str(self.id)
def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):
if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
products = instance.products.all()
total = 0
for x in products:
total += x.price
if instance.subtotal !=total:
instance.subtotal = total
instance.save()
m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.products.through)
def pre_save_cart_receiver(sender, instance, *args, **kwargs):
if instance.subtotal > 0:
instance.total = instance.subtotal
else:
instance.total = 0.00
pre_save.connect(pre_save_cart_receiver, sender=Cart)
Thanks,
Upvotes: 0
Views: 3590
Reputation: 1261
When working with ForeignKey
class, on_delete
parameter is required in __init__
. (It should be set explicitly) in Django
(2.0 for example). It was not required in Django
(1.8).
from django.conf import settings
from django.db import models
from django.db.models.signals import pre_save, post_save, m2m_changed
from products.models import Product
User = settings.AUTH_USER_MODEL
class CartManager(models.Manager):
def new_or_get(self, request):
cart_id = request.session.get("cart_id", None)
qs = self.get_queryset().filter(id=cart_id)
if qs.count() == 1:
new_obj = False
cart_obj = qs.first()
if request.user.is_authenticated and cart_obj.user is None:
cart_obj.user = request.user
cart_obj.save()
else:
cart_obj = Cart.objects.new(user=request.user)
new_obj = True
request.session['card_id'] = cart_obj.id
return cart_obj, new_obj
def new(self, user=None):
user_obj = None
if user is not None:
if user.is_authenticated:
user_obj = user
return self.model.objects.create(user=user_obj)
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE) # You should add on_delete=models.CASCADE argument
products = models.ManyToManyField(Product, blank=True)
subtotal = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
total = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = CartManager()
def __str__(self):
return str(self.id)
def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):
if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
products = instance.products.all()
total = 0
for x in products:
total += x.price
if instance.subtotal !=total:
instance.subtotal = total
instance.save()
m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.products.through)
def pre_save_cart_receiver(sender, instance, *args, **kwargs):
if instance.subtotal > 0:
instance.total = instance.subtotal
else:
instance.total = 0.00
pre_save.connect(pre_save_cart_receiver, sender=Cart)
Upvotes: 1
Reputation: 161
You are missing one required argument in the user field that is needed in ForeignKey
you can add this
on_delete=models.SET_NULL
or
on_delete=models.CASCADE
then the field will be
user = models.ForeignKey(User, null=True, related_name="author",
on_delete=models.SET_NULL)
or
user = models.ForeignKey(User, null=True, blank=True,
on_delete=models.CASCADE)
you can get more information about on_delete parameter at offical docs link
Upvotes: 1