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)



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/>
     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>.

     To unsubscribe from this group, send email to
     django-users+unsubscribe@__googlegroups.com
     <mailto: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.


--
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.



--
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