Electronics & Programming

develissimo

Open Source electronics development and programming

  • You are not logged in.
  • Root
  • » Django
  • » Confused about thread locals... again. [RSS Feed]

#1 Dec. 15, 2010 23:30:06

Doug B.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Confused about thread locals... again.


First, I'd like to find out if there is a better way than thread
locals to do what I want to do. From what I can tell, it isn't
possible any other way. Finally, I don't understand why my thread
locals implementation/hack works - which scares me, so I would like to
ask the wiser gurus out there for an explanation.

Need: To alter the template path used by a custom template loader
based on the the request object. Specifically I want to alter it
based on the incoming domain, and sanitized cookie value allowing
'theme' selection.

I have a basic theme setup using thread locals that works.

in the same module/directory I have:

base.py -> contains the theme objects, thread locals variable, and a
couple of get/set functions that just use getattr/setattr to set a
theme attribute on the local() instance.

middleware.py -> contains the middleware that calls my "set theme"
function

loader.py-> contains the template loader which calls my "get theme"
function

The base setup works fine, but was written with the intention of
subclassing it for another app to set the theme according to a 'site'
object that gets created by another middleware (we serve multiple
sites from one fastcgi instance). So I have another middleware.py
file in another app that imports my ThemeMiddleware and subclasses it
overriding the method returns the template path to cause the loader to
look for that sites templates.

This does not work. I get two different thread locals instances
(print shows different addresses), despite all manipulation of the
local variable happening in base.py just as it did in the working
version.

I've had issues in the past with thread locals working differently
depending on module import method. So I stripped out the thread
locals bit from base.py and put in all by itself in thread_locals.py:

---
try:
from threading import local
except ImportError:
from django.utils._threading_local import local
thread_local=local()
----

Now in base.py I added 'from thread_locals import thread_local' at the
top of the module, and nothing else changes. I was hoping that the
same import statment (it's only imported once, in one file) would
bypass the problem, but it doesn't.

Next I moved the thread_locals.py file from the same directory as my
other theme files to the project root, in the same location as
django's settings.py. No other changes were made.

It works.

I should be happy, but I'm not comfortable allowing solutions I don't
reasonably understand to go into production. I'd love to drop thread
locals entirely, but short of that some understanding of what is
happening and why would be a big help. I googled the heck out if it,
but didn't find anything that fit.

Thanks!

--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to
django-users+unsubscr...@googlegroups.com.
For more options, visit this group athttp://groups.google.com/group/django-users?hl=en.

Offline

#2 Dec. 16, 2010 05:17:26

W. C.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Confused about thread locals... again.


I think that the correct solution for your problem would be, instead of
hacking around with the template path on the fly like this, to instead write
a template loader for your application, and apply the logic you need within
the template loader itself.

See:http://docs.djangoproject.com/en/dev/ref/templates/api/#loading-templatesandhttp://code.djangoproject.com/browser/django/trunk/django/template/loader.pyfordetails.

- Craig -

On Wed, Dec 15, 2010 at 18:30, Doug Ballance <dball...@gmail.com> wrote:

> First, I'd like to find out if there is a better way than thread
> locals to do what I want to do. From what I can tell, it isn't
> possible any other way. Finally, I don't understand why my thread
> locals implementation/hack works - which scares me, so I would like to
> ask the wiser gurus out there for an explanation.
>
> Need: To alter the template path used by a custom template loader
> based on the the request object. Specifically I want to alter it
> based on the incoming domain, and sanitized cookie value allowing
> 'theme' selection.
>
> I have a basic theme setup using thread locals that works.
>
> in the same module/directory I have:
>
> base.py -> contains the theme objects, thread locals variable, and a
> couple of get/set functions that just use getattr/setattr to set a
> theme attribute on the local() instance.
>
> middleware.py -> contains the middleware that calls my "set theme"
> function
>
> loader.py-> contains the template loader which calls my "get theme"
> function
>
> The base setup works fine, but was written with the intention of
> subclassing it for another app to set the theme according to a 'site'
> object that gets created by another middleware (we serve multiple
> sites from one fastcgi instance). So I have another middleware.py
> file in another app that imports my ThemeMiddleware and subclasses it
> overriding the method returns the template path to cause the loader to
> look for that sites templates.
>
> This does not work. I get two different thread locals instances
> (print shows different addresses), despite all manipulation of the
> local variable happening in base.py just as it did in the working
> version.
>
> I've had issues in the past with thread locals working differently
> depending on module import method. So I stripped out the thread
> locals bit from base.py and put in all by itself in thread_locals.py:
>
> ---
> try:
> from threading import local
> except ImportError:
> from django.utils._threading_local import local
> thread_local=local()
> ----
>
> Now in base.py I added 'from thread_locals import thread_local' at the
> top of the module, and nothing else changes. I was hoping that the
> same import statment (it's only imported once, in one file) would
> bypass the problem, but it doesn't.
>
> Next I moved the thread_locals.py file from the same directory as my
> other theme files to the project root, in the same location as
> django's settings.py. No other changes were made.
>
> It works.
>
> I should be happy, but I'm not comfortable allowing solutions I don't
> reasonably understand to go into production. I'd love to drop thread
> locals entirely, but short of that some understanding of what is
> happening and why would be a big help. I googled the heck out if it,
> but didn't find anything that fit.
>
> Thanks!
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To post to this group, send email to django-us...@googlegroups.com.
> To unsubscribe from this group, send email to
> django-users+unsubscr...@googlegroups.com<django-users%2bunsubscr...@googlegroups.com>
> .
> For more options, visit this group at
>http://groups.google.com/group/django-users?hl=en.
>
>

--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to
django-users+unsubscr...@googlegroups.com.
For more options, visit this group athttp://groups.google.com/group/django-users?hl=en.

Offline

#3 Dec. 16, 2010 05:49:39

r.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Confused about thread locals... again.


I faced this problem, and ran into the issue that the request object
is not passed to the template loader, so there's no way to get your
domain from within a custom template loader without using
threadlocals.

What I did instead was as follows:

1) Write a custom render-to-response type function that selects the
template using select_template based on the theme for the domain
2) Write a custom template tag that will select the correct template
for an include based on the theme, and use it instead of the standard
{% include %} tag
3) Write a custom context processor that will determine the base
template for the theme, and pass it in a base_template variable for
use in {% extends base_template %}

Note that (1) means that you will not be able to use generic views
(well, at least pre-class-based ones) or views from third-party apps.
However, depending on your theming system, you may be able to get away
with just (3) or a combination of (2) and (3).


On Dec 16, 12:17 am, "W. Craig Trader" <craig.tra...@gmail.com> wrote:
> I think that the correct solution for your problem would be, instead of
> hacking around with the template path on the fly like this, to instead write
> a template loader for your application, and apply the logic you need within
> the template loader itself.
>
> See:http://docs.djangoproject.com/en/dev/ref/templates/api/#loading-templ...http://code.djangoproject.com/browser/django/trunk/django/template/lo...
> details.
>
> - Craig -
>
> On Wed, Dec 15, 2010 at 18:30, Doug Ballance <dball...@gmail.com> wrote:
> > First, I'd like to find out if there is a better way than thread
> > locals to do what I want to do.  From what I can tell, it isn't
> > possible any other way.   Finally, I don't understand why my thread
> > locals implementation/hack works - which scares me, so I would like to
> > ask the wiser gurus out there for an explanation.
>
> > Need: To alter the template path used by a custom template loader
> > based on the the request object.  Specifically I want to alter it
> > based on the incoming domain, and sanitized cookie value allowing
> > 'theme' selection.
>
> > I have a basic theme setup using thread locals that works.
>
> > in the same module/directory I have:
>
> > base.py -> contains the theme objects, thread locals variable, and a
> > couple of get/set functions that just use getattr/setattr to set a
> > theme attribute on the local() instance.
>
> > middleware.py -> contains the middleware that calls my "set theme"
> > function
>
> > loader.py-> contains the template loader which calls my "get theme"
> > function
>
> > The base setup works fine, but was written with the intention of
> > subclassing it for another app to set the theme according to a 'site'
> > object that gets created by another middleware (we serve multiple
> > sites from one fastcgi instance).  So I have another middleware.py
> > file in another app that imports my ThemeMiddleware and subclasses it
> > overriding the method returns the template path to cause the loader to
> > look for that sites templates.
>
> > This does not work.  I get two different thread locals instances
> > (print shows different addresses), despite all manipulation of the
> > local variable happening in base.py just as it did in the working
> > version.
>
> > I've had issues in the past with thread locals working differently
> > depending on module import method.  So I stripped out the thread
> > locals bit from base.py and put in all by itself in thread_locals.py:
>
> > ---
> > try:
> >    from threading import local
> > except ImportError:
> >    from django.utils._threading_local import local
> > thread_local=local()
> > ----
>
> > Now in base.py I added 'from thread_locals import thread_local' at the
> > top of the module, and nothing else changes.  I was hoping that the
> > same import statment (it's only imported once, in one file) would
> > bypass the problem, but it doesn't.
>
> > Next I moved the thread_locals.py file from the same directory as my
> > other theme files to the project root, in the same location as
> > django's settings.py.  No other changes were made.
>
> > It works.
>
> > I should be happy, but I'm not comfortable allowing solutions I don't
> > reasonably understand to go into production.  I'd love to drop thread
> > locals entirely, but short of that some understanding of what is
> > happening and why would be a big help.  I googled the heck out if it,
> > but didn't find anything that fit.
>
> > Thanks!
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Django users" group.
> > To post to this group, send email to django-us...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > django-users+unsubscr...@googlegroups.com<django-users%2bunsubscr...@googlegroups.com>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/django-users?hl=en.

--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to
django-users+unsubscr...@googlegroups.com.
For more options, visit this group athttp://groups.google.com/group/django-users?hl=en.

Offline

#4 Dec. 16, 2010 19:17:39

Doug B.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

Confused about thread locals... again.


@ringemip
Thanks for the reply. I've been considering something like that, but
given the number of views and tags involved, it would be a very long
process. Especially since I used a new context instance in most of my
custom tags that render another template, rather the pushing,
rendering, poping the original like I should have.

As much as I don't want to use thread_locals, it seems like the best
(interim) approach. The long term plan will definitely move to
something like you describe. It will also give a nice consistent use
pattern when a request object isn't available (ie async mail
templates).

I'd still love to know why the import/locals object is so touchy.

--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to
django-users+unsubscr...@googlegroups.com.
For more options, visit this group athttp://groups.google.com/group/django-users?hl=en.

Offline

  • Root
  • » Django
  • » Confused about thread locals... again. [RSS Feed]

Board footer

Moderator control

Enjoy the 17th of August
PoweredBy

The Forums are managed by develissimo stuff members, if you find any issues or misplaced content please help us to fix it. Thank you! Tell us via Contact Options
Leave a Message
Welcome to Develissimo Live Support