Context processor ('AnonymousUser' object is not iterable) - python

In my context processor.py file I filter a table according to a user. This all works fine :
def subject_renderer(request):
return {"Calicount": Tools_Calibrated.objects.filter(
user=request.user, calibrated=True, issued=True).count(),
}
The problem comes in when I log out and try log back in. Because there is no authenticated user at login I cannot call the query in the context processor.
Question: Why is my context processor function being called when I am not calling the key in the login view template. I know how to solve this with templates but I was wondering how to solve it with context processors. Essentially omit it from one view.
Thank you in advance

It is possible that the user is not logged in, so in that case you can not pass Calicount.
You thus should implement your context processor with:
def subject_renderer(request):
if request.user.is_authenticated:
return {
'Calicount': Tools_Calibrated.objects.filter(user=request.user, calibrated=True, issued=True).count()
}
return {}

Related

How do I delete sessions when a user logs out Django?

I'm learning Django. I created the Sign out function. But when I loop with for it gives an error.
My Code:
def logout(request):
for key in request.session.keys():
del request.session[key]
return redirect('login')
But get this error ? I am using Python 3. Can you help me ?
RuntimeError at /logout/
dictionary changed size during iteration
Modifying a collection over which you are iterating is tricky, and frequently not allowed. It can easily result in problems, since the iterator is usually implemented under the assumption that the collection will not change.
You however do not need to iterate over the keys here. You can use the clear() method [Django-doc]:
def logout(request):
request.session.clear()
return redirect('login')
This is however not sufficient. Django already made a function to logout a user that will clear the session, delete it, etc. logout(..) [Django-doc]. You thus can implement this as:
from django.contrib.auth import logout as auth_logout
def logout(request):
auth_logout(request)
return redirect('login')

How do you call a user defined function in views.py DJANGO

The requirement is to display the logged in username and his role in the organization in all the pages at the top right corner.
The role can be identified by the permissions he is given.
My approach:
I thought of creating a user-defined function in views.py and call it in each and every other function. The function that I create should check the current user's permissions and based on them his role should be decided. All these details must be sent to base.html so that it will render and display the username and his role every time the page is loaded.
Any suggestions on other approaches are welcomed and if my approach is entirely wrong please let me know.
In the views you could do something like:
context = {
'username': username,
'role': role,
}
return render('template.html', context)
and in template.html you would then render it like:
{username} {role}
You can find your answer in the comments section of: Can I call a view from within another view?
btw, yes you can create a method to validate user/department. below is the sample of how I have done in my app.
A better approach I feel is to save such details in DB as a boolean flag and use django admin's capabilities to ease your work.
def validate_details(request):
user = request.GET['username']
user_details = User.objects.filter(name=user).values_list("name", "department", flat=True)
# Call validation method defined in view
is_ok = validate_user(user_details)
if is_ok:
return render_to_response("main/landing.html", {"user": user_details["name"],"department":user_details["department"]}, context_instance=RequestContext(request))
else:
return render_to_response("main/landing.html", {"user":"NA","department":"NA"}, context_instance=RequestContext(request))

How to Prevent a Redirected Django Form from Executing Twice?

My form2 is executing twice due to HttpResponseRedirect and from 'POST'. How do I prevent that from happening? Is it even possible?
What I've tried:
Process and render "getInfo" from form 1 and display it in form2. While this may work but I'll still end up going through the "getInfo" again in form2 to be able to use the returned variable.
Putting "getInfo" inside the if request.method will create an error because getInfo will need to be executed to obtain the returned errors variable.
Any suggestion is definitely welcomed.
Update
I've raised a similar question regarding "Why My Django Form Executed Twice?" and it was answered. I didn't want to create a bigger confusion by adding more questions on top of it. I created this as a follow-up question on how to actually solve it.
views.py
def form1 (request):
NameFormSet = formset_factory (NameForm, formset = BaseNodeFormSet, extra = 2, max_num = 5)
if request.method == 'POST':
name_formset = NameFormSet (request.POST, prefix = 'nameform')
if name_formset.is_valid ():
data = name_formset.cleaned_data
request.session ['data'] = data
return HttpResponseRedirect ('form2')
else:
name_formset = NameFormSet (prefix = 'nameform')
context = {'name_formset': name_formset}
return render (request, 'nameform/form1.html', context)
def form2 (request):
data = request.session ['data']
n, data, errors = getInfo (data) # <==== This statement executed twice in the console
CheckBoxFormSet = formset_factory (CheckBox, extra = 2, max_num = 5)
if request.method == 'POST':
checkbox_formset = CheckBoxFormSet (request.POST, prefix = 'checkbox')
if checkbox_formset.is_valid ():
for i, form in enumerate (checkbox_formset.cleaned_data):
data [i].update (form) # Join cleaned data with original data
n.processData (data, errors) # <=== n object will be used from getInfo
del request.session ['data']
context = {'data': data}
return render (request, 'nameform/success.html', context)
else:
checkbox_formset = CheckBoxFormSet (prefix = 'checkbox')
context = {
'checkbox_formset': checkbox_formset,
'data': data,
'errors': errors, # <==== getInfo needed to execute first to display errors messages
}
return render (request, 'nameform/form2.html', context)
def getInfo (data):
# Do something with data
return (n, data, errors)
Should the else: statement be less indented to align with if request.method == POST:? Also, where does getInfo come from? In the version of django I'm using (1.7) errors are an attribute on the formset after calling is_valid().
edit: further information
OK so your getInfo function runs twice because HttpResponseRedirect actually returns a 302 response to the browser with the new address, which the browser then GETs. Then when the user submits the form the browser POSTs the data to the same view. Since getInfo runs at the start of your view before any GET/POST conditional check, it runs both times. If you just want to delegate returning a response to another view function, you can call it directly, don't return a redirect.
Without knowing any more about your program this is as much as anyone can tell you.
Some more points:
getInfo sounds like it should be a 'safe' function that doesn't mutate its input or have any side effects, so running it twice shouldn't be a problem. If it does either of those things, you ought to rename it at least.
If the results of getInfo aren't expected to change between the GET and the POST request then you can move it into the form1 view function and store the results in session['data']. If it is expected to change, or you need to know if it does change, then you have no option but to run it twice anyway, unless there is some conditional you can check without running it to know if it will change.
Finally, form validation shouldn't be in the view if possible, keep it in your form class. There are hooks in django's form classes for whatever kind of validation you could want to do on submitted data. As a general rule, try to work within the framework, in the way it was designed to be used. This approach, as opposed to constructing a Rube-Goldberg machine out of the scavenged parts of many libraries taped together, will save you a lot of effort in the long run, as the library author and you will be working in the same direction.

Accessing to PK in Function Based View in a Template Context Processor

Im building a Template Context Processor to call the PK of each page that I have and that PK call it in the base.html, I have achieve to do a Template Context Processor with other query, but now I need to pass the PK. The context p works very well, but the context edit it does not, how can I call the PK from a Function Based View?
For example: localhost:8000/path/8 , I need to pass 8 in the context edit
def my_processor(request):
context = {'edit':InfoPredioGeneral.objects.filter(pk=self.kwargs['pk']),
'p':InfoPredioGeneral.objects.filter(user_id=request.user).latest('id')}
return context
I know that it does not works because of self and kwargs are not defined. But how can I do that?
You are using a FBV instead of a CBV, so the self you are using should be used with class methods, answering your question, you should pass the id parameter in the view, do something like this:
def my_processor(request, id):
context = {'edit':InfoPredioGeneral.objects.filter(pk=id),
'p':InfoPredioGeneral.objects.filter(user_id=request.user).latest('id')}
return context
in your urls.py you should put something like this:
url(r'^path/(?P<id>\d+)', my_processor, name='my_processor')

Django Find Out if User is Authenticated in Custom Tag

I'm trying to create a custom tag. Inside this custom tag, I want to be able to have some logic that checks if the user is logged in, and then have the tag rendered accordingly. This is what I have:
def user_actions(context):
request = template.Variable('request').resolve(context)
return { 'auth': request['user'].is_athenticated() }
register.inclusion_tag('layout_elements/user_actions.html', takes_context=True)(user_actions)
When I run this, I get this error:
Caught VariableDoesNotExist while rendering: Failed lookup for key [request] in u'[{}]'
The view that renders this ends like this:
return render_to_response('start/home.html', {}, context_instance=RequestContext(request))
Why doesn't the tag get a RequestContext object instead of the Context object? How can I get the tag to receive the RequestContext instead of the Context?
EDIT:
Whether or not it's possible to get a RequestContext inside a custom tag, I'd still be interested to know the "correct" or best way to determine a user's authentication state from within the custom tag. If that's not possible, then perhaps that kind of logic belongs elsewhere? Where?
By default, an instance of django.template.Context is used in rendering templates, but you can override this in your view, either by passing a subclass of django.template.Context as the context_instance keyword argument to render_to_response, or by instantiating the subclass, and passing it directly to Template.render.
For convenience, Django provides a useful, pre-defined Context subclass: django.template.RequestContext. RequestContext looks in your settings file for a setting called TEMPLATE_CONTEXT_PROCESSORS, which should be a tuple of callable objects, each of which should return a dictionary; RequestContext will loop over each callable, call it, and add the key/value pairs from its returned dictionary to the template context as variables. Check out these links for a more detailed explanation.
To add the current user to your template context, you need django.core.context_processors.auth:
Add the django.core.context_processors.auth context
processor to your list of context
processors in settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
... # Other context processors follow
)
Ensure the view than renders the template which calls
your custom tag uses RequestContext:
from django.template.context import RequestContext
from django.shortcuts import render_to_response
def my_view(request):
# Do some stuff
return render_to_response('templates/view.html',
context_instance=RequestContext(request))
Using RequestContext calls all context processors defined
in settings.TEMPLATE_CONTEXT_PROCESSORS, including the
auth context processor, which adds a context variable 'user'
to your template context.
In your template tag, you can access this variable
via context['user']
#register.inclusion_tag('templates/custom/tag.html', takes_context=True)
def custom_tag(context):
user = context['user']
if user.is_authenticated():
# Some stuff for the logged-in users
else:
# Stuff for anonymous users
i dont see how your view is linked to the template tag, because from what i know its django's template system that renders the tag, so the context is a dictionary, try this, hopefully it helps
user = context['user']
if user.is_authenticated():
do stuff
The "context" of a template node is a different thing to the RequestContext. A Context is also a dictionary, so if it has a user at all it would be accessed via context['user'].
The template nodes context contains information to help it render itself within the template, after doing some reading of the docs, I cannot find any way to access the RequestContext which would be associated with the request via the django.template.Context.
Moreover django.template.RequestContext extends from django.template.Context specifically in order to handle the added request object which would contain the user. So it is no surprise that Context would not have access to it.
See the source code of Context for proof.
How to get the user
After a bit of searching I found the django.template.resolve_variable method which can be used as follows:
from django.template import resolve_variable
user = resolve_variable('user', context)
Where context is a template context.
I ended up just passing the "user" parameter to the tag and using that to decide if the user was auth'd or not.

Categories

Resources