I have a legacy database that we want to replace, and Django is still new 
to us. There are some 40,000 items in the old db, and each item has an 
item_number that is not necessarily the primary key; that way, the users 
can maintain their own sku number system and we can maintain data integrity 
without either of us getting in the other's way. And it also helps 
guarantee data integrity as we migrate the data from the old db to our new 
db, since Django will assign PK's and manage FKs as it goes, and leave the 
item_numbers intact. 

I'm running into trouble though, because Django Views and Forms all assume 
that, when performing a lookup, the input is going to be a primary key. For 
example, I have an item where item.item_number = '515874'. So when I put 
that item_number in, Django looks for an item where item.pk = 515874 and 
raises a ValidationError--because there is no such item. The actual PK for 
item '515874' is 41293. So I need to take the user's input, use it to get 
the right item based on its item_number, and give it back to Django to use 
instead. 

CreateView and {{ form.as_table }} default to populating a dropdown, which 
would mean that the whole item_num/pk problem would go away... but with 
Django querying *all* 40,000 items, the page literally took 20 seconds to 
load. So the users are going to need to type in item_numbers which I'll 
have to convert to PKs. 

Overriding form_valid() and clean() weren't working, because the 
no-such-item ValidationError had already been raised before either method 
could be called. Defining a custom field and overriding that field's 
validate method seems to be the right way to go, but I'm still running into 
issues. The validate method is being called and is returning the correct 
value, but Django seems to be throwing it away. When I step through it with 
the debugger, I see the item where (item.id = 41293 and item.item_number = 
'515874') is correctly being returned. But when Django calls clean() next, 
that item is nowhere to be found and it's busy cleaning '515874', which was 
the original input. And then it breaks.

This particular view/ModelForm is a simple tool for non-programmers to be 
able to evaluate a small part of a background process.

class ItemsTestCollection(models.Model):
    """An item to be tested in Box Opt."""
    item = models.ForeignKey('item.Item', on_delete=models.CASCADE)
    qty = models.IntegerField()
    case = models.ForeignKey('EvaluateTestCase', on_delete=models.CASCADE)
    box = models.ForeignKey('BoxResults', on_delete=models.CASCADE, null=True)


class ItemNumField(forms.CharField):

    def validate(self, value):
        # item = Item.objects.get(item_number=value)
        # value = item.id
        # return value
        return Item.objects.get(item_number=value)

class AddItem(forms.ModelForm):

    item = ItemNumField()

    class Meta:
        model = ItemsTestCollection
        fields = ['item', 'qty', 'case']


class AddItemsToEvaluateCreateView(CreateView):
    model = ItemsTestCollection
    form_class = AddItem
    template_name = 'utils\evaluate.html'

    def get_queryset(self):
        return ItemsTestCollection.objects.filter(case_id=self.kwargs['pk'])

    def get_object(self, queryset=None):
        return EvaluateTestCase.objects.get(pk=self.kwargs['pk'])

    def get_success_url(self):
        if 'add_more' in self.request.POST:
            return reverse('utils:evaluate', kwargs={'pk': self.kwargs['pk']})
        elif 'optimize' in self.request.POST:
            return reverse('utils:results', kwargs={'pk': self.kwargs['pk']})
        else:
            return '/'

    def get_context_data(self, **kwargs):
        context = super().get_context_data()
        context['case_id'] = self.kwargs['pk']
        context['items_in_order'] = 
ItemsTestCollection.objects.filter(case_id=self.kwargs['pk'])
        return context


ValueError at /utils/box-optimization/add-items/118

Cannot assign "'515874'": "ItemsTestCollection.item" must be a "Item" instance.

Request Method: POST
Request URL: http://localhost:8000/utils/box-optimization/add-items/118
Django Version: 2.0.5
Exception Type: ValueError
Exception Value: 

Cannot assign "'515874'": "ItemsTestCollection.item" must be a "Item" instance.

Exception Location: 
C:\miniconda3\envs\django\lib\site-packages\django\db\models\fields\related_descriptors.py
 
in __set__, line 197
Python Executable: C:\miniconda3\envs\django\python.exe
Python Version: 3.6.5
Python Path: 

['C:\\WMS Repository\\Warehouse Management System',
 'C:\\Program Files\\JetBrains\\PyCharm 2017.3.3\\helpers\\pydev',
 'C:\\WMS Repository\\Warehouse Management System',
 'C:\\Program Files\\JetBrains\\PyCharm 2017.3.3\\helpers\\pydev',
 'C:\\Users\\heast\\.PyCharm2018.1\\system\\cythonExtensions',
 'C:\\miniconda3\\envs\\django\\python36.zip',
 'C:\\miniconda3\\envs\\django\\DLLs',
 'C:\\miniconda3\\envs\\django\\lib',
 'C:\\miniconda3\\envs\\django',
 'C:\\Users\\heast\\AppData\\Roaming\\Python\\Python36\\site-packages',
 'C:\\miniconda3\\envs\\django\\lib\\site-packages',
 'C:\\Program Files\\JetBrains\\PyCharm '
 '2017.3.3\\helpers\\pycharm_matplotlib_backend']

Server time: Mon, 16 Jul 2018 15:46:11 -0400
Environment:


Request Method: POST
Request URL: http://localhost:8000/utils/box-optimization/add-items/118

Django Version: 2.0.5
Python Version: 3.6.5
Installed Applications:
['item.apps.ItemConfig',
 'inventory.apps.InventoryConfig',
 'fulfillment.apps.FulfillmentConfig',
 'manifest.apps.ManifestConfig',
 'order.apps.OrderConfig',
 'utils.apps.UtilsConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles']
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']



Traceback:

File 
"C:\miniconda3\envs\django\lib\site-packages\django\core\handlers\exception.py" 
in inner
  35.             response = get_response(request)

File 
"C:\miniconda3\envs\django\lib\site-packages\django\core\handlers\base.py" 
in _get_response
  128.                 response = self.process_exception_by_middleware(e, 
request)

File 
"C:\miniconda3\envs\django\lib\site-packages\django\core\handlers\base.py" 
in _get_response
  126.                 response = wrapped_callback(request, *callback_args, 
**callback_kwargs)

File 
"C:\miniconda3\envs\django\lib\site-packages\django\views\generic\base.py" 
in view
  69.             return self.dispatch(request, *args, **kwargs)

File 
"C:\miniconda3\envs\django\lib\site-packages\django\views\generic\base.py" 
in dispatch
  89.         return handler(request, *args, **kwargs)

File 
"C:\miniconda3\envs\django\lib\site-packages\django\views\generic\edit.py" 
in post
  172.         return super().post(request, *args, **kwargs)

File 
"C:\miniconda3\envs\django\lib\site-packages\django\views\generic\edit.py" 
in post
  141.         if form.is_valid():

File "C:\miniconda3\envs\django\lib\site-packages\django\forms\forms.py" in 
is_valid
  179.         return self.is_bound and not self.errors

File "C:\miniconda3\envs\django\lib\site-packages\django\forms\forms.py" in 
errors
  174.             self.full_clean()

File "C:\miniconda3\envs\django\lib\site-packages\django\forms\forms.py" in 
full_clean
  378.         self._post_clean()

File "C:\miniconda3\envs\django\lib\site-packages\django\forms\models.py" 
in _post_clean
  396.             self.instance = construct_instance(self, self.instance, 
opts.fields, opts.exclude)

File "C:\miniconda3\envs\django\lib\site-packages\django\forms\models.py" 
in construct_instance
  60.             f.save_form_data(instance, cleaned_data[f.name])

File 
"C:\miniconda3\envs\django\lib\site-packages\django\db\models\fields\__init__.py"
 
in save_form_data
  838.         setattr(instance, self.name, data)

File 
"C:\miniconda3\envs\django\lib\site-packages\django\db\models\fields\related_descriptors.py"
 
in __set__
  197.                     self.field.remote_field.model._meta.object_name,

Exception Type: ValueError at /utils/box-optimization/add-items/118
Exception Value: Cannot assign "'515874'": "ItemsTestCollection.item" must 
be a "Item" instance.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/16a9d28f-a23a-4112-acc5-f7be9bef4d12%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to