Pass Django variables between view functions - python

I'm asking a question about variables handling in my Django application view.
I have 2 functions :
The first one lets me to display query result in an array with GET filter parameter (in my case, user writes year and Django returns all objects according to this year. We will call query_naissance this variable).
The second one lets me to create a PDF. I have lots of variables but I want to take one more time query_naissance in my PDF.
This is my first function :
#login_required
def Table_annuelle_BirthCertificate(request) :
query_naissance = request.GET.get('q1')
...
return render(request, 'annuel.html', context)
And my second function looks like :
#login_required
def Table_Naissance_PDF(request) :
data = {"BirthCertificate" : BirthCertificate}
template = get_template('Table_raw.html')
html = template.render(Context(data))
filename = str('Table annuelle Naissance.pdf')
path = '/Users/valentinjungbluth/Desktop/Django/Individus/' + filename
file = open(path, "w+b")
pisaStatus = pisa.CreatePDF(html.encode('utf-8'), dest=file, encoding='utf-8')
file.close()
context = {
"BirthCertificate":BirthCertificate,
"query_naissance":query_naissance,
}
return render(request, 'Table.html', context) # Template page générée après PDF
So How I can add query_naissance given by user in my first function to my second one without write one more time a field ?
Then, I have to call this variable like {{ query_naissance }} in my HTML template.
Thank you

In order to persist information across requests, you would use sessions. Django has very good session support:
# view1: store value
request.session['query_naissance'] = query_naissance
# view2: retrieve vlaue
query_naissance = request.session['query_naissance']
# or more robust
query_naissance = request.session.get('query_naissance', None)
You need 'django.contrib.sessions.middleware.SessionMiddleware' in your MIDDLEWARE_CLASSES.

Related

Passing data from post form to FileResponde view

I recently started using Django and I managed to create two views, one to submit a form and another to return a FileResponse, separately, they work fine.
Now, I need to integrate both, when the client submit the form, I want to redirect to the another view using the fields submitted at the previous form. How can I do that?
Here is my form view:
def submitForm(request):
if 'report' in request.POST:
date_start = request.POST.get('date_start')
date_end = request.POST.get('date_end')
state = request.POST.get('state')
return render(request, 'comissao.html')
Here is my view that creates a pdf file
def createPdf(request):
date_start = '20220301'
date_end = '20220331'
state = 'G00471'
body = "some html"
options = { 'quiet': '' }
pdfkit.from_string(body, options=options)
file = open('file.pdf', 'rb')
return FileResponse(file)
As you can see, I need the information passed at my first view, to use at second view, I tried something like this, but I think I'm mistaking the concept,
return reverse('pdf', kwargs={'state':state, 'date_start':date_start, 'date_end':date_end})
reverse() only returns the URL, but I think you rather want to do a redirect() to that view.
For passing the parameters you have several options:
GET parameters
Session
URL parameters
Let's use GET parameters, which I would suggest:
from urllib.parse import urlencode
...
def submitForm(request):
...
response = redirect('pdf')
params = { state' : state, 'date_start: date_start, 'date_end': date_end}
response['Location'] += f'?{urlencode(params)}'
return response
Then in your PDF view you need to parse the GET parameters:
def createPdf(request):
date_start = request.GET.get("date_start")
...
Note that you may also need to convert your dates into string and back for the query, which I ignored here.

How can I repeatedly call a function from a views.py in Django?

How can I repeatedly call a function from a views.py in Django?
urls.py
urlpatterns = [
url(r'^$', views.index),
url(r'^report/(?P<extension>\d+)/$', views.report),
]
views.py
def report(request, extension):
"""
I will do some logic here. I need the extension variable for
database purposes.
EX:
my_array = Report.objects.fetching_reports(extension='3')
"""
return render(request, 'report.html’)
If you notice in extension, I passed in 3. The idea is that each extension will have their own data. However, I want them to render on the same html template. I will begin rendering from extension 1, up to 12 then goes back to 1. Let’s say extension 4 is missing, it will be redirected to extension 5.These extension will come from my database.
Example:
…/report/1/
…/report/2/
…/report/3/ ## will skip 4 if not available
…/report/5/
…/report/6/ ## and so on..
Each extension will render the same HMTL template. Right now, I can successfully render these reports if I type the URL patter directly to the browser. Is there a way to call report( ) continuously, let’s say every 15 seconds? Or should I have a different approach to this?
Thank you very much for reading.
def report(request, extension):
try:
my_array = Report.objects.fetching_reports(extension=extension)
except Report.DoesNotExist:
my_array = None
extension +=1
if my_array = None:
return HttpResponseRedirect(reverse('your_project_name':'your_app_name', kwargs = {'extension':extension}))
else:
return render(request, 'report.html', {'extension':extension})
that will skip to the next object if 4 doesn't exist, if you wanna skip after 15 seconds you can do a JavaScript redirecting to the next page and using extension var
For each report, pass a next url to the template and use javascript to reload.
<script>
function nextReport() { window.location.href = "{{ next }}"; }
setTimeout(nextReport, 15000);
</script>

Django work flow redirect from one view to another and display page with url parameter

I am trying to create a web app that users will select a file, get data processed and then redirected to a confirmation page with a url parameter(?status=1) How can I move from the processing view to the confirmation view and then display the confirmation page?
I have put my code below which is not working in my views and urls py files
# views.py
def marketdata_processing(request):
if request.method == 'POST':
uploadform = forms.MyUploadForm(request.POST, request.FILES)
if uploadform.is_valid():
newdoc = models.UploadDocument(docfile=request.FILES['uploadfile'])
filename = request.FILES['uploadfile'].name
newdoc.save()
selecteddate = newdoc.getselecteddate() # Model method calculated
fileid = newdoc.pk
request.session['fileid'] = fileid
request.session['selecteddate'] = selecteddate
return redirect(reverse('views.confirm_input_details'))
else:
uploadform = forms.MyUploadForm()
# Render list page with the documents and the form
return render_to_response(
'mytemplate.html',
{'uploadform': uploadform},
context_instance=RequestContext(request)
)
def confirm_input_details(request):
fileid = request.session['fileid']
selecteddate = request.session['selecteddate']
msg = 'Proceed to import data for %s? \nFileID Being Imported is %s ' % (
selecteddate, fileid,)
url = reverse('views.confirm_input_details', kwargs={'status': 1})
return HttpResponseRedirect(url)
# urls.py
urlpatterns = [
url(r'', views.marketdata_processing, name='myapp/mytemplate.html'),
url(r'^\?status=(?P<status>[0-9]+)$',
views.confirm_input_details, name='myapp/myconfirmpage.html'),
]
There are a couple of issues I feel exist in your code:
Indentation is a very important thing in python code. Please make sure the indentation of your if-else statements in the 'marketdata_processing' view are in correct order. Beware, in your code:
return render_to_response('mytemplate.html',
{'uploadform': uploadform},
context_instance=RequestContext(request))
will always get executed as it is outside the else statement. You might want to indent it under the else (if it makes sense)- like so:
else:
uploadform = forms.MyUploadForm()
return render_to_response('mytemplate.html',
{'uploadform': uploadform},
context_instance=RequestContext(request))
Instead of 'redirect(reverse())' try 'HttpResponseRedirect()' in the processing view to call the confirm-page view, like so:
from django.http import HttpResponseRedirect
return HttpResponseRedirect('/?status=1') --> relative URL shown
place the relative/absolute url (both would work) above.
Finally, render your confirm-page template in the 'confirm_input_details' view with the context parameters, like so:
def confirm_input_details(request):
fileid = request.session['fileid']
selecteddate = request.session['selecteddate']
msg = 'Proceed to import data for %s? \nFileID Being Imported is %s ' % (selecteddate, fileid)
return render_to_response('confirmpage_template.html'),
{'fileid': fileid,
'selecteddate': selecteddate,
'msg': msg}, context_instance=RequestContext(request))
** P.S: Stick to neat basics and it will work. You happened to call your confirm_input_details view from within the same view itself. As far as I think, that would probably take you into an infinite loop. Simple concept of any view is:
take input:request, parameters
--> process logic with parameters
--> render a specific template or call another url where a template is being rendered.
You can't expect a page to show up without the rendering a template.

Passing variables from Jinja to database

I'm trying to figure out a way to pass a dynamic URL with webpy that will render a Jinja template with information about the information that was passed. Specifically I have a item database that should be able to take whatever item ID is in the URL and render a template with further information about that item.
To simply the problem, I've hardcoded the value 1043374545 for demonstrations purposes, but I'm hoping that this line will be come dynamic once this initial problem is solved.
urls = ('/1043374545', 'view_item')
class view_item:
def GET(self, itemID):
item_info = sqlitedb.detailInfo(request)
return render_template('view_item.html', item = item_info)
As of now I isolated the issue to having to do with something related to passing the value 1043374545 into the view_item function. Any thoughts on how I can pass a dynamic number within a URL into view_item?
simply put:
urls = (('/([0-9]*)', 'view_item'),)
[0-9]* will tell webpy to only accept numbers after the "/".
Then you can use that value in your GET function, it will be under itemID as you specified in your GET parameter.
class view_item:
def GET(self, itemID):
item_info = sqlitedb.detailInfo(itemID)
return render_template('view_item.html', item = item_info)
check this link for more details:
http://webpy.org/cookbook/url_handling

Update Jinja2 template variables

I am using appengine with Python and jinja2 template.
I encountered an issue during the process: I render a list of games with this code
self.templateValues = {}
self.templateValues['title'] = 'GalaStore'
self.templateValues['values'] = kw
gamesQuery = Game.all()
values = {'games' : gamesQuery.run()}
self.templateValues['gl'] = values
template = JINJA_ENVIRONMENT.get_template(template)
self.response.out.write(template.render(self.templateValues))
then I have some button-filters in my html, and everyone calls a different js function. The problem is: once I hit the filter "sort by alpha" and I call a python function "sortByAlpha" via js (via ajax), how can I update the template variables in runtime withouth calling the template.render() function again? That would cause the reloading of the entire page and I would like to avoid it.
Thank you very much!
Your AJAX request would either need to return the games object list in JSON form, so the JavaScript could update the list in the browser, or you would have a template rendering just that part of the page, and have JavaScript swap out that piece with the HTML loaded from your server.
The latter can be made reusable; have both your main view and your AJAX handler use the same template, rendering just the list of games (no the whole page):
def rendered_games_list(self, sort_by=None):
games_query = Game.all()
if sort_by:
# I winged this bit, you didn't specify the ORM used
games_query = games_query.order_by(sort_by)
template = JINJA_ENVIRONMENT.get_template(games_list_template)
return template.render(gl=games_query.run())
then use this part in your main view:
template_values = {
'title': 'GalaStore',
'values': kw,
'games_list': self.rendered_games_list()
}
template = JINJA_ENVIRONMENT.get_template(template)
self.response.out.write(template.render(self.templateValues))
and in your main template insert the rendered games list HTML as:
{{ games_list|safe }}
So your main template doesn't render the games list itself, it merely includes it.
Your AJAX handler can return the rendered_games_list() directly:
sort_order = self.request.get('sort_order', None)
self.response.out.write(self.rendered_games_list(sort_order))

Categories