【问题标题】:ValueError at /cart/ Cannot assign "'admin'": "CartItem.user" must be a "User" instance/cart/ 处的 ValueError 无法分配“'admin'”:“CartItem.user”必须是“User”实例
【发布时间】:2021-02-03 01:23:13
【问题描述】:

我在尝试保存对象时收到 ValueError,该错误与将用户分配给模型有关。当我使用不带字符串方法(仅 user=request.user)时,它在 /cart/ 处显示 TypeError str 返回非字符串(用户类型) 当我应用字符串方法 (user=str(request.user)) 它给我 ValueError at /cart/ 无法分配“'admin'”:“CartItem.user”必须是“用户”实例。

views.py

from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
from django.contrib.auth import login, logout, authenticate
from django.db import IntegrityError
from .models import Book, CartItem
from django.contrib.auth.decorators import login_required
from .forms import BookForm
# Create your views here.
def signupuser(request):
    if request.user.is_authenticated:
        return render(request, 'main/alreadyloggedin.html')
    elif request.user != request.user.is_authenticated:
        if request.method == "GET":
            return render(request, 'main/signupuser.html', {'form':UserCreationForm()})
        elif request.method == "POST":
            if request.POST['password1'] == request.POST['password2']:
                try:
                    user = User.objects.create_user(request.POST['username'], password=request.POST['password1'])
                    user.save()
                    login(request, user)
                    return render(request, 'main/UserCreated.html')
                except IntegrityError:
                    return render(request, 'main/signupuser.html', {'form':UserCreationForm(), 'error':'That username has already been taken. Please choose a new username'})
            else:
                return render(request, 'main/signupuser.html', {'form':UserCreationForm(), 'error':'Passwords did not match'})

def signinuser(request):
    if request.user.is_authenticated:
        return render(request, 'main/alreadyloggedin.html', {'error':'You are already logged in'})
    elif request.user != request.user.is_authenticated:
        if request.method == "GET":
            return render(request, 'main/signinuser.html', {'form':AuthenticationForm()})
        elif request.method == "POST":
            user = authenticate(request, username=request.POST['username'], password=request.POST['password'])
            if user is None:
                return render(request, 'main/signinuser.html', {'form':AuthenticationForm(), 'error':'Username and password did not match'})
            else:
                login(request, user)
                return render(request, 'main/loggedin.html', {'error':'You are now logged in!'})
 
def logoutuser(request):
    if request.user.is_authenticated:
        if request.method == "GET": 
            return render(request, 'main/logoutuser.html')
        elif request.method == "POST":
            logout(request)
            return render(request, 'main/loggedin.html', {'error':'You are now logged out!'})
    elif request.user != request.user.is_authenticated:
        return render(request, 'main/alreadyloggedin.html', {'error':'You are not logged in'})
    

def home(request):
    books = Book.objects.all()
    return render(request, 'main/home.html', {'books':books})


@login_required
def addtocart(request):
    if request.method == 'POST':
        bookid = CartItem.objects.get(pk=request.POST['bookid'])
        form = CartItem.objects.create(book=bookid, user=str(request.user), commit=False)
        newCartItem = form.save(commit=False)
        newCartItem.user = request.user
        newCartItem.save()
        return redirect('home')
    elif request.method == 'GET':
        return render(request, 'main/signinuser.html', {'form':BookForm})

                                            



home.html

<h1>Here are products</h1>
{% for book in books %}
<h3>{{ book.name }}</h3>
<img src= "/media/{{ book.image }}" alt="">
<p>{{ book.description }}</p>
<form method="POST" action="/cart/">
    {% csrf_token %}
    <button type="submit" name="bookid" value="{{ book.id }}">Add to cart</button>
</form>
{% endfor %}

urls.py

"""EBook URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.conf.urls.static import static
from django.conf import settings
from core import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('signup/', views.signupuser, name='signupuser'),
    path('login/', views.signinuser, name='signinuser'),
    path('logout/', views.logoutuser, name='logoutuser'),
    path('', views.home, name='home'),
    path('cart/', views.addtocart, name='cart'),
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

models.py

from django.db import models
from django.contrib.auth.models import User
# Create your models here.

class Category(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'Category'
        verbose_name_plural = 'Categories'


class Book(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    image = models.ImageField()
    price = models.IntegerField()
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return self.name

class Order(models.Model):
    order_id = models.CharField(max_length=500)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return self.user

class CartItem(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return self.user

forms.py

from django.forms import ModelForm
from .models import CartItem

class BookForm(ModelForm):
    class Meta:
        model = CartItem
        fields = ['book', 'user']

【问题讨论】:

  • 如果您需要非登录/访客用户更新购物车,您需要删除@login_required 装饰器
  • 您出于某种原因正在使用模型创建方法,例如表单?请显示您在获取方法的上下文中传递的 BookForm 代码
  • from django.forms import ModelForm from .models import CartItem class BookForm(ModelForm): class Meta: model = CartItem fields = ['book', 'user']
  • 我目前没有使用 forms.py tho
  • 我是通过账号登录的

标签: python django


【解决方案1】:

您似乎在使用表单,然后在更改代码后使用模型创建方法,就像它是表单一样,还使用书籍 ID 来获取 CartItem?像这样改变你的观点:

@login_required
def addtocart(request):
    if request.method == 'POST':
        try:
            book = Book.objects.get(pk=request.POST['bookid'])
        except Book.DoesNotExist:
            return redirect('home')
        cart_item = CartItem.objects.create(book=book, user=request.user)
        return redirect('home')
    elif request.method == 'GET':
        return render(request, 'main/signinuser.html', {})

我从上下文中删除了表单,因为它看起来好像你没有使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-03
    • 1970-01-01
    • 2018-06-30
    • 2017-07-05
    • 2020-04-22
    • 2019-11-14
    • 2020-04-04
    相关资源
    最近更新 更多