ecdnj
ecdnj

Reputation: 21

int() argument must be a string, a bytes-like object or a number, not 'ModelBase'

I'm fairly new to Django, and coding in general so this could be a conceptual oversight, but I'm running out of ideas so any help is appreciated.

I'm trying to add logic to my form's clean() method which has nested try blocks. I'm trying to get object instances from different ForeignKey related models in each try block. The first two levels seem to work fine, but the third level throws the error below. I've printed the value and type for wine_get.wine_id and I get back 6 and 'int' respectively, so I'm not sure why this isn't considered a number.

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/post/new/

Django Version: 2.1
Python Version: 3.6.5
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'debug_toolbar',
 'bootstrap4',
 'accounts',
 'groups',
 'posts']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware']



Traceback:

File "/anaconda3/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/anaconda3/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "/anaconda3/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/anaconda3/lib/python3.6/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/anaconda3/lib/python3.6/site-packages/django/contrib/auth/mixins.py" in dispatch
  52.         return super().dispatch(request, *args, **kwargs)

File "/anaconda3/lib/python3.6/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/anaconda3/lib/python3.6/site-packages/django/views/generic/edit.py" in post
  141.         if form.is_valid():

File "/anaconda3/lib/python3.6/site-packages/django/forms/forms.py" in is_valid
  185.         return self.is_bound and not self.errors

File "/anaconda3/lib/python3.6/site-packages/django/forms/forms.py" in errors
  180.             self.full_clean()

File "/anaconda3/lib/python3.6/site-packages/django/forms/forms.py" in full_clean
  382.         self._clean_form()

File "/anaconda3/lib/python3.6/site-packages/django/forms/forms.py" in _clean_form
  409.             cleaned_data = self.clean()

File "/Users/evan/code/wine/wineProject/wineProject/posts/forms.py" in clean
  78.                                 wine = wine_get,

File "/anaconda3/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
  82.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/anaconda3/lib/python3.6/site-packages/django/db/models/query.py" in get
  390.         clone = self.filter(*args, **kwargs)

File "/anaconda3/lib/python3.6/site-packages/django/db/models/query.py" in filter
  841.         return self._filter_or_exclude(False, *args, **kwargs)

File "/anaconda3/lib/python3.6/site-packages/django/db/models/query.py" in _filter_or_exclude
  859.             clone.query.add_q(Q(*args, **kwargs))

File "/anaconda3/lib/python3.6/site-packages/django/db/models/sql/query.py" in add_q
  1263.         clause, _ = self._add_q(q_object, self.used_aliases)

File "/anaconda3/lib/python3.6/site-packages/django/db/models/sql/query.py" in _add_q
  1287.                     split_subq=split_subq,

File "/anaconda3/lib/python3.6/site-packages/django/db/models/sql/query.py" in build_filter
  1225.         condition = self.build_lookup(lookups, col, value)

File "/anaconda3/lib/python3.6/site-packages/django/db/models/sql/query.py" in build_lookup
  1096.         lookup = lookup_class(lhs, rhs)

File "/anaconda3/lib/python3.6/site-packages/django/db/models/lookups.py" in __init__
  20.         self.rhs = self.get_prep_lookup()

File "/anaconda3/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py" in get_prep_lookup
  115.                 self.rhs = target_field.get_prep_value(self.rhs)

File "/anaconda3/lib/python3.6/site-packages/django/db/models/fields/__init__.py" in get_prep_value
  965.         return int(value)

Exception Type: TypeError at /post/new/
Exception Value: int() argument must be a string, a bytes-like object or a number, not 'ModelBase'

Local vars from error:

Variable    Value
__class__   <class 'posts.forms.WineForm'>
post_type   'opened'
quantity    2
self    <WineForm bound=True, valid=True, fields=(winemaker;wine;vintage;post_type;quantity;rating;location;tasting_notes)>
vintage '1950'
wine    'Cellar 2'
wine_get    <Wine: Cellar 2>
winemaker   'Cellar 2'
winemaker_get   <WineMaker: Cellar 2>

Session data:

Variable    Value
'_auth_user_backend'  'django.contrib.auth.backends.ModelBackend'
'_auth_user_hash'  '2c72b4192e2d568f616919e66da6b281d3764e4f'
'_auth_user_id'  '2'

models.py

class WineMaker(models.Model):
winemaker_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255, unique=True)
region = models.ForeignKey(
    WineRegion,
    db_column = 'region_id',
    related_name = 'winemaker_region',
    on_delete = models.CASCADE,
    null = True
)

def __str__(self):
    return self.name

class Meta:
    db_table = 'winemakers'

class Wine(models.Model):
wine_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=510)
winemaker = models.ForeignKey(
    WineMaker,
    db_column = 'winemaker_id',
    related_name = 'wine_winemakers',
    on_delete = models.CASCADE
)
vintage = models.CharField(
    max_length = 10,
    choices = VINTAGES,
    default = 'none'
)
description = models.TextField(max_length=3000, null=True)
style = models.ForeignKey(
    Style,
    db_column = 'style_id',
    related_name = 'wine_styles',
    on_delete = models.CASCADE,
    null = True
)
varietal = models.ForeignKey(
    Varietal,
    db_column = 'varietal_id',
    related_name = 'wine_varietals',
    on_delete = models.CASCADE,
    null = True
)
blend = models.ForeignKey(
    Blend,
    db_column = 'blend_id',
    related_name = 'wine_blends',
    on_delete = models.CASCADE,
    null = True
)

def __str__(self):
    return self.name

class Meta:
    db_table = 'wines'
    unique_together = ('winemaker', 'name', 'vintage')

class UserCellar(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(
    settings.AUTH_USER_MODEL,
    related_name = 'userCellar_users',
    on_delete = models.CASCADE
)
wine = models.ForeignKey(
    Wine,
    db_column = 'wine_id',
    related_name = 'userCellar_wines',
    on_delete = models.CASCADE
)
quantity = models.SmallIntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __int__(self):
    return self.wine_id

def __str__(self):
    return self.wine.name

class Meta:
    db_table = 'user_cellars'
    unique_together = ('user', 'wine')

...

forms.py

from django import forms
from .models import *
from django.contrib.auth import get_user_model
from .choices import VINTAGES, POST_TYPE_CHOICES

user = get_user_model()

class WineForm(forms.Form):
    winemaker = forms.CharField(max_length=255)
    wine = forms.CharField(max_length=510)
    vintage = forms.ChoiceField(
        choices = VINTAGES
    )
    post_type = forms.ChoiceField(
        choices = POST_TYPE_CHOICES
    )
    quantity = forms.IntegerField(
        required = False
    )
    rating = forms.IntegerField(
        required = False
        )
    location = forms.CharField(
        max_length = 255,
        required = False
        )
    tasting_notes = forms.CharField(
        max_length = 2000,
        required = False,
        widget = forms.Textarea
        )

    class Meta:
        labels = {
            'winemaker' : 'Winemaker',
            'wine' : 'Wine',
            'vintage' : 'Vintage',
            'post_type' : 'Activity Type',
            'rating' : 'Rating',
            'location' : 'Location',
            'tasting_notes' : 'Tasting Notes',
        }

    def __init__(self, *args, **kwargs):
        super(WineForm, self).__init__(*args, **kwargs)
        self.fields['quantity'].widget.attrs={
            'id': 'quantity'
        }

    def clean(self):
        super().clean()
        winemaker = self.cleaned_data.get('winemaker')
        wine = self.cleaned_data.get('wine')
        vintage = self.cleaned_data.get('vintage')
        post_type = self.cleaned_data.get('post_type')
        quantity = self.cleaned_data.get('quantity')

        if post_type and quantity:
            # If both fields are valid
            if post_type == 'opened':
                try:
                    # Try to get the WineMaker instance
                    winemaker_get = WineMaker.objects.get(
                        name = winemaker,
                    )
                    try:
                        #Try to get the Wine instance
                        wine_get = Wine.objects.get(
                            name = wine,
                            winemaker = winemaker_get,
                            vintage = vintage,
                        )
                        try:
                            #Try to get the UserCellar instance
                            cellar_get = UserCellar.objects.get(
                                user = user,
                                wine = wine_get,
                            )

    ...

Upvotes: 1

Views: 826

Answers (1)

Endre Both
Endre Both

Reputation: 5730

I'm afraid my original answer below is rubbish. When filtering on a foreign key, Django doesn't care if you pass an object or just a primary key:

# wm is a WineMaker object; the next 2 lines are both valid
wines1 = Wine.objects.filter(winemaker=wm)
wines2 = Wine.objects.filter(winemaker=wm.id)

===================

The stack trace is clear that the issue is with this line (though the error message is arguably less than helpful):

wine_id = wine_get.wine_id

Since wine_id is a foreign key, you need to pass a Wine instance:

wine_id = wine_get

Upvotes: 1

Related Questions