Context_processor does not define a " " class/attribute(error) - python

I am following a Django course from Antonio's Melle Book, and I need a context_processor to use a cart instance throught the webapp. I constantly get the error, that the context processor does not define a "cart" object attribute.
Note: I am using cached sessions, if it matters
I tried putting the cart in a try catch statement, I have read the docs, I doesn't sort things out for me
context_processors.py
from .cart import Cart
def cart(request):
return {'cart': Cart(request)}
settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
(...)
'cart.context_processors.cart,']}
cart.py
class Cart(object):
def __init__(self, request):
self.session = request.session
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart

You haven't shown the actual error message. But the problem is probably because you've put the comma inside the quotes instead of outside. Change it to:
'cart.context_processors.cart',]}

Related

how to fix django admin "You don't have permission to view or edit anything."?

for the sake of customizing the default admin site , i have made the following changes:
admin.py:
class CustomAdminSite(admin.AdminSite):
def get_urls(self):
urls = super(CustomAdminSite, self).get_urls()
custom_urls = [
# re_path(r'^.*\.html', views.custom_admin_template_loader, name='custom-loader'),
url(r'^.*\.html', self.admin_view(self.my_view), name="my-view"),
]
return urls + custom_urls
def my_view(self, request):
context = {}
load_template = request.path.split('/')[-1]
template = loader.get_template('admin/' + load_template)
request.current_app = self.name
return HttpResponse(template.render(context, request))
apps.py:
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = 'myproject.admin.CustomAdminSite'
settings.py:
INSTALLED_APPS = [
'myproject.apps.MyAdminConfig',
nothing changed in urls.py
so if i access admin/ it works , but if i access another template using the view i made , it says You don't have permission to edit anything , how to fix it?
for clarifications on WHY i m using that view, it is because i overrided the default admin templates and now i have a navigation bar , which means i need to navigate through different html files (templates)
Solution :
i needed to pass context + set the request.current_app , (added in my custom view)
context = {
**self.each_context(request),
'title': self.index_title,
'app_list': app_list,
}
request.current_app = self.name

Python/Django universal method passed to template engine

I have a large Django Project that has hundreds of views already. I am creating a tasks feature where users are able to complete specific tasks associated with the specific application in the project they are using. I have multiple interfaces (aka Django apps in the project) : admin, management, onsite, etc... and each interface has its own navigation with a tasks link.
What I want is to be able to change the color of this link if a user is in an interface where a task has yet to be completed.
This is easy to check in each view and then I could universally render the correct color for the link based on a variable passed into the view, but that is extremely tedious with hundreds of views.
I suppose I could add a filter in each interface/Django App to simplify this a bit, but is that the most simple solution?
Here is an example of the method I want to be called in each interface's navigation:
from objects_client.task_models.task_models import Tasks
def does_interface_have_open_tasks(current_interface, db_alias):
if Tasks.objects.using(db_alias)\
.filter(interface=current_interface, completed=0).exists():
return True
return False
I ended up using a Context Processor to solve my needs like I show below:
import traceback
from objects_client.task_models.task_models import Tasks
def universally_used_data(request):
# I use multiple DBs
db_alias = request.session.get('db_alias')
# dictionary for global context values
dictionary_to_return = dict()
# interfaces and URL equivalents
interface_dictionary = {
'adm': 'admin',
'mgt': 'management',
'onsite': 'onsite',
'secu': 'security',
'maint': 'maintenance'
}
try:
# get interface url
short_url = request.path[1:-1].split('/')[1]
# get interface from dictionary above
interface = interface_dictionary.get(short_url)
dictionary_to_return['SHORT_URL'] = short_url
dictionary_to_return['INTERFACE'] = interface
# see if there is an open task...
if Tasks.objects.using(db_alias) \
.filter(interface=interface, completed=0).exists():
dictionary_to_return['OPEN_TASKS'] = True
else:
dictionary_to_return['OPEN_TASKS'] = False
except Exception as ex:
print(ex, traceback.format_exc())
return dictionary_to_return
Here is how I load the Context Processor:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
...
]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
...
# custom processors
'utils.context_processors.context_processors.universally_used_data'
],
},
},
]
Then I can just call the this variable in the template like so to change an HTML element's color, no {% load [whatever] %} or anything:
{% if OPEN_TASKS %}
style="color:red;"
{% endif %}
Thank you #Daniel Roseman for the suggestion/comment. This had me stumped for a bit :)

Django context processor being called twice per request

I've found only one topic like this and not a single answer in there seems to work.
I have two context processors:
def cart_view(request):
try:
cart_id = request.session['cart_id']
cart = Cart.objects.get(id=cart_id)
request.session['total'] = cart.items.count()
print('OLD CART USED')
except:
cart = Cart()
cart.save()
cart_id = cart.id
request.session['cart_id'] = cart_id
cart = Cart.objects.get(id=cart_id)
print('NEW CART CREATED')
return {'cart':cart}
# dropdown menu categories to every page
def categories(request):
print('CATEGORIES CONTEXT PROCCESOR')
categories = Category.objects.all()
return {'dropdown_categories':categories}
Settings:
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.media',
'shopping.views.cart_view',
'shopping.views.categories',
]
Via those print statements I'm able to see that each one of those CP being executed twice per request, although I'm rendering just base.html. What may be the problem?
import traceback; traceback.print_stack() gives this two times:
P.S. I know that I'm querying the DB every time I use CP, I'll add caching later.
Cosole log(that's one page load):
OLD CART USED
CATEGORIES CONTEXT PROCCESOR
[30/Aug/2018 18:56:13] "GET / HTTP/1.1" 200 2651
OLD CART USED
CATEGORIES CONTEXT PROCCESOR
[30/Aug/2018 18:56:13] "GET / HTTP/1.1" 200 2651
View:
class HomePageView(TemplateView):
template_name = 'base.html'
Project URLs:
urlpatterns = [re_path(r'^',include('shopping.urls',namespace='shop'))]
App's URLs:
urlpatterns = [re_path(r'^$',views.HomePageView.as_view(),name='home')]
Well, I don't what magic is this but the issue of getting two requests per page load had something to do with this line of code in my base.html:
<img src="#" width="30" height="30" class="d-inline-block align-top" alt="">
As soon as I deleted it, everything started to work normaly...

Custom ContextProcessor with ListView - not showing in template

I am back to django after a few years and I have adopted Class Based Views - definitely a fan, BUT for some reason, I cannot get my custom content processor to show its data. I am using mostly Generic Views on my application, and from what I understand they should automatically serve the context to the view.
This is my context processor (context_processors.py)
from models import Alert
def context_alerts(request):
alert_list = {}
alerts = Alert.objects.filter(to_user=request.user)
alert_list['alerts'] = alerts
alert_list['unread_count'] = len([a for a in alerts if a.unread == True])
# printing to console - this works
print alert_list
return alert_list
Note that when I print the dictionary - it shows in my console, so I know it is firing.
It is setup in my settings as so
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'part_iq.context_processors.context_alerts'
],
},
},
]
Finally, this is an example view - I have about 20 or so, all standard class based views:
class BuyerRfqList(ListView):
context_object_name = "rfqs"
template_name = "dashboard/buyer/rfq-list.html"
def get_queryset(self):
user = self.request.user
rfqs = Rfq.objects.filter(from_user=user, hidden=False).order_by("created_at")
return rfqs
I am simply outputting the alerts in the template as so (trying both the name of the dict and the context processor function):
{{alert_list.unread_count}}
{{context_alerts.unread_count}}
with no luck.
I feel like it is something obvious, but I am too rusty w/ Django and new to ClassBasedViews to figure it out
Two problems:
There is no key called "count" in your "alert_list" dictionary. The template is actually translated to alert_list['count'] (because of #2) which doesn't exist so it just fails silently.
Dictionaries in Django templates are accessed as if they're objects.
so alert_list['alerts']
is equivalent to
{{ alert_list.alerts }}
Now you can just call count on the Queryset
{{ alert_list.alerts.count }}
You don't have anything called alerts_list in the template. That's just the local name you're using inside the function to hold the dict of variables to pass to the template. The contents of that dict are added directly to the context: so you can access {{ alerts }} and {{ unread_count }}.

writing to django session database table after configurating settings.py

I'm writing a new backend API using Django.
I have configured the following values in settings.py:
CACHES = {
'default': {
'BACKEND': 'django.contrib.sessions.backends.cached_db'
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
I can't figure out how to write the session properties to the database. Anyone have any idea?
You have to activate also django.contrib.sessions.middleware.SessionMiddleware middleware first to have access to request.session dictionary in your views.
Here's simplistic example how to use request.session, taken directly from Django session documentation:
def post_comment(request, new_comment):
if request.session.get('has_commented', False):
return HttpResponse("You've already commented.")
c = comments.Comment(comment=new_comment)
c.save()
request.session['has_commented'] = True
return HttpResponse('Thanks for your comment!')

Categories