2017-02-03 9 views
0

さて、「キーワード」モデルは、他の4つのモデルにキーワードを格納しています。それぞれのモデルには、「key_list」フィールドがあります。これはManyToManyFieldの「キーワード」モデルを指しています。私のモデルのそれぞれは、複数のキーワードを持っている、と私はそれらを介して検索し、成功したので、同じようにそれらを見つけるしています:Djangoフィルタリング後に、複数のモデルにわたってキーワードのインスタンスの総数に注釈を付けるにはどうすればよいですか?

keys_selected='term1$term2$term3$' 
keys_selected = keys_selected.rstrip('$') 
keys_selected = keys_selected.split('$') 
goal = len(keys_selected) 
remaining = list() 
remaining += Keyword.objects.filter(employee__key_list__key__in=keys_selected).annotate(num_keys=Count('key')).filter(num_keys=goal).distinct() 
remaining += Keyword.objects.filter(vendor__key_list__key__in=keys_selected).annotate(num_keys=Count('key')).filter(num_keys=goal).distinct() 
remaining += Keyword.objects.filter(application__key_list__key__in=keys_selected).annotate(num_keys=Count('key')).filter(num_keys=goal).distinct() 
remaining += Keyword.objects.filter(machine__key_list__key__in=keys_selected).annotate(num_keys=Count('key')).filter(num_keys=goal).distinct() 
key_list = list() 
for x in remaining: 
    if x not in key_list: 
     key_list.append(x) 

これは、私の4つのモデルでのすべてのエントリに割り当てられているすべてのキーワードの辞書を返します。私の選ばれた言葉を含んでいる。ここでの考え方は、検索クエリと一致するオブジェクトのkey_listにあるすべてのキーワードの単語頻度を視覚的に表示するフィルタを作成することです。このキーワード「雲」を作成する必要があり

{% for key in key_list %} 
<a href="{% url 'keysearch:index' %}?keys_selected={{ key }}${{ keys_selected }}" style="font-size: {{ key.num_keys }}px;">({{ key }})</a> 
{% endfor %} 

を言い換えれば、私はそれは私がその値を呼び出し、そのようにフォントサイズのためにそれを使用できるように、文脈に出力されている辞書にそれを追加したいです私のキーワードはフィルタリングされ、視覚的にどのくらい頻繁に特定のキーワードが私のモデルの結果の中に表示されますが、私は完全に私のフィルタの結果内で機能する方法については失われています。私はこれを複数のモデルにわたってどのように達成するかについて、犠牲になっています。

参照のための私のモデル:

class Keyword(models.Model): 
    key = models.CharField(max_length=2000, unique=True) 

    def __str__(self): 
     return self.key 

    class Meta: 
     ordering = ('key',) 


class Entries(models.Model): 
    name = models.CharField("Name", max_length=200) 
    updated = models.DateTimeField("Last Updated", auto_now=True) 
    key_list = models.ManyToManyField(Keyword, blank=True, verbose_name="Keywords") 
    description = models.TextField("Description", blank=True) 

    class Meta: 
     abstract = True 
     ordering = ('name',) 


class Employee(Entries): 
    uid = models.SlugField("Employee User ID", max_length=6, unique=True, blank=True) 
    manager = models.SlugField("Manager's User ID", max_length=6) 

    def __str__(self): 
     return self.name 


class Vendor(Entries): 
    company = models.CharField("Vendor Company", max_length=200) 
    email = models.EmailField("Vendor Company Email Address", max_length=254, unique=True) 
    vend_man_name = models.CharField("Manager's Name", max_length=200) 
    vend_man_email = models.EmailField("Manager's Email Address", max_length=254) 

    def __str__(self): 
     return self.name 


class Application(Entries): 
    app_url = models.URLField("Application URL", max_length=800, unique=True) 

    def __str__(self): 
     return self.name 


class Machine(Entries): 
    address = models.CharField("Machine Address", max_length=800, unique=True) 
    phys_loc = models.TextField("Physical Location", blank=True) 

    def __str__(self): 
     return self.name 

答えて

0

はGROUPBYを使用して動作します答えhere by Lauritz V. Thaulowを発見しました。

(彼のコードを含む)私の解決策:テンプレート内

from django.db.models import Count 
from keysearch.models import Employee, Vendor, Application, Machine, Keyword 
from itertools import groupby 


def unique_keys(input): 
    output = [] 
    for x in input: 
     if x not in output: 
      output.append(x) 
    return output 


def canonicalize_dict(x): 
    return sorted(x.items(), key=lambda x: hash(x[0])) 


def unique_and_count(lst): 
    grouper = groupby(sorted(map(canonicalize_dict, lst))) 
    return [dict(k + [("count", int(len(list(g)) * 2.3 + 16))]) for k, g in grouper] 


def keycount(key_list='', keys_selected=''): 
    goal = len(keys_selected) 
    key_ref = list() 
    db_list = [Employee, Vendor, Application, Machine] 
    for db in db_list: 
     if keys_selected == '': 
      source = db.objects.all() 
     else: 
      source = db.objects.filter(key_list__key__in=keys_selected).annotate(num_keys=Count('key_list')).filter(num_keys=goal).distinct() 
     for entry in source: 
      key_ref += entry.key_list.values() 
    key_list = unique_and_count(key_ref) 
    return key_list 

@register.inclusion_tag('keysearch/key_cloud.html') 
def key_cloud(keys_selected=''): 
    if keys_selected == '': 
     key_list = Keyword.objects.all() 
     key_list = keycount(key_list, keys_selected) 
    else: 
     keys_selected = keys_selected.rstrip('$') 
     keys_selected = keys_selected.split('$') 
     keys_selected = unique_keys(keys_selected) 
     goal = len(keys_selected) 
     remaining = list() 
     remaining += Keyword.objects.filter(employee__key_list__key__in=keys_selected).annotate(num_keys=Count('key')).filter(num_keys=goal) 
     remaining += Keyword.objects.filter(vendor__key_list__key__in=keys_selected).annotate(num_keys=Count('key')).filter(num_keys=goal) 
     remaining += Keyword.objects.filter(application__key_list__key__in=keys_selected).annotate(num_keys=Count('key')).filter(num_keys=goal) 
     remaining += Keyword.objects.filter(machine__key_list__key__in=keys_selected).annotate(num_keys=Count('key')).filter(num_keys=goal) 
     key_list = unique_keys(remaining) 
     key_list = keycount(key_list, keys_selected) 
     keys_selected = "$".join(keys_selected) 
     keys_selected += '$' 
    context = {'key_list': key_list, 'keys_selected': keys_selected} 
    return context 

そして:

{% for key in key_list %} 
    <a href="{% url 'keysearch:index' %}?keys_selected={{ key.key }}${{ keys_selected }}" style="font-size: {{ key.count }}px;">({{ key.key }})</a> 
{% empty %} 
    <div class="w3-card-2 w3-black w3-center w3-rest"><h4>There are no key queries with this combination.</h4></div> 
{% endfor %} 
関連する問題