Поле 'id' ожидало число, но получило '(string)
Я создаю магазин футболок с вариантами/цветами. При добавлении в корзину я получаю ошибку: Поле 'id' ожидало число, но получило 'Woodstock'. Woodstock - это название футболки, но я передаю cartid в функцию. cartid фактически используется в функции remove_from_cart, но я не уверен, почему ошибка возникает, когда я нажимаю кнопку add to cart. Вот модель корзины:
class Cart(models.Model):
#user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
total = models.DecimalField(max_digits=100, decimal_places=2, default=0.00)
timestamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
def __str__(self):
return "Cart id: %s" %(self.id)
class CartItem(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null=True, blank=True)
product = models.ForeignKey(Product,on_delete=models.CASCADE)
variations = models.ManyToManyField(Variation, blank=True)
quantity = models.IntegerField(default=1)
line_total = models.DecimalField(default=10.99, max_digits=100, decimal_places=2)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
try:
return str(self.cart.id)
except:
return self.product.name
views.py
def view(request):
print("viewing cart")
try:
the_id = request.session['cart_id']
except:
the_id = None
if the_id:
cart = Cart.objects.get(id=the_id)
new_total = 0.00
for item in cart.cartitem_set.all():
line_total = float(item.product.price) * item.quantity
new_total += line_total
request.session['items_total'] = cart.cartitem_set.count()
cart.total = new_total
cart.save()
context = {"cart":cart}
else:
empty_message = "Your cart is empty, please keep shopping"
context = {"empty": True, "empty_message": empty_message}
template = "cart/view.html"
return render(request, template, context)
def add_to_cart(request, slug):
print("add_to_cart pressed")
request.session.set_expiry(100000000)
try:
the_id = request.session['cart_id']
except:
#create cart id
new_cart = Cart()
new_cart.save()
request.session['cart_id'] = new_cart.id
the_id = new_cart.id
cart = Cart.objects.get(id=the_id)
try:
product = Product.objects.get(slug=slug)
except Product.DoesNotExist:
pass
except:
pass
product_variations = []
if request.method == 'POST':
qty = request.POST['qty']
for item in request.POST:
key = item
val = request.POST[key]
try:
v = Variation.objects.get(product=product, category__iexact=key, title__iexact=val)
product_variations.append(v)
except:
pass
cart_item = CartItem.objects.create(cart=cart, product=product)
if len(product_variations) > 0:
cart_item.variations.add(*product_variations)
cart_item.quantity = qty
cart_item.save()
print("cart item added")
return HttpResponseRedirect(reverse("carts:cart"))
return HttpResponseRedirect(reverse("carts:cart"))
def remove_from_cart(request, id):
print(id) #this is showing the item name, the reason it's not working. Either traced back to html view or urls.py
try:
the_id = request.session['cart_id']
cart = Cart.objects.get(id=the_id)
except:
return HttpResponseRedirect(reverse("carts:cart"))
cartitem = CartItem.objects.get(id=id)#error is traced to this line
cartitem.cart = None
cartitem.save()
return HttpResponseRedirect(reverse("carts:cart"))
html
{% block content %}
<div class="col-sm-8 offset-sm-2">
{% if empty %}
<h1 style="text-align:center;">{{ empty_message }}</h1>
{% else %}
<table class="table">
<thead>
<th>Item</th>
<th>Price</th>
<th>Qty</th>
<th></th>
</thead>
<tfoot>
<tr>
<td></td>
<td></td>
<td>Total: {{ cart.total }}</td>
</tr>
</tfoot>
{% for item in cart.cartitem_set.all %}
<tr>
<td>{{ item.product }}
{% if item.variations.all %}
<ul>
{% for var in item.variations.all %}
<li> {{ var.category|capfirst }} : {{ var.title|capfirst }}</li>
{% endfor %}
</ul>
{% endif %}
</td>
<td>{{ item.product.price }}</td>
<td>{{ item.quantity }}</td>
<td><a href='{% url "carts:remove_from_cart" item.id %}'>Remove</a></td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
{% endblock %}
urls.py для cart
app_name='carts'
urlpatterns =[
path('cart/', views.view, name='cart'),
path('cart/<id>/', views.remove_from_cart, name='remove_from_cart'),
path('cart/<slug:slug>/', views.add_to_cart, name='add_to_cart'),
]
При исследовании этой проблемы было предложено удалить миграции и запустить makemigrations/migrate, но у меня это не сработало. Любые другие предложения или почему item.id передает имя, а не id?
Ваш url-путь remove_from_cart
соответствует путям типа cart/<id>/
, где id
не имеет типа, поэтому соответствует чему угодно, путь add_to_cart
использует cart/<slug:slug>/
, но поскольку любой slug будет также соответствовать id
из предыдущего пути, этот вид никогда не будет использоваться. Вам нужно сделать эти пути уникальными, чтобы они никогда не совпадали с одним и тем же путем.
Один из способов - сделать id
целым числом, чтобы слизни не совпадали с ним
path('cart/<int:id>/', views.remove_from_cart, name='remove_from_cart'),
path('cart/<slug:slug>/', views.add_to_cart, name='add_to_cart'),
Лучшим способом является добавление префиксов к этим путям, чтобы они никогда не сталкивались
path('cart/remove/<int:id>/', views.remove_from_cart, name='remove_from_cart'),
path('cart/add/<slug:slug>/', views.add_to_cart, name='add_to_cart'),