List(array) of HTML element with django 2.0.6 - html

I'm passing a list of HTML element to the views.py from html through post but Im just getting the last value.
here is the html code that i used, multiple lines of this one
<input name="idborrow[]" id="borrow" value='+element[i].id+'>
and here is my code in the views.py
if request.method == 'POST':
idborrow = request.POST.get('idborrow[]', '')
print (idborrow)
in the console, it just prints the last value, how to get the whole list of values

Try using getlist
Ex:
request.POST.getlist('idborrow[]')

Related

How to easily extract request.POST data after Django form submission?

My request.POST data looks like this after my Django form submission:
<QueryDict: {'form-0-country': ['19389'], 'form-0-city': ['Montreal'], 'form-0-eid': ['450'], 'form-0-company': ['Nestle'], 'form-0-dept': ['HR'], 'form-1-country': ['19390'], 'form-1-city': ['Toronto'], 'form-1-eid': ['432'], 'form-1-company': ['Nestle'], 'form-1-dept': ['Finance']}>
These are values of two forms contained in two different rows on the webpage. The values from these two rows are printed sequentially in the request.POST. Is there a way to get this data printed in the backend in a simpler way so that I don't have to loop through all this data to extract the specific fields contained in it?
For eg. something like this:
<QueryDict: {'form-0-country': ['19389','19390'], 'form-0-city': ['Montreal','Toronto'], 'form-0-eid': ['450'], 'form-0-company': ['Nestle','Nestle'], 'form-0-dept': ['HR','Finance']>
so that I can easily loop through the value (lists) in the dict above.
instead of:
<QueryDict: {'form-0-country': ['19389'], 'form-0-city': ['Montreal'], 'form-0-eid': ['450'], 'form-0-company': ['Nestle'], 'form-0-dept': ['HR'], 'form-1-country': ['19390'], 'form-1-city': ['Toronto'], 'form-1-eid': ['432'], 'form-1-company': ['Nestle'], 'form-1-dept': ['Finance']}>
Here is my code snippet:
if request.method == 'POST':
form = CreationForm(request.POST)
if form.is_valid():
form.save()
print(form.cleaned_data)```
You can use cleaned_data to extract the values from your form.
For example:
country = form.cleaned_data["country"]
city = form.cleaned_data["city"]
You should print form instead of printing request.POST
e.g.
def your_view(request):
if request.method == 'POST':
form = YourForm(request.POST)
if form.is_valid():
print(form.cleaned_data)
...
...
...

How to loop through all items in xpath

I'm new to both xpath and html so I'm probably missing something fundamental here. I have a html where I want to extract all the items displayed below. (I'm using scrapy to do my requests, I just need the proper xpath to get the data)
enter image description here
Here I just want to loop through all these items and from there and get some data from inside each item.
for item in response.xpath("//ul[#class='feedArticleList XSText']/li[#class='item']"):
yield {'name': item.xpath("//div[#class='intro lhNormal']").get()}
The problem is that this get only gives me the first item for all the loops. If I instead use .getall() I then get all the items for every loop (which in my view shouldn't work since I thought I only selected one item at the time in each iteration). Thanks in advance!
It seems you're missing a . in your XPath expression (to "indicate" you're working from a context node).
Replace :
yield {'name': item.xpath("//div[#class='intro lhNormal']").get()}
For :
yield {'name': item.xpath(".//div[#class='intro lhNormal']").get()}
You do miss smth. fundamental. Python by default does not have xpath() function.
You better use bs4 or lxml libraries.
See an example with lxml:
import lxml.html
import os
doc = lxml.html.parse('http://www.websters-online-dictionary.org')
if doc:
table = []
trs = doc.xpath("/html/body/div[1]/div[1]/table[1]/tbody/tr")
for tr in islice(trs, 3):
for td in tr.xpath('td'):
table += td.xpath("/b/text() | /text()")
buffer = ''
for i in range(len(table)):
buffer += table[i]
the full explanation is here.

How can I use pagination when I am using a form to input a date and submitting that form sends a post request and pagination accepts get request?

I am using django to display a webpage. I want to display details of files from database. These files can be of any number. I am using a form to input a date from HTML file which is accepted by a django view function. This function checks if the request is of type POST and returns the data between the mentioned date. Now when I use pagination to display these pages, pressing the next doesn't show anything as this time the request gets changed to GET. In my django view function, data is fetched in a list. Every file's data is in a list. So, all the data consists lists of lists. How will I be able to display these lists using pagination without sending the requests again. Is it possible to do so?
My data is stored in a database according to dates. I am fetching the data in a given range. This range comes from html page. Here is how I am trying to fetch the details:
<div class="container">
<form method="POST">
{% csrf_token %}
<input type="date" name="start_date">
<input type="date" name="end_date">
<button type="Submit">Get Details</button>
</form>
</div>
This is the code that I use at the backend to serve the webpage.
def data_range(request):
if request.method == 'POST':
form = Form(request.POST)
try:
if form.is_valid():
start_date = form.data.get('start_date')
end_date = form.data.get('end_date')
page_data = get_page_details(start_date, end_date)
else:
current_date = datetime.datetime.now()
start_date = end_date = current_date.strftime("%Y-%m-%d")
page_data = get_page_details(start_date, end_date)
except Exception:
return render(request, 'UserInterface/no_data_fort.html', {'list_item_count': 0})
else:
return render(request, 'UserInterface/no_data_fort.html', {'list_item_count': 0})
if page_data:
# Calculating total files in fortnightly data
list_item_count = len(page_data)
# Adding Paginator or pagination
paginator = Paginator(page_data, 1)
page = request.GET.get('page')
data = paginator.get_page(page)
return render(request, 'UserInterface/fortnightly_range.html', {'page_data_list': data, 'list_item_count': list_item_count})
else:
return render(request, 'UserInterface/no_data_fort.html', {'list_item_count': 0})
page_data that I fetch is a list of lists.

Django Template render dictionary values into html form using Function Based View

Summary
Using Django 1.8, I'm trying to make a Function Based View that renders an html page that allows me to update the contents of the object. I'm able to get this to work by using the form.as_p as shown in the documentation here, but I can't get these values inside an html <input> as the value.
Issue
The issue is that only the first word appears and the rest of the text is cut off (e.g. for a html input tag, the value of 'Hello World Will' gets turned into 'Hello')
model.py
class Questions(model.Model):
title = models.CharField(max_length=512, null=False, blank=False)
forms.py
class QuestionsForm(forms.ModelForm):
class Meta:
model = Questions
fields = ('title', )
views.py
def advice_update(request, pk)
question_results = Questions.object.get(id=pk)
advice_form = QuestionsForm(request.POST or None, instance=question_results)
...
return render(request, 'advice/advice_update.html', {'advice_form': advice_form, 'question_results': question_results,})
advice_update.html
<form method='POST' action=''>{% csrf_token %}
# METHOD 1 - This code works and renders the form with paragraphs enclosed
# but I want more control
{{ advice_form.as_p }}
# METHOD 2 - When I try to get the value by itself, it works too
{{ advice_form.instance.title }} # E.g. 'Hello World'
{{ question_results.title }} # E.g. 'Hello World'
# METHOD 3 - When I try to put the text inside a 'value' tag in an 'input',
# the text gets cut off and only the first word appears in the input
# When I look at the console, I see the rest of the text in there.
<input id="id_title" type="text" name="title" class="form-control" value={{ question_results.title }}>
I tried a few things like adding autoescape and safe tags, but when I use METHOD 3, the value inside the tag of advice.html cuts off when there's a space (e.g. 'Hello World' turns into 'Hello').
First, you don't need to set null=False, blank=False on your title field as those are there by default.
It looks like the main issue you're having is adding the Bootstrap css class to the form element, which you can accomplish a couple of different ways. Also note that your value attribute is missing quotes around it.
The first way is to add the appropriate classing to the widget from the Python side of the form:
class QuestionsForm(forms.ModelForm):
class Meta:
model = Questions
fields = ('title', )
def __init__(self, *args, **kwargs):
super(QuestionsForm, self).__init__(*args, **kwargs)
self.fields['title'].widget.attrs['class'] = 'form-control'
However, this gets really tedious when you're dealing with a lot of form fields. So, I use django-widget-tweaks to instead add these at the template level:
{{ form.title|add_class:"form-control" }}
which I find a lot easier to deal with. This way you don't have to render the field by hand. Also be sure to handle the case if there's no matching question in your view:
question = get_object_or_404(Question, id=pk)

How to style WTForm field through a widget?

I want to style a wtform field through a custom widget but the rendering keeps returning raw html code (with ampersands). Why?
this is my widget:
def my_widget(field, **kwargs):
field_id = kwargs.pop('id', field.id)
html = [u'<input class="my_class" %s value="" type="text">' % html_params(id=field_id, name=field_id)]
return u''.join(html)
You need to tell than string should be rendered as is without escaping HTML:
from wtforms.widget.core import HTMLString
def my_widget(field, **kwargs):
....
return HTMLString(u''.join(html))