0

I am trying to create a list of ProductPart objects where ProductPart.part matches the value of an instance of Variety.variety_name. Here is a demonstration of my problem.

> v = Variety.objects.get(id=2)
> p = ProductPart.objects.get(id=1)
> v.variety_name
'Non Pareil (Inshell)'
> p.part
<Variety: Non Pareil (Inshell)>
> a = ProductPart.objects.values().filter(part=v.variety_name)
...
ValueError: invalid literal for int() with base 10: 'Non Pareil (Inshell)'

This pattern seems to work elsewhere in my models, but for some reason it isn't working here. Does anyone know what I am doing wrong? Can someone help me understand why it is reaching for an int() object?

Traceback:

Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Projects\AlmondKing\AlmondKing\InventoryLogs\models.py", line 49, in _total_sales_of_variety
  sold = ProductPart.objects.values().filter(part=self.variety_name)
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\query.py", line 679, in filter
  return self._filter_or_exclude(False, *args, **kwargs)
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\query.py", line 697, in _filter_or_exclude
  clone.query.add_q(Q(*args, **kwargs))
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\sql\query.py", line 1304, in add_q
  clause, require_inner = self._add_q(where_part, self.used_aliases)
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\sql\query.py", line 1332, in _add_q
  allow_joins=allow_joins, split_subq=split_subq,
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\sql\query.py", line 1194, in build_filter
  lookups, value)
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\fields\related.py", line 1740, in get_lookup_constraint
   ookup_class(target.get_col(alias, source), val), AND)
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\lookups.py", line 96, in __init__
  self.rhs = self.get_prep_lookup()
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\lookups.py", line 134, in get_prep_lookup
  return self.lhs.output_field.get_prep_lookup(self.lookup_name, self.rhs)
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\fields\__init__.py", line 727, in get_prep_lookup
  return self.get_prep_value(value)
File "C:\Users\Adam\Envs\AlmondKing\lib\site-packages\django\db\models\fields\__init__.py", line 985, in get_prep_value
  return int(value)
ValueError: invalid literal for int() with base 10: 'Non Pareil (Inshell)'

Models:

class Variety(models.Model):
    product_group = models.ForeignKey(ProductGroup)
    variety_name = models.CharField(max_length=140)
    husked = models.BooleanField()
    finished = models.BooleanField() #defunct
    description = models.CharField(max_length=500, blank=True)

class ProductPart(models.Model):
    product = models.ForeignKey(Product)
    part = models.ForeignKey(Variety)
    qty = models.DecimalField(max_digits=28, decimal_places=2)
Adam Starrh
  • 6,428
  • 8
  • 50
  • 89

4 Answers4

2

You are trying to match a foreign key to a string, you need to provide the model

ProductPart.objects.values().filter(part=v)

Note: the values isn't necessary either

ProductPart.objects.filter(part=v)

From the documentation for Values

a QuerySet subclass that returns dictionaries when used as an iterable, rather than model-instance objects.

In other words, you are losing some control over your objects with your current approach

Sayse
  • 42,633
  • 14
  • 77
  • 146
  • Wanted to note that I'm using the `values` to set up my list comprehension: `total_variety_sold = sum([ProductPart['total_qty_sold'] for ProductPart in sold])` . While I haven't gotten this working yet, it doesn't like it if I remove the `values()` bit. – Adam Starrh Jun 16 '15 at 08:24
  • 1
    @AdamStarrh - You may want to switch your query around and do the `filter` first then (`.filter(..).values()`) – Sayse Jun 16 '15 at 08:25
  • @AdamStarrh - No worries, generally `values` or `values_list` should be the last parts of your query, django (or more specifically south) is clever enough to try to optimize your queries – Sayse Jun 16 '15 at 08:38
2

According to Django ORM you should address model objects directly in a filter (it makes code easy readable)

v = Variety.objects.get(id=2)
a = ProductPart.objects.filter(part=v)
akarilimano
  • 1,034
  • 1
  • 10
  • 17
2

That's an error you get when you try to parse a string to an int and is not a valid integer: int('hello')

You are trying to do something weird in this query:

a = ProductPart.objects.values().filter(part=v.variety_name)

Basically, part is a foreign key to Variety (a foreign key in this case is an integer) and you are trying to compare it with a string v.variety_name.

I think the correct way to do it is like this:

a = ProductPart.objects.filter(part=v)
Paulo Bu
  • 29,294
  • 6
  • 74
  • 73
2

You should use:

a = ProductPart.objects.values().filter(part__variety_name=v.variety_name)

Check this Django Doc Lookups that span relationships

Amar
  • 666
  • 5
  • 13
  • This syntax doesn't seem to be working, but thanks for pointing me to this link! – Adam Starrh Jun 16 '15 at 08:00
  • Yeah sorry for that! But basically you can access attribute of related objects in query by using "__" (double underscores) . Hope this helps! Peace!! – Amar Jun 16 '15 at 08:08