DJANGO simplejson - django

Good afternoon..i have a model with a class like this:
class Reportage:
def get_num(self):
end_date = self.date.end_date
start_date = self.date.start_date
duration = time.mktime(end_date.timetuple()) - time.mktime(start_date.timetuple())
delta_t = duration / 60
num = []
for t in range(0,duration,delta_t):
start = t + start_date
end = datetime.timedelta(0,t+delta_t) + start_date
n_num = self.get_num_in_interval(start,end)
num.append([t, n_num])
return num
I want to serialize with simplejson the array num [] in the views.py for passing in a second moment this array to a jquery script to plot it in a graph..
what's the code to serialize that array..?
I hope I was clear .. thanks in advance to all those who respond ..

Following #ninefingers' response. I think that your question is aimed on how to make that dumped json string available to a jQuery plugin.
# views.py
def my_view(request):
# do stuff
num = reportage_instance.get_num()
num_json = simplejson.dumps(num)
return render(request, 'template.html', {
'num_json': num_json,
})
In your template, you make available that json obj as a Javascript variable
# template.html
<html>
<body>
<script>
var NUM_JSON = {{num_json|safe}};
myScript.doSomething(NUM_JSON);
</script>
</body>
</html>
Now you can call regular JS with the NUM_JSON variable.

If you're looking to do this in a model, something like this would work:
# if this were a models.py file:
import simplejson
# other django imports:
class SomeModel(models.Model):
property = models.SomeField()...
def some_function(self):
num = []
# full num
simplejson.dumps(num)
That'll dump num to a string-representation of the json, which you can then return, or write to a file, and so on.
From a view you have a choice - but if your view is an ajax view returning some json for processing you might do this:
# views.py
# ...
def my_ajax_call(request, model_pk):
try:
mymodel = SomeModel.get(pk=model_pk)
except SomeModel.NotFoundException as e:
return HttpResonse("Unknown model", status=404)
else:
return HttpResponse(mymodel.some_function()) # returns simplejson.dumps(num)
This can then be used from a template in Javascript - the other answer shows you how you might approach that :)

Related

How to Output More than Once In frontend In DJango

I am building a web app that makes use of the HackerNews API and I keep running into the same error.
I am trying to Output the 10 requested result from API but everytime i use the return response it only outputs the first result.
I want it to output 10 articles from the API instead of just the One.
This is my code:
from operator import itemgetter
import requests
from django.shortcuts import render
# Make an API call and store the response.
def home(request):
url = 'https://hacker-news.firebaseio.com/v0/topstories.json'
r = requests.get(url)
print(f"Status code: {r.status_code}")
# Process information about each submission.
submission_ids = r.json()
submission_dicts = []
for submission_id in submission_ids[:10]:
# Make a separate API call for each submission.
url = f"https://hacker-news.firebaseio.com/v0/item/{submission_id}.json"
r = requests.get(url)
print(f"id: {submission_id}\tstatus: {r.status_code}")
response_dict = r.json()
# Build a dictionary for each article.
submission_dict = {
'title': response_dict['title'],
'hn_link': f"http://news.ycombinator.com/item?id={submission_id}",
# 'comments': response_dict['descendants'],
}
submission_dicts.append(submission_dict)
# submission_dicts = sorted(submission_dicts, key=itemgetter('comments'),
# reverse=True)
for submission_dict in submission_dicts:
print(f"\nTitle: {submission_dict['title']}")
print(f"Discussion link: {submission_dict['hn_link']}")
# print(f"Comments: {submission_dict['comments']}")
count = 0
if count < 10:
return render(request, "news_api/home.html", submission_dict)
You're only getting one result because your return statement is calling "submission_dict". You probably wanted to call "submission_dict(s)" or something similar but it's hard to tell based on what has been commented out in your code. I think that's your primary problem. Without seeing your template, I don't know what your context object is supposed to look like.
But try this:
# views.py
def hacker_news_api_selector():
url = 'https://hacker-news.firebaseio.com/v0/topstories.json'
r = requests.get(url)
submission_list = r.json()
context = {}
context['objects'] = []
# Process information about each submission.
for submission_id in submission_list[:10]:
# Make a separate API call for each submission.
url = f"https://hacker-news.firebaseio.com/v0/item/{submission_id}.json"
r = requests.get(url)
response_dict = r.json()
context['objects'].append(response_dict)
return context
def home(request):
context = hacker_news_api_selector()
return render(request, "news_api/home.html", context)
And in the template...
# news_api/home.html
<html>
...
{% for x in objects %}
<li>{{ x.title }}</li>
{% endfor %}
</html>

Publish a custom Django Flatpage at a set date and time

I have a custom Flatpage model:
from django.contrib.flatpages.models import FlatPage
class MyFlatPage(FlatPage):
publish = models.DateTimeField()
so that I can add a publish date in the future.
Now, I don't have a proper list of flatpages on the front end, my use for frontpages is more like 'one-offs', where I specific the URL and all that. For example, 'about', '2019prize', 'Today's walk', stuff like that.
The urls.py is set up to catch all the flatpages with:
from django.contrib.flatpages import views
re_path(r'^(?P<url>.*/)$', views.flatpage)
How can I set these pages I create to be displayed only after the publish date has arrived? I know that I can filter them by looking up something like pages.filter(publish__lte=now). Where and how should I put that code though?
Additional information
I suppose I need to create a custom view, is that correct? The original view is in ../lib/python3.8/site-packages/django/contrib/flatpages/views.py:
def flatpage(request, url)
if not url.startswith('/'):
url = '/' + url
site_id = get_current_site(request).id
try:
f = get_object_or_404(FlatPage, url=url, sites=site_id)
except Http404:
if not url.endswith('/') and settings.APPEND_SLASH:
url += '/'
f = get_object_or_404(FlatPage, url=url, sites=site_id)
return HttpResponsePermanentRedirect('%s/' % request.path)
else:
raise
return render_flatpage(request, f)
#csrf_protect
def render_flatpage(request, f):
if f.registration_required and not request.user.is_authenticated:
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(request.path)
if f.template_name:
template = loader.select_template((f.template_name, DEFAULT_TEMPLATE))
else:
template = loader.get_template(DEFAULT_TEMPLATE)
f.title = mark_safe(f.title)
f.content = mark_safe(f.content)
return HttpResponse(template.render({'flatpage': f}, request))
How can I extend this, adding my if publish__lte=now code?
What I did is copy-paste the view code from ../lib/python3.8/site-packages/django/contrib/flatpages/views.py to my app.views, rename the two functions, and add the following to render_myflatpage:
def render_myflatpage(request, f):
[...]
if f.publish > now:
f.content = 'This content will be published on ' + str(f.publish)
I then assigned the new view in the catch-all urls.py code:
re_path(r'^(?P<url>.*/)$', myflatpage)
I know this goes against the DRY protocol; this works for me for the time being. If there's a more elegant solution please do let me know.

Django WeasyPrint - Export filtered list

So I've created a pdf file from a ListView called "OrderListView". Now I would like to pass a queryset to the pdf file.
I rewrote my listview as a function view for more clarity. I need to find a way to pass the queryset to the pdf view. I'm using django-filter to create the filtered view. I have the following;
filters.py
class OrderFilter(django_filters.FilterSet):
class Meta:
model = Order
fields = {
'start_date': ['gte'],
'end_date': ['lte'],
}
views.py
from .filters import *
# View to show a filtered list using django-filter
def order_list(request):
order_list = Order.objects.all()
order_filter = OrderFilter(request.GET, queryset=order_list)
start_date__gte = request.GET.get('start_date__gte','')
start_date__lte = request.GET.get('start_date__lte','')
return render(request, 'orders/order_list.html', {
'filter': order_filter,
'start_date__gte': start_date__gte,
'start_date__lte': start_date__lte,
})
# View to create a pdf file from the filtered view using WeasyPrint
def order_list_pdf(request):
# Edited: Create queryset
start_date__gte = request.GET.get('start_date__gte','')
start_date__lte = request.GET.get('start_date__lte','')
order_list = Order.objects.filter(
Q(start_date__gte=start_date__gte) |
Q(start_date__lte=start_date__lte)
)
order_filter = OrderFilter(request.GET, queryset=order_list)
response = HttpResponse(content_type="application/pdf")
response['Content-Inline'] = 'attachment; filename=filtered_list.pdf'.format()
html = render_to_string('pdf/pdf_booking_list_arrivals.html', {
'filtered_list': order_list,
})
font_config = FontConfiguration()
HTML(string=html).write_pdf(response, font_config=font_config)
return response
So I have tried using
start_date__gte = request.GET.get('start_date__gte','')
start_date__lte = request.GET.get('start_date__lte','')
And pass the query with the url
#edited
<a class="btn" href="{% url 'order_list_pdf' %}?start_date__gte={{ start_date__gte }}&start_date__lte={{ start_date__lte }}">Create PDF</a>
This does create the query in the url but does not filter the list. The generated pdf is working, I just need to find a way to only send the filtered results to the pdf view.
Any help would be appreciated!

Django model property with dictionary data

I'm trying to access a property/computed field that contains a dictionary within my template I'm not quite sure on how I should be looping over the values, and from a code standpoint is this the correct way to go... As you can see below, my view creates a filter queryset and my hope is that each row within that queryset will contain the dict from the computed field/property from the model. Any advice would be greatly appreciated. I'm having a hard time determining what would be the correct way to loop over the data in the template itself. The final product would look something like this...
<div id={{provider.id}}>{{provider.name}}</div>
<div class="dayofweek">Monday</div>
<div class="timesavailable">
<ul>
<li>8:00</li>
<li>8:30></li>
</div>
Model:
from project.lib.file import GetSchedule
class Provider(models.Model):
....
#property
def current_schedule(self):
sched = GetSchedule(self.id)
return sched.returnSchedule()
Helper Function:
class GetSchedule(object):
schedule = {}
def __init__(self, provider_id):
self.provider = provider_id
try:
self.schedule = GetSchedule.__buildSchedule(self,self.provider)
except ObjectDoesNotExist:
print "Init failed - Cannot find provider in db with id: %s" % self.provider
raise ValueError
def __buildSchedule(self, provider):
#default values for now - dict will contain data soon
pid = self.provider
sched = {'Monday':{'8:00','8:30','10:00'}, 'Tuesday':{'10:00','10:30','11:00'}, 'Wednesday':{'9:30','10:00','10:30'}}
val = {
'Schedule' : sched
}
return val
def returnSchedule(self):
return self.schedule
View:
prov_list = Provider.objects.filter(docspeciality__name=dft_spec)
context_dict = {
'DftSpec': dft_spec,
'DftZip': dft_zip,
'DftIns': dft_ins,
'DocList': prov_list}
return render_to_response('search/provider.html', context_dict, context_instance=RequestContext(request))

Creating PDFs with django (wkhtmltopdf)

Could someone please provide me with a comprehensive example of how to get a view in django to return a PDF using wkhtmltopdf. There are limited number of examples that come with django-wkhtmltopdf and they presume a level of knowledge I just don't have. I have looked through the source code but I can't make heads or tails of how to use it (for example whats the difference between PDFTemplateView and PDFTemplateResponse?!?)
I would be very grateful for any help.
BTW(I'm using templates for the header and footer as well)
EDIT
def some_view(request,sID):
something = get_object_or_404(Something,id=sID)
return render_to_response('something.html', {'something':something}, context_instance=RequestContext(request))
How would I get the following simple view to provide me with a pdf instead of an html file?
EDIT 2
I am currently playing around with:
def pdf_view(request,sID):
template = 'pdf.html'
something = get_object_or_404(Something,id=sID)
context = {
'something' : Something,
'object_for_header_and_footer': something.object_for_header_and_footer,
}
cmd_options = settings.WKHTMLTOPDF_CMD_OPTIONS
return PDFTemplateResponse(request=request,
context=context,
template=template,
filename='something',
header_template='header.html',
footer_template='footer.html',
cmd_options=cmd_options)
but I am getting 'str' object has no attribute 'update' in /usr/local/lib/python2.7/dist-packages/wkhtmltopdf/utils.py in wkhtmltopdf, line 74. I don't know whether to starting hacking wkhtmltopdf?!?!
The difference between PDFTemplateView and PDFTemplateResponse is that the view is a class-based view. And PDFTemplateResponse renders the pdf data and sets the right response headers. To add header and footer:
# urls.py
from django.conf.urls.defaults import *
from wkhtmltopdf.views import PDFTemplateView
urlpatterns = patterns('',
...
url(r'^pdf/$', PDFTemplateView.as_view(template_name='my_template.html',
filename='my_pdf.pdf',
header_template='my_header_template.html',
footer_template='my_footer_template.html',
...
), name='pdf'),
)
Opening pdf/ in your browser will start a download of my_pdf.pdf based on the my_template.html, my_header_template.html and my_footer_template.html.
The advanced example shows how to subclass PDFTemplateView extending and changing the logic of PDFTemplateView. To understand what happens read Using class based views.
Like header_template and footer_template you can define a response_class. Because PDFTemplateResponse is the default, you don't have to define it.
EDIT
The following simple view provides you with a pdf instead of an html. This is not using django-wkhtmltopdf. You could use wkhtmltopdf in your html2pdf function.
def some_view(request):
t = loader.get_template('myapp/template.html')
c = RequestContext(request, {'foo': 'bar'})
html = t.render(c)
pdf_data = html2pdf(html) # Your favorite html2pdf generator
response = HttpResponse(pdf_data, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="some_filename.pdf"'
return response
EDIT 2
A simple view with context:
template.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Untitled</title>
</head>
<body>
<h1>{{ title }}</h1>
</body>
</html>
urls.py
from views import MyPDFView
urlpatterns = patterns('',
(r'^pdf/', MyPDFView.as_view()),
)
views.py
from django.views.generic.base import View
from wkhtmltopdf.views import PDFTemplateResponse
class MyPDFView(View):
template='template.html'
context= {'title': 'Hello World!'}
def get(self, request):
response = PDFTemplateResponse(request=request,
template=self.template,
filename="hello.pdf",
context= self.context,
show_content_in_browser=False,
cmd_options={'margin-top': 50,},
)
return response
EDIT 3
If you use a DetailView, you can add the object to context:
url(r'^books/(?P<pk>\d+)/$', MyPDFView.as_view(), name='book-detail'),
class MyPDFView(DetailView):
template='pdftestapp/template.html'
context= {'title': 'Hello World!'}
model = Book
def get(self, request, *args, **kwargs):
self.context['book'] = self.get_object()
response=PDFTemplateResponse(request=request,
template=self.template,
filename ="hello.pdf",
context=self.context,
show_content_in_browser=False,
cmd_options={'margin-top': 50,}
)
return response
Hmm the error indicates that you're passing string somewhere that you shouldn't.
After checking its source code, I guess in settings.py you have WKHTMLTOPDF_CMD_OPTIONS as a string, something like
WKHTMLTOPDF_CMD_OPTIONS = 'some_option_here'
But you should assign a dict there:
WKHTMLTOPDF_CMD_OPTIONS = {
'quiet': True,
}
Otherwise your code should work fine.