Having two views
views.py
def followup(request):
''''''
marklist = report_template(request)
return render(request, 'incident/followup.html',{'somevar':somevar})
def report_template(request):
'''''
report=Report.objects.filter(report=report_id)
''''''
return render(request, 'incident/print.html',
{'report':report})
I am calling one method inside another method.Calling report_template method into followup method.followup method also have variable to render in template.
How to pass the variable of report_template method to followup method and make it display in template.
Thanks
One way to achieve this would be to create a helper method that returns the report or the context needed by both the methods. The issue here is you are returning a HTTPResponse object, and it is cleanest to use helper method here:
def get_report(request):
report=Report.objects.filter(report=report_id)
#do more processing here.
#returning a dict is probably safest here, because, in the calling method, `.get()` would not throw an error if key is not present.
return {'report': report, 'somevar': somevar}
def followup(request):
marklist = get_report(request).get('somevar')
return render(request, 'incident/followup.html',{'somevar':marklist})
def report_template(request):
report = get_report(request).get('report')
return render(request, 'incident/print.html',
{'report':report})
You can not do that with views, you have to look up for templatetags, which is a better way to do so in Django (a view accepts a Request argument and returns an HttpResponse variable).
See https://docs.djangoproject.com/en/dev/howto/custom-template-tags/.
Using templatetags makes your code reusable, by factoring what you do in views.
Related
I have the following question for you. I want to know the best and elegant way to reuse some variable results obtained in a view in another one.
I'm trying to explain me better with an example.
I'have 2 differente app, app A and app B.
In app A views.py I have a lot of code to process data from the models with a creation of a lot of new variables.
Now, in app B I have the necessity to reuse some variables obtained in views.py app A, but I wonna write again the same code to get them.
Is there a way to achive my goal?
EDIT
Following the #sandeshdaundkar's suggestions I could overcome my problem creating a new function and call it in my views.py of each app.
I'm trying to achive this result but I'm not good at python's function and how call it inside my views.py.
I have created the following function in my_app/utility.py:
def my_func():
defaults = list(0 for m in range(13))
iva_debito = dict()
for year, month, totale in(Ricavi.objects.values_list( 'data_contabile__year', 'data_contabile__month').
annotate(totale=ExpressionWrapper(Sum(F('quantita') * F('ricavo')*(F('iva'))),
output_field=FloatField())).values_list('data_contabile__year', 'data_contabile__month', 'totale')):
if id not in iva_debito.keys():
iva_debito[id]=list(defaults)
index=month
iva_debito[id][index]=totale
iva_debito_totale={'IVA a Debito Totale': [sum(t) for t in zip(*iva_debito.values())],}
context= {
'iva_debito_totale':iva_debito_totale,
}
return context
And here my my_app/views.py:
...
from .utility import my_func
def iva(request):
data = my_func()
iva_debito_totale=data['iva_debito_totale']
context= {
'iva_debito_totale': iva_debito_totale,
}
return render(request, 'iva/iva.html', context)
I have solved it with the solution above.
def func_name():
# do calculation,
return context_for_view_one, obj_to_reuse
def view_one(request):
context, iva = func_name()
return render(context=context) # context to be used in view a
def view_two(request):
context, iva = func_name()
return render(context=iva) # iva to be used in view b
def iva(request):
data = func_name()
iva_debito_totale = data['iva_debito_totale']
return render(request, 'template.html', context={'totale': iva_debito_totale})
I hope this gives you an idea, we return 2 objects from common function. One which is to be used in view_one and others to be used in view_two. You can try something similiar
I ran into this problem while trying to capture POST data.
In Django 1.X, I structured my views like this:
def view_name(request, template_name='template.html'):
variable1 = data
variable2 = moreData
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
Now, I see that render_to_response() has been deprecated, but I'm unsure how to port the code with all of the locals() calls.
Do I have to convert all of my views by building a dict with all desired variables?
Is there another way to port this to keep the locals() incorporation?
Thanks!
You can call this with:
def view_name(request, template_name='template.html'):
variable1 = data
variable2 = moreData
# …
return render(request, template_name, locals())
That being said, please do not use locals(). It makes it very unclear what exactly you pass to the template. Furthermore you often will pass more to the template than you want to. Finally most IDEs will say a variable is not used, and thus you might remove it, but it is in fact used in the template.
I am calling tastypie api from normal django views.
def test(request):
view = resolve("/api/v1/albumimage/like/user/%d/" % 2 )
accept = request.META.get("HTTP_ACCEPT")
accept += ",application/json"
request.META["HTTP_ACCEPT"] = accept
res = view.func(request, **view.kwargs)
return HttpResponse(res._container)
Using tastypie resource in view
Call an API on my server from another view
achieve the same thing but seems harder.
Is my way of calling api acceptable?
Besides, it would be awesome if I could get the result in python dictionary instead of json.
Is it possible?
If you need a dictionary, it means that you must design your application better. Don't do important stuff in your views, nor in the Tastypie methods. Refactor it to have common funcionality.
As a general rule, views must be small. No more than 15 lines. That makes the code readable, reusable and easy to test.
I'll provide an example to make it clearer, suppose in that Tastypie method you must be creating a Like object, maybe sending a signal:
class AlbumImageResource(ModelResource):
def like_method(self, request, **kwargs):
# Do some method checking
Like.objects.create(
user=request.user,
object=request.data.get("object")
)
signals.liked_object(request.user, request.data.get("object"))
# Something more
But, if you need to reuse that behavior in a view, the proper thing would be to factorize that in a different function:
# myapp.utils
def like_object(user, object):
like = Like.objects.create(
user=request.user,
object=request.data.get("object")
)
signals.liked_object(request.user, request.data.get("object"))
return like
Now you can call it from your API method and your view:
class AlbumImageResource(ModelResource):
def like_method(self, request, **kwargs):
# Do some method checking
like_object(request.user, request.data.get("object")) # Here!
And in your view...
# Your view
def test(request, object_id):
obj = get_object_or_404(Object, id=object_id)
like_object(request.user, obj)
return HttpResponse()
Hope it helps.
I'm hoping to use a context processor or middleware to modify the values of the dictionary passed to render_to_response prior to the actual rendering. I have a messaging schema I'm trying to implement that would populate a message list based on the existence of a type of user that I'd like to search the context for prior to the rendering of the template.
Example:
def myview(...):
...
return render_to_response('template.html',
{'variable': variable},
)
and I'd like to be able to add additional information to the context on the existence of 'variable'.
How can I access 'variable' after my view defines it but before it gets to the template so that I can further modify the context?
use TemplateResponse:
from django.template.response import TemplateResponse
def myview(...):
...
return TemplateResponse(request, 'template.html',
{'variable': variable},
)
def my_view_wrapper(...):
response = my_view(...)
variable = response.context_data['variable']
if variable == 'foo':
response.context_data['variable_is_foo'] = True
return response
This is easy. If you have supplied just a little bit more code in your example the answer might have bit you.
# first build your context, including all of the context_processors in your settings.py
context = RequestContext(request, <some dict values>)
# do something with your Context here
return render_to_response('template.html', context)
Update to comment:
The result of a render_to_response() is an HTTPResponse object containing a template rendered against a Context. That object does not (to my knowledge) have a context associated with it. I suppose you could save the result of render_to_response() in a variable and then access the Context you passed it, but I'm not sure what problem you are trying to solve.
Did you modify the Context during rendering? If so you may find that the information is not there any longer because the Context has a scope stack which is pushed/popped during template processing.
You can create a dictonary for the context:
def myview(...):
c = dict()
c["variable"] = value
...
do some stuff
...
return render_to_response('template.html',c)
Maybe the RequestContext is the thing you are looking for.
Sorry or the confusing title! It's actually a lot simpler than it sounds.
I've got a function:
def get_messages(request):
# do something expensive with the request
return 'string'
I want to be able to call that function from the template, so I've strapped in with a context processor:
def context_processor(request):
return {'messages':get_messages(request)}
So now when I have {{messages}} in my template, string prints out. Great.
The problem is get_messages is quite expensive and isn't always needed. Less than half the templates need it. Is there a way of passing the function to the template and leave it up to the template if it runs or not?
I tried this already:
def context_processor(request):
return {'messages':get_messages}
But that just outputs the function description <function get_messages at 0x23e97d0> in the template instead of running it.
I think You shouldn't mix logic of application with template (the view in MVC pattern). This breaks consistency the architecture. You can call get_messages in views that need it and simply pass messages to the template context, in the others just pass None.
But answering Your question: You can make a proxy object. E.g:
class Proxy(object):
def __init__(self, request)
self.request = request
super(Proxy, self).__init__()
def get_messages(self):
# so some expensive things
return 'string'
# context processor
def context_processor(request):
return {'messages':Proxy(request)}
# in the view
{{ messages.get_messages }}
You can make this ever more generic, and create Proxy class that has one method (e.g get), and takes one parameter in constructor: a function which takes request object as first parameter. This way You gain generic method to proxy a function call in Your templates. Here it is:
class Proxy(object):
def __init__(self, request, function)
self.request = request
self.function = function
super(Proxy, self).__init__()
def get(self):
return self.function(self.request)
then You can write even cooler than I had written before:
# context processor
def context_processor(request):
return {'messages':Proxy(request, get_messages)}
# sounds nice to me
{{ messages.get }}