It's great that you could find where the issue is coming from!

Cheers,

Thomas


2012/12/20 Mike Dewhirst <mi...@dewhirst.com.au>

> On 19/12/2012 11:58pm, Thomas Orozco wrote:
>
>> Hi,
>>
>> If you have no relationship, I'm a bit at a loss. I think the easier
>> way would be to use a debugger if possible.
>>
>> I think we need to know what field is causing the ValidationError.
>> The line that's causing an error is in the to_python method of the
>> ModelChoiceField object.
>>
>> Basically, you'll need to use a debugger to extract as much
>> information from that object to be able to tell which field it is.
>> (ModelChoiceField.queryset will give you the list of objects that can
>> fit in that field. It could help).
>>
>
> Thomas
>
> I adjusted the error message in ModelChoiceField to include the key, value
> and the actual error raised. This revealed the problem. Thanks for pointing
> me in the right direction.
>
> It is raising DoesNotExist and nominating the first B record which would
> be deleted according to my code.
>
> This says it is already deleted. Which leads me to believe my code is
> deleting it unexpectedly as far as the Admin is concerned.
>
> I believe the Admin is built to delete records itself and won't cope with
> records being deleted behind its back. It must be designed to consider such
> a thing as an integrity error.
>
> If I adjust my code to simply null the item_id then everything looks good
> and I end up with a bunch of orphaned records in the database. Lucky its
> just a prototype :)
>
> I don't think I can do anything about this. It would need an Admin dev to
> figure out what to do. My inclination would be a meta option to signal that
> ModelChoiceField needn't worry if the record does not exist.
>
> Thanks for all your effort
>
> Much appreciated
>
> Mike
>
>
>
>> (See https://github.com/django/**django/blob/master/django/**
>> forms/models.py#L988<https://github.com/django/django/blob/master/django/forms/models.py#L988>
>> )
>>
>>
>>
>> On a side note, I can't see how your delete_bparts method would work:
>>
>> When you don't want to delete, you join using '' ( bpart.a_partcodes =
>> ' '.join(acodes) )
>> But you split using split(), which splits on whitespace: acodes =
>> bpart.a_partcodes.split()
>>
>> Am I missing something here?
>>
>
> It must be a typo because I actually join using a space.
>
>
>
>>
>>
>> Last, would you mind sharing the bpart.a_partcodes code ?
>>
>>
>> Cheers,
>>
>>
>> Thomas
>>
>> 2012/12/19 Mike Dewhirst <mi...@dewhirst.com.au>:
>>
>>> Thomas
>>>
>>> Thanks for replying
>>>
>>>
>>> On 19/12/2012 12:06am, Thomas Orozco wrote:
>>>
>>>>
>>>> Hi,
>>>>
>>>>
>>>> Could you provide the following information?
>>>>       - What's the relationship between A and B (model code of the
>>>> field,
>>>> if there is, would be great)
>>>>
>>>
>>>
>>> There is no relationship at all. A and B are separately and independently
>>> related to Item.
>>>
>>> A and B are actually copied from 'a' and 'b' which *are* related but
>>> exist
>>> purely as a stand-alone reference. When Item gets an A record (and it can
>>> have many) it is copied from its 'a' reference record. Item then
>>> automatically gets copies of all the corresponding 'b' reference records
>>> as
>>> B records - except duplicates are semi-skipped.
>>>
>>> Where a duplicate would have occurred, I append the A_code into a special
>>> field on the B record to indicate which A records were/are "interested"
>>> in
>>> that B record. When A records are deleted, it is necessary to delete
>>> their
>>> corresponding B records - unless another A record is still interested in
>>> which case we just remove the deleted A_code from the special field.
>>>
>>> I could send you the model code off-list if you wish.
>>>
>>>
>>>        - The code of your pre_delete signal handler / the method it
>>>> calls.
>>>>
>>>
>>>
>>> #  this lives in models.A_Part.py   #   #   #
>>>
>>> from django.db.models.signals import pre_delete, post_delete
>>>
>>> def cleanup_bparts(sender, instance, **kwargs):
>>>      instance.item.delete_bparts(a_**code=instance.a_code)
>>>
>>> pre_delete.connect(cleanup_**bparts, sender=A_Part, weak=False)
>>> #post_delete.connect(cleanup_**bparts, sender=A_Part, weak=False)
>>>
>>> #   #   #   #   #   #   #   #   #   #   #   #
>>>
>>> ... and the item.delete_bparts() code ...
>>>
>>>
>>> def delete_bparts(self, a_code):
>>>      qs_bpart = B_Part.objects.filter(item=**self,
>>>                                       a_partcodes__contains=a_code)
>>>      for bpart in qs_bpart:
>>>          acodes = bpart.a_partcodes.split()
>>>          if len(acodes) == 1:
>>>              bpart.delete()
>>>          else:
>>>              acodes.remove(a_code)
>>>              bpart.a_partcodes = ' '.join(acodes)
>>>              bpart.save()
>>>
>>>
>>>
>>>> I think you have a ForeignKey field that is required or limited and that
>>>> is causing the ValidationError.
>>>> Indeed, that line 988 is in the code for ModelChoiceField
>>>>
>>>
>>>
>>> I have been through all the fk fields and they are all null=True,
>>> blank=True
>>> and in Postgress each _id column is nullable.
>>>
>>> I also had an ordering sequence on some of the models and I removed all
>>> that
>>> as well.
>>>
>>> As mentioned earlier, embedded print statements seem to prove the
>>> delete_bparts() code is working nicely.
>>>
>>> When I comment out the pre-delete connection, the A_Part record gets
>>> delete
>>> as expected - but obviously it doesn't clean up the B records.
>>>
>>> Thanks ....
>>>
>>> Mike
>>>
>>>
>>>>
>>>> Best,
>>>>
>>>> Thomas
>>>>
>>>> 2012/12/17 Mike Dewhirst <mi...@dewhirst.com.au
>>>> <mailto:mi...@dewhirst.com.au>**>
>>>>
>>>>
>>>>      I'm getting a baffling ValidationError.
>>>>
>>>>      Request URL: 
>>>> http://127.0.0.1:8000/admin/__**assembly/item/4/<http://127.0.0.1:8000/admin/__assembly/item/4/>
>>>>
>>>>      
>>>> <http://127.0.0.1:8000/admin/**assembly/item/4/<http://127.0.0.1:8000/admin/assembly/item/4/>
>>>> >
>>>>      Django Version:         1.4.3
>>>>      Exception Type:         ValidationError
>>>>      Exception Value:        [u'Select a valid choice. That choice is
>>>> not
>>>>      one of the available choices.']
>>>>
>>>>      Exception Location:
>>>>      C:\usr\bin\lib\site-packages\_**_django\forms\models.py in
>>>> to_python,
>>>>
>>>>      line 988
>>>>      Python Version:         2.7.3
>>>>
>>>>      Background ...
>>>>
>>>>      I have an Item model which has two one-to-many relationships with
>>>>      other types of child records (call them A and B models).
>>>>
>>>>      In the Admin, when the user adds an A record, some B records get
>>>>      added automatically.
>>>>
>>>>      The next A record to get added does much the same but if there are
>>>>      any B duplicates it doesn't try to add those but instead just adds
>>>>      its mark to a special field in the B record which is already there.
>>>>
>>>>      My code - which from embedded print statements appears to be doing
>>>>      exactly what I want - will either delete the B record or just
>>>> remove
>>>>      the mark previously added. Eventually when the last A record is
>>>>      deleted the idea is that the last B records will go at the same
>>>> time.
>>>>
>>>>      Unfortunately, at the final hurdle we get the ValidationError at
>>>>      line 988 in to_python.
>>>>
>>>>      The local vars nominate ...
>>>>
>>>>      self    <django.forms.models.__**ModelChoiceField object at
>>>> 0x00F5DE70>
>>>>
>>>>      value   u'251'
>>>>      key     'pk'
>>>>
>>>>      ... and that is the pk of the A record which triggers the Item code
>>>>      via a pre_delete signal.
>>>>
>>>>      Summarising:
>>>>
>>>>      - the deletion/mark removal method lives in the Item model
>>>>      - the pre-delete signal is detected in the A record
>>>>      - the signal connects a stub method in the A record
>>>>      - the stub method in the A record calls the Item method
>>>>      - the Item method iterates over a filtered queryset of B records
>>>> and
>>>>      uses the passed value (the aforesaid mark from the A record) to
>>>>      decide whether to delete the B record or just remove the mark and
>>>>      save it
>>>>
>>>>      None of my code appears in the TraceBack so I assume the Admin is
>>>>      trying to delete the A record. I've tried both pre_delete and
>>>>      post_delete signals in the A record.
>>>>
>>>>      Why is it so?
>>>>
>>>>      Thanks for any hints
>>>>
>>>>      Mike
>>>>
>>>>
>>>>      --
>>>>      You received this message because you are subscribed to the Google
>>>>      Groups "Django users" group.
>>>>      To post to this group, send email to django-users@googlegroups.com
>>>>      <mailto:django-users@**googlegroups.com<django-users@googlegroups.com>
>>>> >.
>>>>
>>>>      To unsubscribe from this group, send email to
>>>>      django-users+unsubscribe@__goo**glegroups.com<http://googlegroups.com>
>>>>      
>>>> <mailto:django-users%**2bunsubscr...@googlegroups.com<django-users%252bunsubscr...@googlegroups.com>
>>>> **>.
>>>>
>>>>      For more options, visit this group at
>>>>      
>>>> http://groups.google.com/__**group/django-users?hl=en<http://groups.google.com/__group/django-users?hl=en>
>>>>      
>>>> <http://groups.google.com/**group/django-users?hl=en<http://groups.google.com/group/django-users?hl=en>
>>>> >.
>>>>
>>>>
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Django users" group.
>>>> To post to this group, send email to django-users@googlegroups.com.
>>>> To unsubscribe from this group, send email to
>>>> django-users+unsubscribe@**googlegroups.com<django-users%2bunsubscr...@googlegroups.com>
>>>> .
>>>> For more options, visit this group at
>>>> http://groups.google.com/**group/django-users?hl=en<http://groups.google.com/group/django-users?hl=en>
>>>> .
>>>>
>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "Django users" group.
>>> To post to this group, send email to django-users@googlegroups.com.
>>> To unsubscribe from this group, send email to
>>> django-users+unsubscribe@**googlegroups.com<django-users%2bunsubscr...@googlegroups.com>
>>> .
>>> For more options, visit this group at
>>> http://groups.google.com/**group/django-users?hl=en<http://groups.google.com/group/django-users?hl=en>
>>> .
>>>
>>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To post to this group, send email to django-users@googlegroups.com.
> To unsubscribe from this group, send email to django-users+unsubscribe@**
> googlegroups.com <django-users%2bunsubscr...@googlegroups.com>.
> For more options, visit this group at http://groups.google.com/**
> group/django-users?hl=en<http://groups.google.com/group/django-users?hl=en>
> .
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to