2017-11-11 5 views
2

Mein Ziel ist es, einen Abschnitt "Empfohlene Produkte" auf meiner E-Commerce-Website zu erstellen, wenn Sie auf eine einzelne Produktseite zugreifen.Verwandte Objekte über Tags in Django abrufen

Ich habe ein sereis von Produkten, die mehrere benutzerdefinierte Tags im Admin haben. Das Kennzeichnungssystem ist eine Kombination aus django-taggit und modelcluster, wie in der Wagtail-CMS docs beschrieben.

Ich versuche es so zu machen, dass Django beim Zugriff auf eine Produktseite alle anderen Produkte mit den gleichen/ähnlichen Tags betrachtet und im Abschnitt "Empfohlene Produkte" basierend auf der Anzahl der identischen Tags auflistet. Die django-taggit Dokumente scheinen diese Notwendigkeit in ihrer API mit der get_related() Funktion, wie their docs zu adressieren.

Ich kämpfe um das funktioniert aber wie ich weiterhin auf Fehler, die neueste sein Exception Type: KeyError at /categories/test-category/test-product/ Exception Value: (15,). Hier ist mein Code so weit:

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 

EDIT | Voll Fehler Zurückverfolgungs unter:

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,) 

Wenn ich versuche, und auf andere Produktseiten ich die gleichen Fehler, nur mit einem anderen Ausnahmewert. Die Funktion erwartet einen Schlüssel von einem Diktat, aber aus irgendeinem Grund erhält sie stattdessen den Wert ... Könnte das ein Kompatibilitätsproblem mit dem Code sein?

+0

Würde 'related_products = current_tags.similar_objects()' Ihnen die Liste der gewünschten 'Product' Objekte zurückgeben? Das Durchreichen von 'Product.objects.filter (...)' scheint keinen Zweck zu erfüllen (noch ist es eine gültige Syntax für die Methode 'filter'). – gasman

+0

Das war, was ich mit meinem ersten Versuch versuchte - gibt mir immer noch den gleichen Fehler: 'Exception Typ: KeyError at/categories/Test-Kategorie/Test-Produkt/Exception Value: (15,)' und die Traceback führt zu ' tuple (result [k] für k in lookup_keys) '@gasman – DDiran

+0

Bitte teilen Sie die volle Traceback - eine einzige Zeile Code sagt mir wirklich nichts. – gasman

Antwort

0

OK also nach viel Recherche und Basteln habe ich eine Lösung gefunden, jedoch funktioniert diese nur für Django> = 1.9.

Github Benutzer Nickhudkins lief in das gleiche Problem und bearbeitet die similar_objects() Funktion, um den KeyError aufzulösen, wie in seinem ticket beschrieben.

Die Lösung besteht darin, in das Taggit managers.py zu gehen und die Funktion wie folgt zu bearbeiten (+ bedeutet das Hinzufügen der Zeilen und - das Entfernen).

   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: 
0

Wenn Sie nicht wollen, django-taggit, andere mögliche Lösung flicken ist raw SQL-Abfrage zu verwenden. Ähnlich wie das:

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'); 

ArticlePage - mein Modell

ArticleTag - m2m-Modell für meine Tags (iherited von TaggedItemBase)

wagtailcore_page - Basis Bachstelze Tabelle für Seiten

taggit_tag - Taggit Tag Tabelle

(1, 2, 3) - j Ust Beispiel Tag IDs

Hoffe es hilft! Fühlen Sie sich frei, passen Sie es Ihren Bedürfnissen an.

Verwandte Themen