通过Django中的标签获取相关对象

时间:2017-11-11 17:00:58

标签: django django-queryset wagtail django-taggit

我的目标是在访问单个产品页面时在我的电子商务网站中构建“推荐产品”部分。

我有一些产品,在管理员中有几个用户定义的标签。标记系统是django-taggitmodelcluster的组合,详见Wagtail-CMS docs

我试图这样做,以便在访问产品页面时,Django会查看具有相同/类似标签的所有其他产品,并根据相同标签的数量将它们列在“推荐产品”部分中。根据{{​​3}},django-taggit文档似乎在其API中使用get_related()函数来满足此需求。

我正在努力让这个工作,但是当我继续遇到错误时,最新的是Exception Type: KeyError at /categories/test-category/test-product/ Exception Value: (15,)。到目前为止,这是我的代码:

class ProductTag(TaggedItemBase):
    content_object = ParentalKey('Product', related_name='tagged_items')

class Product(Page):
    ...

    tags = ClusterTaggableManager(through=ProductTag, blank=True)

def get_context(self, request):
    context = super(Product, self).get_context(request)

    current_tags = self.tags
    related_products = Product.objects.filter(current_tags.similar_objects())

    context['related_products'] = related_products
    return context

编辑 |完整错误回溯如下:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/categories/test-category/test-product/

Django Version: 1.11.5
Python Version: 3.5.2
Installed Applications:
['home',
 'search',
 'products',
 'wagtail.wagtailforms',
 'wagtail.wagtailredirects',
 'wagtail.wagtailembeds',
 'wagtail.wagtailsites',
 'wagtail.wagtailusers',
 'wagtail.wagtailsnippets',
 'wagtail.wagtaildocs',
 'wagtail.wagtailimages',
 'wagtail.wagtailsearch',
 'wagtail.wagtailadmin',
 'wagtail.wagtailcore',
 'modelcluster',
 'taggit',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles']
Installed Middleware:
['django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'wagtail.wagtailcore.middleware.SiteMiddleware',
 'wagtail.wagtailredirects.middleware.RedirectMiddleware']



Traceback:

File "C:\Users\ddl_9\Envs\fstvl\lib\site-packages\django\core\handlers\exception.py" in inner
  41.             response = get_response(request)

File "C:\Users\ddl_9\Envs\fstvl\lib\site-packages\django\core\handlers\base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\ddl_9\Envs\fstvl\lib\site-packages\django\core\handlers\base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\ddl_9\Envs\fstvl\lib\site-packages\wagtail\wagtailcore\views.py" in serve
  26.     return page.serve(request, *args, **kwargs)

File "C:\Users\ddl_9\Envs\fstvl\lib\site-packages\wagtail\wagtailcore\models.py" in serve
  773.             self.get_context(request, *args, **kwargs)

File "C:\Users\ddl_9\Desktop\fstvl\products\models.py" in get_context
  143.      related_products = current_tags.similar_objects()

File "C:\Users\ddl_9\Envs\fstvl\lib\site-packages\taggit\utils.py" in inner
  146.         return func(self, *args, **kwargs)

File "C:\Users\ddl_9\Envs\fstvl\lib\site-packages\taggit\managers.py" in similar_objects
  350.                 tuple(result[k] for k in lookup_keys)

Exception Type: KeyError at /categories/test-category/test-product/
Exception Value: (15,)

如果我尝试访问其他产品页面,我会收到相同的错误,只是具有不同的异常值。该函数期待来自dict的密钥,但由于某种原因,它被赋予了价值......这可能是代码的兼容性问题吗?

2 个答案:

答案 0 :(得分:0)

好的,经过大量的研究和修补,我找到了解决方案,但仅适用于Django> = 1.9

Github用户nickhudkins遇到了同样的问题并编辑了similar_objects()函数来解决KeyError,详见他的ticket

解决方案是进入taggit managers.py并按如下方式编辑函数(+表示添加行并删除它们)。

             objs = rel_model._default_manager.filter(**{
                  "%s__in" % remote_field.field_name: [r["content_object"] for r in qs]
              })
 +            actual_remote_field_name = remote_field.field_name
 +            if VERSION > (1, 9):
 +                actual_remote_field_name = f.target_field.get_attname()
 +            else:
 +                actual_remote_field_name = f.related_field.get_attname()
              for obj in objs:
 -                items[(getattr(obj, remote_field.field_name),)] = obj
 +                items[(getattr(obj, actual_remote_field_name),)] = obj
          else:
              preload = {}
              for result in qs:

答案 1 :(得分:0)

如果您不想修补raw,其他可能的解决方案是使用ArticlePage.objects.raw('select a.page_ptr_id, p.title, count(at.tag_id) as tag_count from article_articlepage a join wagtailcore_page p on a.page_ptr_id = p.id join article_articletag at on at.content_object_id = a.page_ptr_id join taggit_tag t on t.id = at.tag_id where tag_id in (1, 2, 3) group by (page_ptr_id, p.id) order by tag_count desc'); sql查询。与此类似:

ArticlePage

ArticleTag - 我的模特

TaggedItemBase - 我的代码的m2m模型(来自wagtailcore_page

taggit_tag - 页面基础Wagtail表

(1, 2, 3) - Taggit标签表

person(marc,male). person(faith,female). person(alan,male). person(kim,female). person(missy,female). person(eric,male). person(charles,male). person(eleanor,female). person(roland,male). person(corey,male). person(amy,female). person(tyler,male). person(matty,male). person(kaydi,female). person(jenna,female). person(allison,female). person(emma,female). person(hayley,female). person(jaylin,female). person(lukus,male). person(brendon,male). person(bradley,male). person(tylerh,male). person(dayna,female). person(victor,male). person(jacoby,male). person(javi,male). person(jordan,male). person(jaxson,male). person(kenzie,female). person(richard,male). person(reggie,male). person(reggiejr,male). person(beverly,female). person(floyd,male). person(marjorie,female). person(kevin,male). parent(marc,alan). parent(faith,alan). parent(charles,marc). parent(charles,kim). parent(charles,missy). parent(charles,eric). parent(eleanor,marc). parent(eleanor,kim). parent(eleanor,missy). parent(eleanor,eric). parent(eric,matty). parent(eric,tyler). parent(eric,kaydi). parent(amy,matty). parent(amy,tyler). parent(amy,kaydi). parent(missy,jordan). parent(missy,jaxson). parent(missy,kenzie). parent(richard,jordan). parent(corey,kenzie). parent(corey,jaxson). parent(kim,allison). parent(kim,jenna). parent(kim,emma). parent(kim,jaylin). parent(kim,hayley). parent(kim,dayna). parent(roland,allison). parent(roland,jenna). parent(roland,emma). parent(roland,jaylin). parent(roland,hayley). parent(roland,dayna). parent(dayna,javi). parent(dayna,jacoby). parent(victor,javi). parent(victor,jacoby). parent(jenna,bradley). parent(brendon,bradley). parent(tylerh,lukus). parent(allison,lukus). parent(reggie,reggiejr). parent(beverly,reggiejr). parent(floyd,beverly). parent(marjorie,beverly). parent(reggiejr,kevin). parent(floyd,eleanor). parent(marjorie,eleanor). married(marc,faith). married(charles,eleanor). married(kim,roland). married(eric,amy). married(missy,corey). married(dayna,victor). married(allison,tylerh). married(marjorie,floyd). married(beverly,reggie). father(X, Y) :- parent(X, Y), person(X,male). mother(X, Y) :- parent(X, Y), person(female,Y). son(X, Y) :- parent(Y,X), person(X,male). daughter(X, Y) :- parent(X,Y), person(Y,female). grandparent(X, Z) :- parent(X, Y), parent(Y, Z). grandfather(X, Z) :- grandparent(X, Z), person(X,male). grandmother(X, Z) :- grandparent(X, Z), person(female,Y). grandson(X, Z) :- grandchild(X, Z), person(X,male). granddaughter(Y, Z) :- grandchild(Y, Z), person(Y,female). grandchild(X, Z) :- grandparent(Z, X). sibling(X,Y) :- parent(Z,X), parent(Z,Y). brother(Y, X) :- sibling(Y,X), person(X,male), not(X=Y). sister(X, Y) :- sibling(X, Y), person(Y,female). auntoruncle(X, W) :- sibling(X, Y), parent(Y, W). auntoruncle(X, Z) :- married(X,Y), sibling(Y,W), parent(W,Z). uncle(X, W) :- auntoruncle(X, W), person(X,male). aunt(X, W) :- auntoruncle(X, W), person(female,Y). cousin(X, Y) :- parent(Z, X), auntoruncle(Z, Y), Y\=X. nieceornephew(X, Y) :- parent(Z, X), sibling(Z, Y). nephew(X, Y) :- nieceornephew(X, Y), person(X,male). niece(X, Y) :- nieceornephew(Y, X), person(Y,female). greatgrandparent(X, Z) :- parent(X, Y), grandparent(Y, Z). greatgrandfather(X, Z) :- greatgrandparent(X, Z), person(X,male). greatgrandmother(X, Z) :- greatgrandparent(X, Z), person(female,Y). greatgrandchild(X, Z) :- child(X, Y), grandchild(X, Z). greatgrandson(X, Z) :- greatgrandchild(X, Z), person(X,male). greatgranddaughter(X, Z) :- greatgrandchild(X, Z), person(female,Y). married_to(X,Y) :- married(X,Y), not divorced(X,Y). whatgender(X,Y) :- person(X,Y). **child(X, Y) :- parent(Y, X). cousinonceremoved(X, Y) :- cousin(Z, Y), child(X, Z). halfsibling(X,Y) :- parent(Z,X), parent(Z,Y), parent(P,X), \+parent(P,Y). halfbrother(X,Y) :- halfsibling(X,Y), male(X). halfsister(X,Y) :- halfsibling(X,Y), female(X).** - 只是示例标记ID

希望它有所帮助!随意适应您的需求。