表单对象没有属性“save_m2m”django
Posted
技术标签:
【中文标题】表单对象没有属性“save_m2m”django【英文标题】:Form object has no attribute 'save_m2m' django 【发布时间】:2017-10-27 03:45:27 【问题描述】:我在视图中遇到了一些问题,我创建了 CBV CreateView。所以它工作得很好,它保存了表单,但我有错误'ProductForm'对象没有属性'save_m2m,如果我不使用form.save_m2m,它不会将图像添加到我的产品中,但会将其添加到媒体中。
所以这里有model.py
class Product(models.Model):
class Meta:
verbose_name = 'Продукт'
verbose_name_plural = 'Продукты'
shop = models.ForeignKey(Shop, verbose_name='Название магазина')
category = models.ForeignKey(Category, verbose_name='Название категории')
title = models.CharField(max_length=255, verbose_name='Название товара')
slug = models.SlugField(_("Название на транслите"), max_length=50, unique=True, blank=True, null=True)
price = models.DecimalField(null=True, blank=True, verbose_name='Цена', decimal_places=0, max_digits=10)
sell_count = models.PositiveIntegerField(_("Количество продаж"), default=0, null=True, blank=True)
discount = models.PositiveIntegerField(null=True, blank=True, verbose_name='Скидка')
currency = models.CharField(null=True, max_length=255, verbose_name='Валюта', default='сом')
quantity = models.IntegerField(verbose_name='Количество', default=0)
delivery_type = models.CharField(verbose_name='Вид доставки', choices=DELIVERY_TYPES, default='self',
max_length=255)
delivery_cost = models.FloatField(verbose_name='Стоимость доставки', default=0, null=True, blank=True)
# settings = models.ManyToManyField('ProductSettings', verbose_name='Характеристика')
availability = models.CharField(_("Наличие"), max_length=100, choices=AVAILABILITY_TYPES, default='available')
published = models.BooleanField(default=True)
short_description = models.TextField(max_length=300, null=True, blank=True,
verbose_name='Короткое описание товара до 300 символов')
long_description = RichTextUploadingField(null=True, blank=True, verbose_name='Полное описание')
images = models.ManyToManyField('Media', verbose_name='Изображения продукта', blank=True)
objects = ProductPublishedManager()
class Media(models.Model):
class Meta:
verbose_name = "Изображение"
verbose_name_plural = "Изображения"
image = models.ImageField(upload_to='images')
这里有forms.py
class ProductForm(forms.ModelForm):
class Meta:
model = Product
exclude = ['slug', 'objects', 'sell_count']
removed_images = forms.CharField(required=False)
uploaded_images = forms.CharField(required=False)
def __init__(self, *args, **kwargs):
self.user = kwargs['initial']['user']
super(ProductForm, self).__init__(*args, **kwargs)
self.fields['shop'].queryset = Shop.objects.filter(user__in=[self.user.id])
for field in iter(self.fields):
self.fields[field].widget.attrs.update(
'class': 'form-control'
)
这里是views.py
class ProductCreateView(LoginRequiredMixin, AddProductMixin, CreateView):
form_class = ProductForm
template_name = 'product/product_form.html'
def get_success_url(self):
return reverse('shops:detail', args=(self.object.shop.slug,))
def get_initial(self):
return 'shop': Shop.objects.get(slug=self.kwargs['slug']),
'user': self.request.user
def form_valid(self, form, **kwargs):
product = form.instance
product.slug = slugify(form.instance.title)
product.shop = Shop.objects.get(slug=self.kwargs['slug'])
form.save()
if form.cleaned_data['uploaded_images']:
if ',' in form.cleaned_data['uploaded_images']:
for item in form.cleaned_data['uploaded_images'].split(','):
try:
media = Media.objects.get(id=int(item))
product.images.add(media)
except ObjectDoesNotExist:
pass
else:
try:
media = Media.objects.get(id=int(form.cleaned_data['uploaded_images']))
product.images.add(media)
except ObjectDoesNotExist:
print('error')
form.save_m2m()
if form.cleaned_data['removed_images']:
for item in form.cleaned_data['removed_images'].split(','):
try:
media = Media.objects.get(id=int(item))
image_path = MEDIA_ROOT + '/' + media.image.name
os.remove(image_path)
media.delete()
except ObjectDoesNotExist:
pass
return super(ProductCreateView, self).form_valid(form)
【问题讨论】:
我没有在你的代码中看到commit=False
。 Django 仅在 form.save(commit=False) 调用时添加 save_m2m 属性...
抱歉,如果我使用 form.save(commit=False),它会给出这个异常“对象需要有一个字段“产品”的值,然后才能使用这种多对多关系。”可能是我必须在另一个地方使用 form.save(commit=False),但我不知道我必须在哪里使用这个功能。
是的.. 做obj = form.save(commit=False)
然后做obj.save()
然后form.save_m2m()
这只是猜测。但是文档中提到了一些关于 save_m2m() is only required if you use save(commit=False)
的内容,当您在表单上使用简单的 save() 时,所有数据(包括多对多数据)都会被保存,而无需任何额外的方法调用。
是的!文档有,你说得对,但我不知道为什么它没有保存所有数据——包括多对多数据,好的,我会尝试保存对象。
【参考方案1】:
我重写了我的模型,向 Media 添加了新变量。在视图中我已经改变了
product.images.add(media)
到
product.media_set.add(media)
和我的模型
class Media(models.Model):
class Meta:
verbose_name = "Изображение"
verbose_name_plural = "Изображения"
image = models.ImageField(upload_to='images')
products = models.ManyToManyField(Product)
def __str__(self):
return self.image.url
在课堂产品中我删除了 var 图像
【讨论】:
【参考方案2】:这样试试
form.save(commit=False)
form.save_m2m()
【讨论】:
【参考方案3】:尝试像这样编辑您的视图,
def form_valid(self, form, **kwargs):
product = form.save(commit=False)
product.slug = slugify(form.instance.title)
product.shop = Shop.objects.get(slug=self.kwargs['slug'])
product.save()
if form.cleaned_data['uploaded_images']:
if ',' in form.cleaned_data['uploaded_images']:
for item in form.cleaned_data['uploaded_images'].split(','):
try:
media = Media.objects.get(id=int(item))
product.images.add(media)
except ObjectDoesNotExist:
pass
else:
try:
media = Media.objects.get(id=int(form.cleaned_data['uploaded_images']))
product.images.add(media)
except ObjectDoesNotExist:
# **Edited here**..
product.save_m2m()
if form.cleaned_data['removed_images']:
for item in form.cleaned_data['removed_images'].split(','):
try:
media = Media.objects.get(id=int(item))
image_path = MEDIA_ROOT + '/' + media.image.name
os.remove(image_path)
media.delete()
except ObjectDoesNotExist:
pass
return super(ProductCreateView, self).form_valid(form)
【讨论】:
我,尝试编辑代码,它没有将媒体图像添加到产品中,没有错误。但是当我添加 form.save_m2m() 时,它会将图像添加到产品中。但例外是 ProductForm 是对象没有属性 'save_m2m' django 我认为这是 django 的错误) 要让 form.save_m2m 工作,你需要做 form.save(commit=False),这可能是问题....编辑了代码 有什么例外? 我解决了,只是重写模型。对于 Media 类,添加了具有多对多字段的产品变量,并将 product.images.add(media) 中的视图重写到 product.media_set.add(media)以上是关于表单对象没有属性“save_m2m”django的主要内容,如果未能解决你的问题,请参考以下文章
无法将图像上传到 Django 项目,获取表单对象没有属性“保存”
Django CBV - Formsets:'NoneType'对象没有属性'id'