Help with context_processor

64 views
Skip to first unread message

Mikkel Kromann

unread,
Jun 18, 2018, 3:16:53 PM6/18/18
to Django users
Hi.

Once again thanks for all your invaluable advice to me so far. Now, I'm battling context_processors.
I really struggle to find a good example that can help me understand how to use them.
They seem quite helpful to a lot of stuff I plan to do.

I think I got the configuration in settings.py and @register right as my tag is accepted as registered.
What baffles me is whether to include "request" as argument to my context processor GetItemDictionary()
The error I get now (without declaring request as an argument) is


"GetItemDictionary() takes 0 positional arguments but 1 was given"

With request as argumetn to GetItemDictionary(request) I get this error:

'GetItemDictionary' did not receive value(s) for the argument(s): 'request'

Should I pass request to my GetItemDictionary somewhere in my view, or is that done automagically by the template?
I realise that I've probably done something wrong elsewhere, but I'm at a loss to guess where ...
I suspect that the @register.simple_tag stuff I do may be the culprit as the tag may not be simple.


thanks, Mikkel

From project/app/templatetags/items_extra.py
from django import template
register = template.Library()

@register.simple_tag()
def GetItemDictionary():
# For now pass a hardcoded dictionary - replace with query later
   
return {
       
'year': {'name': 'year', 'readable': 'Year', 'urlname': 'year_list' },
       
'region': {'name': 'region', 'readable': 'Region', 'urlname': 'region_list' },
       
'location': {'name': 'location', 'readable': 'Location', 'urlname': 'location_list' },
   
}


From my settings.py
TEMPLATES = [
   
{
       
'BACKEND': 'django.template.backends.django.DjangoTemplates',
       
'DIRS': [
            BASE_DIR
+ '/templates/',
       
],
       
'APP_DIRS': True,
       
'OPTIONS': {
           
'context_processors': [
               
'items.templatetags.items_extra.GetItemDictionary',
               
'django.template.context_processors.debug',
               
'django.template.context_processors.request',
               
'django.contrib.auth.context_processors.auth',
               
'django.contrib.messages.context_processors.messages',
           
],
           
'libraries':{
               
'items_extra': 'items.templatetags.items_extra',
           
},
       
},
   
},
]


From my template:
{% load items_extra  %}
{% GetItemDictionary as Items %}
{% block sidebar %}
<ul>
{% for item in Items %}
   
<li><a href="{% url item.urlname}">item.readable</a>
{% endfor %}
</
ul>
I
: {{ Items }}
{% endblock %}





Andréas Kühne

unread,
Jun 18, 2018, 4:55:29 PM6/18/18
to django...@googlegroups.com
First of all - that is not how a context processor works.

You are confusing template tags and context processors. A template tag is one of the following:

It must then be registered and then included in your template. So then you should put it in the templatetags module and load it into your template. It should NOT be added to the OPTIONS dictionary.

However, a context processor is called EVERYTIME a request is handled and returns it's content to the template - WITHOUT the need of calling anything OR adding it to your template. So in your case you would need to move the context processor from the templatetags module, not load it with register, and also load use {% include %} in your template. And finally don't call it.

What happens with the context processor is that it autmatically gets called and the dictionary result is added to the context of the template.

So your context processor should look like this:
def GetItemDictionary(request):

# For now pass a hardcoded dictionary - replace with query later
    
return {
        
'year': {'name': 'year', 'readable': 'Year', 'urlname': 'year_list' },
        
'region': {'name': 'region', 'readable': 'Region', 'urlname': 'region_list' }, 
        
'location': {'name': 'location', 'readable': 'Location', 'urlname': 'location_list' },
    
}

Without registering it or anything.

This way you will be able to get the information in your template like this:
{% block sidebar %}
<ul>
    <li><a href="{{ year.urlname }}">{{year.readable}}</a>
    <li><a href="{{ region.urlname }}">{{region.readable}}</a>
    <li><a href="{{ location.urlname }}">{{location.readable}}</a>
</ul>
{% endblock %}

The reason for needing to add year, region and location, is because that is the way you are creating the dictionary in your context processor.

Best regards,

Andréas

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/54694b80-86ae-4934-913f-7a03e215463e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mikkel Kromann

unread,
Jun 19, 2018, 2:59:24 PM6/19/18
to Django users
Thank you so much Andreas.
This is very helpful.

I wasn't able to figure that from the documentation (not sure who to blame, though ;)
So I relied on various stackoverflow posts, which were quite confusing to say the least.

Now, is there anyway I can loop over the items in the dictionary?
In the end, I will probably query my dictionary from another model of mine.

Would the { for item in items } still hold?


cheers, Mikkel

Best regards,

Andréas

To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

Andréas Kühne

unread,
Jun 20, 2018, 3:28:55 AM6/20/18
to django...@googlegroups.com
Hi Mikkel,

No - you can't loop over a dictionary that way. However - You don't need to resort to doing that either. If you want to loop over something use a list. Like this:

return {
  'items': [
       {'name': 'year', 'readable': 'Year', 'urlname': 'year_list' },
          {'name': 'region', 'readable': 'Region', 'urlname': 'region_list' },
      {'name': 'location', 'readable': 'Location', 'urlname': 'location_list' }
  ]
}

Then in the template:
{% for item in Items %}
    
<li><a href="{% url item.urlname}">{{item.readable}}</a>
{% endfor %}


Regards,

Andréas

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Matthew Pava

unread,
Jun 20, 2018, 9:56:34 AM6/20/18
to django...@googlegroups.com

Well, you can access a dictionary like a list using these:

items.keys(), template:

                for k in items.keys

 

items.values(), template:

                for v in items.values

 

items.items(), template:

                for k, v in items.items


Regards,

 

Andréas

 


For more options, visit https://groups.google.com/d/optout.

 

--

You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Andréas Kühne

unread,
Jun 20, 2018, 2:34:50 PM6/20/18
to django...@googlegroups.com
Hi Matthew,

That's true, You would then be able to get the dictionary values once more. Hadn't thought of that. Good point! Thanks :-)

Regards,

Andréas


Regards,

 

Andréas

 

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Mikkel Kromann

unread,
Jun 20, 2018, 2:51:43 PM6/20/18
to Django users
Thank you both.
Clearly, I also missed some important points about dictionaries.
Mistakes are good teachers, but it surely helps having competent people on a mailing list :)

I'll sum up the simple solution to context processors that worked for me, if somebody would find it useful some day.

Basically in any of your .py files you can put a definition taking 'request' as argument and returning a dictionary.
Recommended file is <app>/contextprocessor.py (my <app> is named items)
def GetItemDictionary(request):
   
return {
         
'itemDictionary': [

           
{'name': 'region', 'readable': 'Region', 'urlname': 'region_list' },

           
{'name': 'location', 'readable': 'Location', 'urlname': 'location_list' },
       
]
   
}



This will allow you to iterate over the dictionary 'itemDictionary' in all your templates, e.g. in template.html
{% for item in itemDictionary %}
   
<li><a href={% url item.urlname %}>{{ item.readable }}</a>
{% endfor %}


To ensure that Django passes the itemDictionary dict to the template, you will need to register it in settings.py
TEMPLATES = [
   
{
       
'BACKEND': 'django.template.backends.django.DjangoTemplates',
       
'DIRS': [
            BASE_DIR
+ '/templates/',
       
],
       
'APP_DIRS': True,
       
'OPTIONS': {
           
'context_processors': [

               
'items.contextprocessor.GetItemDictionary',

               
'django.template.context_processors.debug',
               
'django.template.context_processors.request',
               
'django.contrib.auth.context_processors.auth',
               
'django.contrib.messages.context_processors.messages',
           
],

       
},
   
},
]

And that's about it. Thanks again to Matthew and Andréas for helping me out here.


cheers, Mikkel

Regards,

Andréas


Regards,

 

Andréas

 

To post to this group, send email to djang...@googlegroups.com.


For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to djang...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
Reply all
Reply to author
Forward
0 new messages