0

J'ai des problèmes de forme dans les vues, j'ai créé CBV CreateView. Donc ça marche bien et ça économise le formulaire mais j'ai l'erreur 'ProductForm' l'objet n'a pas d'attribut 'save_m2m, si je n'utilise pas form.save_m2m il n'ajoutera pas d'images à mon produit, mais l'ajoutera au média.L'objet de formulaire n'a pas d'attribut 'save_m2m' django

Nous avons donc ici 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') 

Ici j'ai 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' 
      }) 

Et voici 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) 
+0

Je n'ai pas vu 'commit = False' dans votre code. Django n'ajoute l'attribut save_m2m que lorsque form.save (commit = False) s'appelle ... –

+0

o désolé, si j'utilise form.save (commit = False), cela donne cet exeption "l'objet doit avoir une valeur pour le champ" produit " avant cette relation many-to-many peut être utilisé. " peut être que je dois utiliser form.save (commit = False) dans un autre endroit, mais je ne sais pas où je dois utiliser cette fonction. –

+0

yes .. fais 'obj = form.save (commit = False)' alors fais 'obj.save()' alors 'form.save_m2m()' –

Répondre

0

Tentez de modifier votre point de vue comme celui-ci ,

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) 
+0

It didn't travaillé –

+0

Y at-il une erreur? Ou est-ce simplement ne pas économiser? – zaidfazil

+0

J'ai édité le code – zaidfazil

0

Essayez comme ça

form.save(commit=False) 
form.save_m2m() 
0

i ve rewrote my model with adding new varialble to Media. And in view i ai changé de

product.images.add(media) 

à

product.media_set.add(media) 

et Mon modèle

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 

in class Produit i supprimé var images