Igor
Igor

Reputation: 479

Problem with saving ManyToMany field data in intermediary models

First of all, sorry for my English.

I have this structure, idea is: Product can have many suppliers, and supplier himself have products

class Supplier(Model):
     title = CharField()

     def add_product(self, **kwargs):
            s2p = Stock(supplier=self, **kwargs)
            s2p.save()

class Product(Model):
    title = CharField()
    stock = ManyToManyField(Supplier, through="Stock")

class Stock(Model):
    in_stock = BooleanField()
    product = ForeignKey(Product, related_name="product_stock")
    supplier = ForeignKey(Supplier, related_name="supplier_stock")



# forms.py
class ProductForm(ModelForm):
    class Meta:
        model = Product

    stock = ModelChoiceField(queryset=Supplier.objects.all(), widget=CheckboxSelectMultiple)        


    # views.py
    def product_edit(request, product_id, template):
        if product_id:
            product = get_object_or_404(Product, pk=product_id)
            else:
            product = Product()

        if request.method == "POST":
            data = request.POST.copy()
            form = ProductForm(data, request.FILES, instance=product)
            if form.is_valid():
                prod = form.save(commit=False)
                if product.id:
                    prod.editedby = product.editedby
                else:
                    prod.createdby = request.user
                    prod.editedby = request.user
                prod.save()
                if "stock" in request.POST:
                    actions.clear_stock() 
                    suppliers = data.get('stock','')
                    for supplier in suppliers: 
                        supp = Supplier.objects.get(pk=supplier)
                        supp.add_product(product=prod)
        else:
            form = ProductForm(instance=product)

        dict = {
            'form': form,
        }

        return render_to_response(template, dict, context_instance=RequestContext(request))

    # actions.py
    def clear_stock():
        s2ps = Stock.objects.all()
        for s2p in s2ps:
            s2p.delete()

When i add product, it must be related to supplier(s), i use this type of logic:

  1. Parsing POST data field "stock", where IDs of supplier is stored
  2. Then in for loop i get instance for supplier by ID, which was previously get from POST, and stored in "suppliers"
  3. For each of "Supplier" i get instance by ID
  4. Then add them to database with Supplier.add_product model function

The problem is, that only last supplier from the list is added to database

Hope I explained the problem.

Upvotes: 1

Views: 351

Answers (2)

shadfc
shadfc

Reputation: 6594

Another solution is to change your form field to a ModelMultipleChoiceField. Then you would be able to iterate form.cleaned_data['stock'] which would give you the actual instances of Supplier which were selected. This avoids dealing with the POST QueryDict directly and also removes the need to do the Supplier queries "manually".

Upvotes: 2

Jordan Reiter
Jordan Reiter

Reputation: 21002

You want to change this:

data.get('stock','')

to this:

data.getlist('stock')

QueryDict.get('foo') only returns one value for foo, even if there are multiple values for foo. See the documentation for QueryDict.getlist().

Upvotes: 2

Related Questions