As far as I can tell, django-tagging will only create a cloud for one particular database model. This is usually awesome, but sometimes not enough. What if, for instance, you wanted to make a combined cloud that consolidated tags across more than one model? Maybe your blog puts tags not just on posts, but also on tweets and bookmarks.
That's pretty much the situation I was in, and here's how I hacked on the module's codebase to get it done. The code below accepts a queryset of TaggedItem objects and returns a list of tags and font sizes you can use to format the cloud, as I did here.
<div class="source"><pre><span></span><span class="sd">"""</span> <span class="sd">A modification of the tag cloud utilities in django-tagging. </span> <span class="sd">Necessary so I can run a tagcloud for all the models, not just one.</span> <span class="sd">Tip: It's good to submit a select_related query to avoid a ton of</span> <span class="sd">database hits. This will run a join that really slims things down.</span> <span class="sd">&gt;&gt;&gt; cloud.calculate_cloud(TaggedItem.objects.select_related().all())</span> <span class="sd">"""</span> <span class="kn">import</span><span class="w"> </span><span class="nn">math</span> <span class="kn">from</span><span class="w"> </span><span class="nn">django.utils.translation</span><span class="w"> </span><span class="kn">import</span> <span class="n">ugettext</span> <span class="k">as</span> <span class="n">_</span> <span class="c1"># Font size distribution algorithms</span> <span class="n">LOGARITHMIC</span><span class="p">,</span> <span class="n">LINEAR</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span> <span class="k">def</span><span class="w"> </span><span class="nf">_calculate_thresholds</span><span class="p">(</span><span class="n">min_weight</span><span class="p">,</span> <span class="n">max_weight</span><span class="p">,</span> <span class="n">steps</span><span class="p">):</span> <span class="n">delta</span> <span class="o">=</span> <span class="p">(</span><span class="n">max_weight</span> <span class="o">-</span> <span class="n">min_weight</span><span class="p">)</span> <span class="o">/</span> <span class="nb">float</span><span class="p">(</span><span class="n">steps</span><span class="p">)</span> <span class="k">return</span> <span class="p">[</span><span class="n">min_weight</span> <span class="o">+</span> <span class="n">i</span> <span class="o">*</span> <span class="n">delta</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">steps</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span> <span class="k">def</span><span class="w"> </span><span class="nf">_calculate_tag_weight</span><span class="p">(</span><span class="n">weight</span><span class="p">,</span> <span class="n">max_weight</span><span class="p">,</span> <span class="n">distribution</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""</span> <span class="sd"> Logarithmic tag weight calculation is based on code from the</span> <span class="sd"> `Tag Cloud`_ plugin for Mephisto, by Sven Fuchs.</span> <span class="sd"> .. _`Tag Cloud`: http://www.artweb-design.de/projects/mephisto-plugin-tag-cloud</span> <span class="sd"> """</span> <span class="k">if</span> <span class="n">distribution</span> <span class="o">==</span> <span class="n">LINEAR</span> <span class="ow">or</span> <span class="n">max_weight</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="k">return</span> <span class="n">weight</span> <span class="k">elif</span> <span class="n">distribution</span> <span class="o">==</span> <span class="n">LOGARITHMIC</span><span class="p">:</span> <span class="k">return</span> <span class="n">math</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">weight</span><span class="p">)</span> <span class="o">*</span> <span class="n">max_weight</span> <span class="o">/</span> <span class="n">math</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">max_weight</span><span class="p">)</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="n">_</span><span class="p">(</span><span class="s1">'Invalid distribution algorithm specified: </span><span class="si">%s</span><span class="s1">.'</span><span class="p">)</span> <span class="o">%</span> <span class="n">distribution</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">_group_tagged_items</span><span class="p">(</span><span class="n">tagged_item_qs</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""</span> <span class="sd"> Accepts a queryset of TaggedItem objects, groups them by tag, and then counts their frequency.</span> <span class="sd"> """</span> <span class="n">tag_count</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">for</span> <span class="n">ti</span> <span class="ow">in</span> <span class="n">tagged_item_qs</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">tag_count</span><span class="p">[</span><span class="n">ti</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="s1">'count'</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> <span class="n">tag_count</span><span class="p">[</span><span class="n">ti</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'font-size'</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="s1">'count'</span><span class="p">:</span> <span class="mi">1</span><span class="p">}</span> <span class="k">return</span> <span class="n">tag_count</span> <span class="k">def</span><span class="w"> </span><span class="nf">calculate_cloud</span><span class="p">(</span><span class="n">tagged_items_qs</span><span class="p">,</span> <span class="n">steps</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="n">distribution</span><span class="o">=</span><span class="n">LOGARITHMIC</span><span class="p">,</span> <span class="n">min_count</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""</span> <span class="sd"> Add a ``font_size`` attribute to each tag according to the</span> <span class="sd"> frequency of its use, as indicated by its ``count``</span> <span class="sd"> attribute.</span> <span class="sd"> ``steps`` defines the range of font sizes - ``font_size`` will</span> <span class="sd"> be an integer between 1 and ``steps`` (inclusive).</span> <span class="sd"> ``distribution`` defines the type of font size distribution</span> <span class="sd"> algorithm which will be used - logarithmic or linear. It must be</span> <span class="sd"> one of ``tagging.utils.LOGARITHMIC`` or ``tagging.utils.LINEAR``.</span> <span class="sd"> """</span> <span class="n">tag_counts</span> <span class="o">=</span> <span class="n">_group_tagged_items</span><span class="p">(</span><span class="n">tagged_items_qs</span><span class="p">)</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">tag_counts</span><span class="p">)</span> <span class="o">&</span><span class="n">gt</span><span class="p">;</span> <span class="mi">0</span><span class="p">:</span> <span class="n">counts</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span><span class="p">[</span><span class="s1">'count'</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">tag_counts</span><span class="o">.</span><span class="n">values</span><span class="p">()]</span> <span class="n">min_weight</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">counts</span><span class="p">))</span> <span class="n">max_weight</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">counts</span><span class="p">))</span> <span class="n">thresholds</span> <span class="o">=</span> <span class="n">_calculate_thresholds</span><span class="p">(</span><span class="n">min_weight</span><span class="p">,</span> <span class="n">max_weight</span><span class="p">,</span> <span class="n">steps</span><span class="p">)</span> <span class="k">for</span> <span class="n">tag</span> <span class="ow">in</span> <span class="n">tag_counts</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span> <span class="n">font_set</span> <span class="o">=</span> <span class="kc">False</span> <span class="n">tag_weight</span> <span class="o">=</span> <span class="n">_calculate_tag_weight</span><span class="p">(</span><span class="n">tag_counts</span><span class="p">[</span><span class="n">tag</span><span class="p">][</span><span class="s1">'count'</span><span class="p">],</span> <span class="n">max_weight</span><span class="p">,</span> <span class="n">distribution</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">steps</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">font_set</span> <span class="ow">and</span> <span class="n">tag_weight</span> <span class="o">&</span><span class="n">lt</span><span class="p">;</span><span class="o">=</span> <span class="n">thresholds</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span> <span class="n">tag_counts</span><span class="p">[</span><span class="n">tag</span><span class="p">][</span><span class="s1">'font_size'</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="n">font_set</span> <span class="o">=</span> <span class="kc">True</span> <span class="c1"># Cut off the data at the minimum count</span> <span class="n">tag_list</span> <span class="o">=</span> <span class="p">[(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">[</span><span class="s1">'font_size'</span><span class="p">],</span> <span class="n">v</span><span class="p">[</span><span class="s1">'count'</span><span class="p">])</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">tag_counts</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">v</span><span class="p">[</span><span class="s1">'count'</span><span class="p">]</span> <span class="o">&</span><span class="n">gt</span><span class="p">;</span> <span class="n">min_count</span><span class="p">]</span> <span class="c1"># Sort by count</span> <span class="n">tag_list</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">:</span><span class="n">cmp</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">y</span><span class="p">[</span><span class="mi">2</span><span class="p">]))</span> <span class="c1"># Reverse that</span> <span class="n">tag_list</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span> <span class="k">return</span> <span class="n">tag_list</span> </pre></div>