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.