问题
In my online shop, I fetch all of the products and services from two different apps and list them for the user to make his wishlist.
Each product or service is displayed in a bootstrap card that contains an input field for the count of products.
#views.py
def my_products(request):
ip_sensor = Ip_sensor.objects.all().order_by('title')
control_valves = ControlValves.objects.all().order_by('title')
context = {
'ip_sensor': ip_sensor,
'control_valves': control_valves,
}
return render(request, 'users/basket/my_products.html', context)
then in the template, they are being displayed in this way:
<form method="post" id="add_to_wishlist" data-url="{% url 'my_products' %}">
{% csrf_token %}
{% if ip_sensor %}
{% for item in ip_sensor %}
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-12">
<p class="card-text text-center text-capitalize">{{ item.title }}</p>
</div>
<div class="col-12">
<div class="form-group">
<input type="hidden" name="tag" value="{{ item.type }}"> <!-- what to put in name field of this line -->
<input type="hidden" name="item_id" value="{{ item.id }}"> <!-- what to put in name field of this line -->
<label for="count" class="control-label">count</label>
<input type="text"
id="count"
name="count" <!-- what to put in name field of this line -->
placeholder="Count"
class="form-control"
autofocus/>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
{% endif %}
</form>
Question:
When I return the count of each product or service through a POST method back to my views.py
to save to his wishlist, I don't know how to distinguish between the returned values??
Since items are being displayed in a for loop and I want to save each of the selected items separately in a WishListItem
object (model), I need to name each card's input fields separately but I don't know how to do it.
I can save each item in this way:
if request.method == 'POST':
owner = request.user
count = request.POST.get('count')
tag = request.POST.get('tag')
object_id = request.POST.get('item_id')
wishlist = WishListItem(owner=owner,
content_type=class_types[tag],
object_id=object_id,
tag=tag,
count=count)
wishlist.save()
return redirect('my_products')
回答1:
When there are multiple inputs with same name, request.POST
has list of all those input element values. So, you can get all item ids using request.POST.getlist('item_id')
and it will return list containing all ids. In your html you can name all other inputs using id
as part of the name
attribute, like this:
...
<input type="hidden" name="tag_{{ item.id }}" value="{{ item.type }}"> <!-- item id has become part of the input name -->
<input type="hidden" name="item_id" value="{{ item.id }}"> <!-- all item ids will be accessed as list in view -->
<label for="count" class="control-label">count</label>
<input type="text"
id="count"
name="count_{{ item.id }}" <!-- item id has become part of the input name -->
placeholder="Count"
class="form-control"
autofocus/>
...
And in your view you can access all values like this:
...
for object_id in request.POST.getlist('item_id'): #this will contain a list with all item ids in it
count = request.POST.get('count_%s'%object_id) #as html inputs are named with ids as part of name you can access them
tag = request.POST.get('tag_%s'%object_id) #as html inputs are named with ids as part of name you can access them
wishlist = WishListItem(owner=owner,
content_type=class_types[tag],
object_id=object_id,
tag=tag,
count=count)
wishlist.save()
...
回答2:
I found the answer based on @datosula's answer.
since the product id may be repetitive because products are loaded from various tables, then a unique tag is required to distinguish returned values in views.py
. I mixed up product's title and products type to achieve this:
<div class="form-group">
<input type="hidden" name="title_type" value="{{ item.title }}{{ item.type }}">
<input type="hidden" name="item_id_{{ item.title }}{{ item.type }}" value="{{ item.id }}">
<input type="hidden" name="tag_{{ item.title }}{{ item.type }}" value="{{ item.type }}">
<input type="hidden" name="title_{{ item.title }}{{ item.type }}" value="{{ item.title }}">
<div class="text-center">
<input type="number"
id="count"
name="count_{{ item.title }}{{ item.type }}"
placeholder="count"
class="form-control"
value="0"
min="0"
max="9999"
autofocus/>
</div>
</div>
in views.py
I got the values and created the object like the following:
....
for item in request.POST.getlist('title_type'):
object_id = request.POST.get('item_id_%s'%item)
tag = request.POST.get('tag_%s'%item)
print('\ntag: ', tag )
print('\nclass_types[tag]: ', class_types[tag])
count = request.POST.get('count_%s'%item)
title = request.POST.get('title_%s'%item)
if count != '0': # only save those products that their count is not 0
wishlist = WishListItem(owner=owner,
content_type=class_types[tag],
object_id=object_id,
tag=tag,
count=count,
title=title)
wishlist.save()
....
wish it helps somebody
来源:https://stackoverflow.com/questions/65422388/how-to-name-numerous-dynamic-input-fields-for-post-method-django