UnboundLocalError at / local variable 'Profile' referenced before assignment - python

i am writing a django views as shown:-
def feed(request):
if request.user.is_authenticated:
user=request.user
profile=Profile.objects.filter(user=user)
userfollowing=FollowingProfiles.objects.filter(Profile=profile)
for following in userfollowing:
username=following.ProfileName
useraccount=User.objects.filter(username=username)
Profile=Profile.objects.filter(user=useraccount)
Post=post.objects.filter(Profile=Profile)
comment=comment.objects.filter(post=Post)
final_post_queryset=final_post_queryset+Post
final_comment_queryset=final_comment_queryset+comment
return render(request,'feed/feed.html',{'final_comment_queryset':final_comment_queryset,'final_post_queryset':final_post_queryset})
else:
redirect('signup')
while template feed.html is:-
{% extends 'base.html' %}
{% block content %}
{% load static %}
{% for p in final_post_queryset %}
{{ p.DatePosted }}
<img src="{{ p.Picture.url }}"/>
{% endblock %}
while the error is:-
so the error is in the 3rd line of view
profile=Profile.objects.filter(user=user)

I'm assuming you already imported the Profile module (with from .models import Profile or the like), and are confused as to why it doesn't exist (if you haven't, you need to add that import to the top of your file).
Even if you have imported it, this code won't work. Your problem is you assigned to the name Profile at function scope, making it a local variable, and local variables are local (but initially empty) from the beginning of the function. Trying to access them before they're assigned to raises the UnboundLocalError you're seeing (that error is only raised when you try to read from a local name before you've assigned to it; it can't be raised simply by failing to import a module, which would simply raise a NameError). You couldn't see the globally imported Profile even if you did import it, because within the function, Profile must be local or global, it can't be both.
To fix, choose a different name for your local variable so the global Profile remains accessible:
def feed(request):
if request.user.is_authenticated:
user=request.user
profile=Profile.objects.filter(user=user) # This line is fine!
userfollowing=FollowingProfiles.objects.filter(Profile=profile)
for following in userfollowing:
username=following.ProfileName
useraccount=User.objects.filter(username=username)
# Use lowercase profile, not Profile
# Profile=Profile.objects.filter(user=useraccount) # This line was the problem!
profile = Profile.objects.filter(user=useraccount) # This line is the solution!
Post = post.objects.filter(Profile=profile) # Change to match new name
... rest of your code ...
You were already using lowercase profile correctly earlier, and never seem to need it again, so I just reused the name.

Related

Django dynamic url parameter names

Basically trying to do
{% url dynamic_url_name dynamic_parameter_name=dynamic_parameter_value %}
Tried the simplest approach of
{{entry}}
{% include 'mainsite/children/title_template.html' with
the_title=title_text
is_title_page=True
entries_of="title"
belongs_to="profile"
belongs_to_url_arg="user"
belongs_to_url_arg_value="author"
%}
But unfortunately this resulted in utter failure of
From this I can tell that parameters can't be context variables, so what I can try to do next is to simply unpack a dictionary as I would do inside python with something like
{% url **{dynamic_parameter_name:dynamic_parameter_value} %}
But I have no idea if it is possible inside django templates, and if possible how?
My urls look like
re_path(r'^title/(?P<title_text>[a-zA-Z0-9-]+)/$', TitlePage.as_view(), name='title')
re_path(r'^user/(?P<user>[a-zA-Z0-9-]+)/$', ProfilePage.as_view() ,name='profile')
And I the url is choosen either by a context variable or in an include tag, hence it is a variable.
{% url url_variable xxx=value %}
Now, url_variable is already a part of django, url tag accepts variable as it's first argument. But the xxx is not always the same, rather it changes according to url_variable, in this particular case; if url_variable is title, I want xxx to be title_text and if it is profile I want it to be user.
The parameter name is held in belongs_to, so if this was a regular python function, I could've simply done
url(url_variable, **{belongs_to: value})
and it would've unpacked it with the correct parameter name. So I need some kind of equivalency of this in template processor
I think you're overcomplicating things. You haven't shown your views themselves, but I can't see why they couldn't all take a commonly-named parameter - say, param - that does the specific work. So the URLs could be:
re_path(r'^title/(?P<param>[a-zA-Z0-9-]+)/$', TitlePage.as_view(), name='title')
re_path(r'^user/(?P<param>[a-zA-Z0-9-]+)/$', ProfilePage.as_view() ,name='profile')
and now you can do
{% url dynamic_url_name param=dynamic_parameter_value %}
**kwargs are not specifically supported as a parameter for the {% url %} tag, but there are a few workwarounds.
If you have a path in urlpatterns defined as:
path('myurl/<str:some>/<str:thing>', name='myurl')
Then you could have a filetoinclude.html:
My Url
And then in your main.html:
{% include 'filetoinclude.html' with urlname='myurl' some="aaa" thing="bbb" %}
And when you render you will have something like:
My Url
But obviously the issue is that maybe you want to address specific parameters of the URL when you reverse it. For this reason you could create a templatetag like:
from django.urls import reverse
from django import template
register = template.Library()
#register.simple_tag
def dynamic_url(urlname, **kwargs):
return reverse(urlname, kwargs=kwargs)
and then in your filetoinclude.html you could do:
{% load url_extended %}
{% dynamic_url urlname some=some thing=thing %}
which will yield the same URL as before.

Django Pagination KeyError 'source'

I installed Django template pagination tag from: https://github.com/jmcclell/django-bootstrap-pagination and while I followed all the instructions, I'm getting 'source' errors.
Apparently I'm doing something wrong.
===========================================
EDIT 3
SETTINGS.py
TEMPLATE_CONTEXT_PROCESSORS = (
"django.contrib.auth.context_processors.auth",
"django.core.context_processors.request",
)
VIEW.py:
def pagination(request):
location = Location.objects.all()
return render_to_response('pagination.html',
location,
context_instance=RequestContext(request))
TEMPLATE
{% load bootstrap_pagination %}
<h1>Location</h1>
{% for location in location %}
<h2>{{ location.name }}</h2>
{% endfor %}
{% bootstrap_paginate location %}
ERROR:
AttributeError at /pagination/
'str' object has no attribute 'paginator'
Request Method: GET
Request URL: http://127.0.0.1:8000/pagination/
Django Version: 1.5.4
Exception Type: AttributeError
Exception Value:
'str' object has no attribute 'paginator'
Error during template rendering
In template /home/jr/Documents/python/amapp/sdr/article/templates/pagination.html, error at line 7
'str' object has no attribute 'paginator'
1 {% load bootstrap_pagination %}
2
3
4
5
6
7 {% bootstrap_paginate location %}
I'm the author of the library, but you must forgive me as I haven't used Python in quite some time and I've core dumped most of my knowledge about this library.
So, #WayBehind was correct, your first mistake was using "page_obj". That was simply an example. In your case, you want to use "location"
However, you never got to see that error because you have a more pressing error which is that the library isn't playing nice with your setup. I wrote this library with Python 2.7 with the request context preprocessor. Please double check that you have the context preprocessor enabled as per the documentation and please be sure you are using Python <3.0. I know for a fact the library does not currently working on 3.x. There is a fork of the library where some other folks have been working to fix that and I am actively keeping an eye on it to pull those changes in when ready, but as of now it just doesn't work.
If you are using Python 2.x and you have the request context preprocessor enabled, I am not sure why you would be getting that error. If you can confirm those two things are true, I'll be happy to take a closer look tomorrow.
Edit:
This may or may not be an issue, but I notice that you loop through your Location object using the same variable name for the instance:
{% for location in location %}
<h2>{{ location.name }}</h2>
{% endfor %}
{% bootstrap_paginate location %}
Is it possible that Django's template scoping is such that the object you are passing to bootstra_paginate is the last instance of "location" rather than the entire set? This is an off the cuff guess as a first stab at this because otherwise things appear to be correct.
Have you followed all the steps ?
Request is in the context_processor (settings.py)?
TEMPLATE_CONTEXT_PROCESSORS = (
....
"django.core.context_processors.request",
....
)
You are using obj_list in the template, but do you have anything inside obj_list ? Maybe you have to use "location" instead of "obj_list" ? Because I think your object list is inside location (Location objects) but you are using obj_list like in the example. In the example obj_list is just a variable example for an object list.
EDIT:
Change this:
def pagination(request):
args = {}
args.update(csrf(request))
args['location'] = Location.objects.all()
return render_to_response('pagination.html', args)
for this:
from django.template import RequestContext
def pagination(request):
location = Location.objects.all()
return render_to_response('pagination.html', 'location':location,context_instance=RequestContext(request))
Using page_obj worked for me, for anyone wondering why this doesn't work when using Django 2.0.2 and django-bootstrap4 0.0.6.
I came across this by digging through the context variables in the error message that showed up from Django's DEBUG mode.

Automatically add a variable into context on per-application basis in Django?

I want to add a context variable in Django, so that I could define its value on per-application basis, or leave it empty.
Example:
apps/someapp/views.py:
def_context_var('app_name', 'Calendar')
templates/base.html:
{% if app_name %}You are in {{ app_name }} app.{% endif %}
....
{% if app_name %}Subsections of {{ app_name }}: ...{% endif %}
I considered the following:
Declare a variable in the app (in a view, or in URLs), and make a context processor. But I can't understang how to extract that var given the request object.
Put decorators on views. Hm, I don't like the idea: too much boilerplate or duplicated code.
#1 but nicer: make methods (like in the example above) that are executed on server restart, write the data into a dict, then a context processor somehow (how?) gets the application name and extracts the data from the dict. Where do I put the method, the dict, how does the context processor know where the view object is in?
You can call resolve(request.path) in a context processor to resolve the current url. See the django documentation on resolve for its return values, especially app_name.

Unable to get custom context processor to be invoked

I am trying to create a custom context processor which will render a list of menu items for a logged in user. I have done the following:
Within my settings.py I have
TEMPLATE_CONTEXT_PROCESSOR = (
'django.contrib.auth.context_processors.auth',
'mysite.accounts.context_processors.user_menu',
)
Under the accounts submodule I have context_processors.py with the following, for now:
def user_menu(request):
return {'user_menu':'Hello World'}
On my template page I have the following:
{% if user.is_authenticated %}
Menu
{{user_menu}}
{% endif %}
The invoking view is as follows:
def profile(request):
return render_to_response('accounts/profile.html',context_instance=RequestContext(request))
However I am unable to get the {{user_menu}} to render anything on the page, I know the user is authenticated as other sections of the template with similar checks render correctly. Am I missing something here. Please help
Thank you
Edit: Thanks Ben, Daniel, I have fixed the (S) in TEMPLATE_CONTEXT_PROCESSOR, however Django now has trouble resolving the module and I get the following message
Error importing request processor module django.contrib.auth.context_processors: "No module named context_processors"
UPDATE: I fixed it by changing the path to django.core.context_processors.auth Seems like the modules have been moved around
The setting name should be TEMPLATE_CONTEXT_PROCESSORS, with an S.

User authentication in Django

I learned how to authenticate users in Django months ago, but I've since upgraded and am having some problems so it occurred to me this morning that I may not have been doing it correctly from the start so I decided to ask.
In my project's urls.py file I've got ^accounts/login/$ and ^accounts/logout/$ both wired up to the built-in login() and logout() views (at django.contrib.auth.views) and ^accounts/profile/$ is connected to a view I've written, called "start_here" whose contents are basically this:
def start_here(request):
if request.user:
user_obj = request.user
else:
user_obj = None
is_auth = False
if request.user.is_authenticated():
is_auth = True
return render_to_response("profile.html", {'auth': is_auth,'user': user_obj,})
Now, "profile.html" extends a master template, called master.html, inside which is a "navbar" block whose contents are supposed to change if 'auth' == True (snippet below)
{% block navbar %}
{% if auth %}
Link A
Link B
Link C
Link D
Link E
Link F
Logout
{% else %}
Login
{% endif %}
{% endblock %}
My problem is that when I log in, and it redirects to /accounts/profile, the navbar doesn't display Links A-F + Logout, it displays only "login". It doesn't work the way I expect it to unless I manually copy-paste the above block into profile.html. When calling render_to_response(), does the context I provide get passed to the parent template as well as the child?
Full source to master and profile.html: http://dpaste.com/hold/128784/
I don't see anything suspect in the code.
This answer is tangential, but Jim's suggestion to use RequestContext is so good I want to explicitly explain how to do it.
You can reduce your start_here function to
from django.template import RequestContext
def start_here(request):
return render_to_response("profile.html", {},
context_instance=RequestContext(request))
By using RequestContext, user is automatically added to the context. Instead of using
{% if auth %}
use
{% if user.is_authenticated %}
Yes the context you pass in render_to_response() is passed to the named templates and ALL the templates it includes or inherits from.
You should look into Using RequestContext
Another thing to check...
Just making sure:
your profile template begins with
{% extends 'master.html' %}
In order to make sure django correctly identifies users, you need to make sure it is properly enabled in your settings module. specifically, you need to make sure that the SessionMiddleware and AuthenticationMiddleware modules are enabled in your settings.MIDDLEWARE_CLASSES. also be sure that auth is in your installed apps and you have run syncdb since enabling it.
If you have not taken the above steps, then django will not be able to detect when users have logged in and perform request setup properly.

Categories