Search code examples
pythondjangomany-to-many

how can i select correctly many to many field django


I need to select 'changes' which related to sku id

I need help with views.py

models.py

Change

class Change (models.Model):
    raw_current = models.ForeignKey(Raw, blank=True, null=True, on_delete=models.CASCADE, related_name='raw_current')
    raw_new = models.ForeignKey(Raw, blank=True, null=True, on_delete=models.CASCADE, related_name='raw_new')
    created_date = models.DateTimeField(default=timezone.now)  # когда была создана заявка

    def __str__(self):
      return self.raw_current.num


    def publish(self):
        self.created_date = timezone.now()
        self.save()

Raw

class Raw (models.Model):
    num = models.CharField(max_length=200)  # артикул сырья
    name = models.CharField(max_length=200)  # наименование
    layer = models.CharField(max_length=200)  # название слоя на русском

    def __str__(self):
        return self.num +' ' + self.name

Sku

class Sku (models.Model):
    num = models.CharField(max_length=200)  # артикул готоваой продукции (ГП)
    name = models.CharField(max_length=200)  # наименование ГП
    raw = models.ManyToManyField(Raw, blank=True, null=True)  # сырье
    weight = models.IntegerField(blank=True, null=True)  # вес
    photo = models.ImageField(blank=True, null=True,
                              upload_to="images/")  # фото
    type = models.ForeignKey(ProductsTypes, blank=True, null=True, on_delete=models.CASCADE)
    def __str__(self):
        return self.num + ' ' + self.name

views.py

def change(request,sku_id):
    sku = Sku.objects.get(id=sku_id)
    list_change = Change.objects.filter(raw_current = sku.raw)
    return render(request, 'main/change.html', {'sku':sku,'list_change':list_change,'change':change,})

urls.py

   path('change/<sku_id>', views.change, name='change'),  

TypeError at /change/1

Field 'id' expected a number but got <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x10920d9f0>.

if in

views.py

def change(request,sku_id):     
sku = Sku.objects.get(id=sku_id)     
list_change = Change.objects.all()     
return render(request, 'main/change.html',{'sku':sku,'list_change':list_change,'change':change,})  

then i have the whole list but i need only changes belongs to selected sku

thanks for help


Solution

  • Because your raw field in Sku model is a ManyToManyField, you CANNOT do things like this:

    list_change = Change.objects.filter(raw_current = sku.raw)
    

    A ManyToManyField means that you can store not only one Raw in the Sku.raw field, and you can use sku.raw.all() to see all the Raws related to a specific sku object.

    You can see the official document here.

    Thus, if you want to filter all the Changes whose raw_current are equal to a bunch of Raws belongs to a sku, you can try something like this:

    list_change = Change.objects.filter(raw_current__in=sku.raw.all())