Django, how to reuse variable results get in a views in another one? - django

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

Related

Django render() in 2.X

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.

Defining functions inside of views

I am attempting to create a job board website and upon entering a zip code in a form, that zip code is passed to a search_results view (as zip_code). In this view, I need to:
Get the surrounding zip codes (with a certain mile radius)
Get objects in DB that match those zip codes.
I have step one complete and have not implemented step two yet (actual code not that important to question):
from uszipcode import Zipcode, SearchEngine
def search_results(request, zip_code):
zip_codes = []
search = SearchEngine(simple_zipcode=True) # create SearchEngine object
zip_code = search.by_zipcode(zip_code) #create Zipcode object?
latitude = zip_code.lat
longitude = zip_code.lng
result = search.by_coordinates(latitude, longitude, radius = 5, returns = 5)
for item in result:
zip_codes.append(item.zipcode)
# code that will return matching objects
My question is can you define functions inside of a view in Django, like such:
def search_results(request, zip_code):
zip_codes = getSurroundingZipCodes(zip_code)
results = getJobsInArea(zip_codes)
return render(request, 'results.html', {'results: results})
def getSurroundingZipCodes(zip_code):
# logic for this function
def getJobsInArea(zip_codes):
# logic for this function
This is something I haven't seen in any tutorials so I feel like the answer is no, but I'm not sure why?
Yes you can do it. django view here is a function . You can define functions inside function.
That is how decorators work in python. But
why cant we define functions in seperate modules and import them above? Like in a file do
utils.py
def getSurroundingZipCodes(zip_code):
# logic for this function
def getJobsInArea(zip_codes):
# logic for this function
and simply import
from utils import getSurroundingZipCodes,getJobsInArea
this way they will be resuable

call variable from method inside the method

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.

Using tastypie api from other views

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.

Django - Access Context Dictionary Before Template

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.