Django 商品系统报错总结和处理

发布时间 2023-08-30 22:51:50作者: 九尾cat

Django 商品系统报错总结和处理

  针对上一章中,写的Django商品系统中间遇到很多问题,这里先总结一部分,后续继续总结遇到的问题。就个人而言,对于小白来说先简单实现所需的功能在进行优化,对于一些模版文件先实现简单的表单在添加css文件美化页面优化。

AttributeError: 'Product' object has no attribute 'photo'

new_product.photo.save('flows.jpg', File(photo_file), save=True)

AttributeError: 'Product' object has no attribute 'photo'

 

AttributeError: 'Product' object has no attribute 'photo' 错误通常是因为 Product 模型中没有定义名为 photo 的属性。添加了一个 photo 属性,它是一个 ImageField 类型。upload_to 参数指定了上传文件的存储路径,blank=True 表示该字段可以为空。然后你就可以使用 new_product.photo.save() 方法来保存图片了。你需要在 Product 模型中添加一个 photo 属性并指定其类型,例如:

class Product(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    price = models.DecimalField(max_digits=10, decimal_places=2)
    created_at = models.DateTimeField(auto_now_add=True)
    photo = models.ImageField(upload_to='product_photos/', blank=True)

    def __str__(self):
        return self.name

UnorderedObjectListWarning

UnorderedObjectListWarning: Pagination may yield inconsistent

results with an unordered object_list: <class 'goods.models.Product'> QuerySet.

paginator = Paginator(products, 6)

 

这个警告意味着您的查询结果是无序的,这可能会导致分页结果不一致。为了避免这个问题,您可以将查询结果按照某个字段进行排序

 products = Product.objects.order_by('id')
 paginator = Paginator(products, 6)

ImageField's 'upload_to' argument must be a relative path

ERRORS:

goods_service.Product.photo: (fields.E202) ImageField's 'upload_to' argument must be a relative path, not an absolute path.

HINT: Remove the leading slash.

goods_service.Product.video: (fields.E202) FileField's 'upload_to' argument must be a relative path, not an absolute path.

HINT: Remove the leading slash.

 

报错的原因是ImageField的'upload_to'参数必须是相对路径,而不是绝对路径。解决方法是移除路径开头的斜杠

    photo = models.ImageField(upload_to='/product_photos/', blank=True)
    video = models.FileField(upload_to='/product_videos/', blank=True)

## 修改为
    photo = models.ImageField(upload_to='product_photos/', blank=True)
    video = models.FileField(upload_to='product_videos/', blank=True)

django.db.migrations.exceptions.InconsistentMigrationHistory

django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency goods_service.0001_initial on database 'default'

回滚数据库:首先,您可以回滚数据库,将数据库恢复到迁移历史中的上一个正确状态。可以使用以下命令回滚数据库:

python manage.py migrate <app_name> <previous_migration>
python manage.py migrate goods_service zero

#然后重新应用迁移:
python manage.py migrate

重新创建迁移历史:如果回滚数据库后仍然存在问题,您可以尝试重新创建整个迁移历史。请按照以下步骤操作:

  • 删除数据库中的所有表(请备份数据)
  • 删除应用目录中的migrations目录下的所有文件,除了__init__.py文件
  • 使用以下命令创建新的迁移历史
python manage.py makemigrations <app_name>

python manage.py migrate

手动调整迁移顺序:如果您知道哪个迁移应该在另一个迁移之前应用,您可以手动调整它们的顺序。您可以编辑goods_service应用的migrations目录中的迁移文件,将其dependencies列表中的admin.0001_initial修改为正确的依赖关系。

例如,在goods_service应用的0001_initial.py文件中,您可以将以下行
('admin', '0001_initial'),

#修改为
('other_app', '0001_initial'),

#重新迁移应用
python manage.py migrate

NameError: name 'ProductForm' is not defined

NameError: name 'ProductForm' is not defined

原因是在代码中使用了一个未定义的变量或函数名。解决该错误的方法是确保变量或函数名已正确定义。

定义了一个名为ProductForm的表单类,并在create_product函数中实例化了该表单类。确保在使用ProductForm之前先定义了它,这样就不会再出现NameError: name 'ProductForm' is not defined的错误。

from django import forms

# 定义一个产品表单类
class ProductForm(forms.Form):
    name = forms.CharField(max_length=100)
    price = forms.DecimalField()
    description = forms.CharField(widget=forms.Textarea)

# 在其他地方使用ProductForm
def create_product(request):
    # 实例化ProductForm
    form = ProductForm(request.POST, request.FILES, instance=new_product)

        if form.is_valid():
            form.save()
            messages.success(request, '商品添加成功!')
            logger.info('用户%s添加商品%s成功' % (request.user.username, name))
            return redirect('home')
        else:
            messages.error(request, '商品添加失败!')
            logger.error('用户%s添加商品%s失败' % (request.user.username, name))
            return redirect('add_product')

 

TypeError: init() got an unexpected keyword argument 'auto_now_add'

因为在create_time字段上使用了auto_now_add=True参数,而DateField字段不支持此参数。

要解决这个问题,您可以将create_time字段更改为models.DateField(auto_now_add=True),然后在模型中使用该字段。

#报错的类
class ProductForm(forms.Form):
    name = forms.CharField(max_length=200)
    price = forms.DecimalField(max_digits=10, decimal_places=2)
    description = forms.CharField(max_length=1000, widget=forms.Textarea)
    photo = forms.ImageField()
    video = forms.FileField()
    create_time = forms.DateField(auto_now_add=True)
    update_time = forms.DateTimeField(auto_now=True)

##解决
##将create_time字段更改为models.DateField(auto_now_add=True)
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=200)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    description = models.CharField(max_length=1000)
    photo = models.ImageField()
    video = models.FileField()
    create_time = models.DateField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)

##使用ProductForm类来创建表单用于在视图中处理用户输入的数据
from django import forms
from .models import Product

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = '__all__'

## 在视图中使用ProductForm来处理表单数据
from django.shortcuts import render
from .forms import ProductForm

def create_product(request):
    if request.method == 'POST':
        form = ProductForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            # 处理表单成功提交后的逻辑
    else:
        form = ProductForm()
    
    return render(request, 'create_product.html', {'form': form})

##在模板中使用form渲染表单:
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">提交</button>
</form>

##就可以创建一个包含自动生成创建时间和更新时间的产品表单,并将用户输入的数据保存到数据库中。