I have 2 models:
models.py:
class Item(models.Model):
name = models.CharField(max_length=100)
price = models.FloatField(max_length=20)
shelfLife = models.BooleanField()
def __str__(self):
return self.name
@property
def shL(self):
temp = "Doesnt' have shelf life"
if(self.shelfLife):
temp = "Does have sehlf life"
return temp
class Order(models.Model):
num = models.CharField(max_length=20)
date = models.DateField()
items = models.ManyToManyField(Item)
def __str__(self):
return self.num
according to this doc I can do:
views.py:
elif request.method == "POST":
list_items = request.POST.getlist('arr[]') # get list of items
order_num = request.POST.getlist('o_n') # get order num
order_date = request.POST.getlist('o_d') # get order date
order = Order(num=order_num[0], date=order_date[0])
order.save()
for i in range(len(list_items)):
item_name = str(list_items[i])
item = Item.objects.filter(name=item_name)
order.items.add(item)
To fetch each item that I need, I loop through the list_items
list of strings and filter each object request by this string and then just add the item to the many-to-many field of the order model.
In addition, when I fetch
item = Item.objects.filter(name="Salad")
the returned QuerySet is not empty, however, if I pass a string variable to the name
filter it returns an empty QuerySet.
I would appreciate any help! Thanks
EDIT: As @Willem Van Onsem sudjested I chaned my views.py to:
elif request.method == "POST":
list_items = request.POST.getlist('arr[]') # get list of items
order_num = request.POST.getlist('o_n') # get order num
order_date = request.POST.getlist('o_d') # get order date
order = Order(num=order_num[0], date=order_date[0])
order.save()
items = Item.objects.filter(name__in=list_items)
order.items.add(*items)
However, I still get a QuerySet items
as an empty QuerySet.
I have checked the request variable list_tems
and it is a list of strings (it's not empty).
I tested it by creating an array of Strings
arr=["Salad", "Chocolate"]
and paste it as a filter
items = Item.objects.filter(name__in=arr)
order.items.add(*items)
to the QuerySet and it works - QuerySet object items
is not empty and it writes the right data to the DB.
index.html:
$(document).on('click','.btn-create-order',function(){
$.ajax({
method: "GET",
contentType: "application/json",
url: "{% url 'order-items api' %}",
success: function(data){
var index = 1;
data.forEach(element => {
$('#multyItemSelect').append("<option value='" + index + "' id='" +index+ "'> "+ element['fields'].name+"</option>")
index++;
});
},
error: function(jqXHR, textStatus, errorThrown){}
})
})
$('.order-new-submit').click(function(){
var order_num = $('#InputNumber').val()
var order_date = $('#InputDate').val()
var item_selected = $('#multyItemSelect').val() // number
var arr = [] // arr for the item names
var index = 0;
item_selected.forEach(e => {
arr[index] = $('#' + e).html()
index++
});
console.log(order_date)
// DEBUGIN
// arr.forEach(e => {
// console.log(e)
// });
// END DEBUGIN
$.ajax({
method: "POST",
url: "{% url 'order-items api' %}",
data: {'arr[]': arr,
'o_n' : order_num,
'o_d' : order_date},
success: function(data){
},
error: function(jqXHR, textStatus, errorThrown){}
})
})
Thanks to @Willem Van Onsem the issue has been found:
print(list_items)
prints values with space at the beginning:
[' Salad', ' Beef Stake ', ' Chocolate']
item
in order.items.add(…)
needs to be a model object, or the primary key of that model, but not a queryset. You can however make use of iterable unpacking to pass the items wrapped in the QuerySet
as individual parameters:
for i in range(len(list_items)):
item_name = str(list_items[i])
items = Item.objects.filter(name=item_name)
order.items.add(*items) # ← with an asterisk (*)
You can boost efficiency by fetching all the Item
s in one query with:
items = Item.objects.filter(name__in=[str(x) for x in list_items])
order.items.add(*items)