Search code examples
pythondjangodjango-modelsmodel

How to iterate through queryset and get value Django


I wanna do a simple recommendation system based on users' Animals that they added. I want to show only products of a category, that's been mapped in "zwierzeta" dictionary. So basically if user has chosen that he has a horse (which is id 1, i want to show only products that have category 4) Also if user has more than 1 animals, i want to show them randomly from list of categories id. The logic seems to be fine, im just new at django and i have no idea how to actually iterate through the querysets and how to get a value(animal) from a particular queryset. The get method doesnt work. Do you have any idea how to get a particular value from a queryset?

class MyAnimal(models.Model):
    name = models.CharField(max_length=256)
    animal = models.ForeignKey(Animal, on_delete=models.CASCADE, null=False)

class ProductInStore(models.Model):
    product = models.ForeignKey('Product', on_delete=models.CASCADE)

class Product(models.Model):
    product_category = models.ManyToManyField(EcommerceProductCategory)

def list(self, request):
    ProductCategoryAnimal.objects
    qs = MyAnimal.objects.filter(user=self.request.user)
    if qs:
        for q in qs:
            categories = []
            get_category = ProductCategoryAnimal.objects.values_list('category_id', flat=True).get(animal_id=q.animal_id)
            categories.append(get_category)
        print(categories)
        result = ProductInStore.objects.filter(
            product__product_category__id=random.choice(categories)
        )
    else:
        result = ProductInStore.objects.all()[:1]
    return result.order_by('?')[:1]

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/rest_framework/generics.py", line 199, in get
    return self.list(request, *args, **kwargs)
  File "/Users/jakubstrawa/programming/DeorPythonek/api/ecommerce/views.py", line 180, in list
    product__category_id=random.choice(categories)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/query.py", line 942, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/query.py", line 962, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/query.py", line 969, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1358, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1380, in _add_q
    split_subq=split_subq, check_filterable=check_filterable,
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1319, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/sql/query.py", line 1156, in build_lookup
    raise FieldError('Related Field got invalid lookup: {}'.format(lookup_name))
django.core.exceptions.FieldError: Related Field got invalid lookup: category_id


Solution

  • You can simplify this to:

    def list(self, request):    
        zwierzeta = {1 : 4, 6: 5, 8: 6, 9: 6, 4: 3}
        qs = MyAnimal.objects.filter(user=self.request.user)
        if qs:
            category=random.choice([zwierzeta[q.animal_id] for q in qs])
            result = ProductInStore.objects.filter(
                product__product_category__id=category
            )
        else:
            result = ProductInStore.objects.all()
        return result.order_by('?')[:1]

    But using a dictionary with hardcoded items looks odd: it means you need to know the primary keys in advance and it is hard to later add new categories since it requires deploying a new software version. It might be better to model the relation between a category and an animal as a ManyToManyField or equivalent.