Discussion:
how to delete in the admin - strategy needed
Mike Dewhirst
2013-02-04 07:14:32 UTC
Permalink
This is the error ... Select a valid choice. That choice is not one of
the available choices.

I want to delete a bunch of "child" records when a "parent" record is
deleted. While I'm using that terminology they are not actually related
in the usual sense. All however are in foreign key relationships with
the same owner/master.

The child records all know which parents they have because the parent
added its mark to a field in the child when the child record got created
and linked to the master. In fact if that child had been added by
another parent, the next parent just adds its mark instead of adding
another child.

When a parent gets deleted from the master, its mark is removed from all
the child records it was involved with and if it was the only mark the
child gets deleted too. Or at least that is what I want to happen.

My question is:

In overview, how should I be doing this?

At the moment I'm trying to do it all via model methods calling various
managers because it feels like the right place to do it.

I have tried to make a custom manager with use_for_related_fields = True
but still get the same error.

Thanks for any help

Mike
--
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
m1chael
2013-02-04 09:07:02 UTC
Permalink
I'll admit that i'm a bit old-school and most people are going to
cringe at seeing this,

I would set a DB trigger with the raw logic
This is the error ... Select a valid choice. That choice is not one of the
available choices.
I want to delete a bunch of "child" records when a "parent" record is
deleted. While I'm using that terminology they are not actually related in
the usual sense. All however are in foreign key relationships with the same
owner/master.
The child records all know which parents they have because the parent added
its mark to a field in the child when the child record got created and
linked to the master. In fact if that child had been added by another
parent, the next parent just adds its mark instead of adding another child.
When a parent gets deleted from the master, its mark is removed from all the
child records it was involved with and if it was the only mark the child
gets deleted too. Or at least that is what I want to happen.
In overview, how should I be doing this?
At the moment I'm trying to do it all via model methods calling various
managers because it feels like the right place to do it.
I have tried to make a custom manager with use_for_related_fields = True but
still get the same error.
Thanks for any help
Mike
--
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
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
--
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Mike Dewhirst
2013-02-04 21:46:02 UTC
Permalink
Post by m1chael
I'll admit that i'm a bit old-school and most people are going to
cringe at seeing this,
I would set a DB trigger with the raw logic
I hadn't thought of that but I think it would be my last resort. I'd
like to keep all the logic in one place. The answer has to be in a
models.Manager somewhere. I guess I need to dig deeper.

Thanks

Mike
Post by m1chael
This is the error ... Select a valid choice. That choice is not one of the
available choices.
I want to delete a bunch of "child" records when a "parent" record is
deleted. While I'm using that terminology they are not actually related in
the usual sense. All however are in foreign key relationships with the same
owner/master.
The child records all know which parents they have because the parent added
its mark to a field in the child when the child record got created and
linked to the master. In fact if that child had been added by another
parent, the next parent just adds its mark instead of adding another child.
When a parent gets deleted from the master, its mark is removed from all the
child records it was involved with and if it was the only mark the child
gets deleted too. Or at least that is what I want to happen.
In overview, how should I be doing this?
At the moment I'm trying to do it all via model methods calling various
managers because it feels like the right place to do it.
I have tried to make a custom manager with use_for_related_fields = True but
still get the same error.
Thanks for any help
Mike
--
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
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
--
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Mike Dewhirst
2013-02-05 06:45:49 UTC
Permalink
Could someone please point out my mistake?

def clean_out(self):
child_lst = list(Child.objects.filter(master=self.master,
tags=self.mark))
for child in child_lst:
child.delete()

child_lst = list(Child.objects.filter(master=self.master,
tags__contains=self.mark))
for child in child_lst:
marks = child.tags.split()
marks = marks.remove(self.mark)
child.tags = ' '.join(marks)
child.save()


The "self" in this case is an instance of the Parent class and
clean_out() is a Parent model method. Both Parent and Child have a
foreign key relationship with the Master model. Nothing has a foreign
key pointing to either Parent or Child.

Parent.clean_out() method is connected to the pre_delete signal of the
Parent model.

The purpose of the method is more or less documented below.

I've tried this a number of different ways and always get the "Select a
valid choice ..." error mentioned below.
Post by Mike Dewhirst
This is the error ... Select a valid choice. That choice is not one of
the available choices.
I want to delete a bunch of "child" records when a "parent" record is
deleted. While I'm using that terminology they are not actually related
in the usual sense. All however are in foreign key relationships with
the same owner/master.
The child records all know which parents they have because the parent
added its mark to a field in the child when the child record got created
and linked to the master. In fact if that child had been added by
another parent, the next parent just adds its mark instead of adding
another child.
When a parent gets deleted from the master, its mark is removed from all
the child records it was involved with and if it was the only mark the
child gets deleted too. Or at least that is what I want to happen.
In overview, how should I be doing this?
At the moment I'm trying to do it all via model methods calling various
managers because it feels like the right place to do it.
I have tried to make a custom manager with use_for_related_fields = True
but still get the same error.
Thanks for any help
Mike
--
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Pankaj Singh
2013-02-05 17:57:12 UTC
Permalink
Hey Mike,

I tried to replicate what you were trying to do and I got it working.

By the way, you can directly delete filtered child objects, no need to
create a list. And you don't need to create a list for iterating over a
queryset.

Queryset supports iteration by default(
https://docs.djangoproject.com/en/dev/topics/db/queries/#querysets-are-lazy
).

Here is models.py:

from django.db import modelsfrom django.db.models.signals import
pre_deletefrom django.dispatch import receiver

class Master(models.Model):
name = models.CharField(max_length=200)

def __unicode__(self):
return self.name

class Parent(models.Model):
name = models.CharField(max_length=200)
master = models.ForeignKey(Master)
mark = models.CharField(max_length=40)

def __unicode__(self):
return self.name

def clean_out(self):
Child.objects.filter(master=self.master, tags=self.mark).delete()

child_lst = Child.objects.filter(master=self.master,
tags__contains=self.mark)
for child in child_lst:
marks = child.tags.split()
marks.remove(self.mark)
child.tags = ' '.join(marks)
child.save()

class Child(models.Model):
name = models.CharField(max_length=200)
tags = models.TextField()
master = models.ForeignKey(Master)

def __unicode__(self):
return self.name

@receiver(pre_delete, sender=Parent)def parent_delete_handeler(sender,
instance, *args, **kwargs):
instance.clean_out()


Sincerely,
Pankaj Singh
http://about.me/psjinx
Post by Mike Dewhirst
Could someone please point out my mistake?
child_lst = list(Child.objects.filter(**master=self.master,
tags=self.mark))
child.delete()
child_lst = list(Child.objects.filter(**master=self.master,
tags__contains=self.mark))
marks = child.tags.split()
marks = marks.remove(self.mark)
child.tags = ' '.join(marks)
child.save()
The "self" in this case is an instance of the Parent class and clean_out()
is a Parent model method. Both Parent and Child have a foreign key
relationship with the Master model. Nothing has a foreign key pointing to
either Parent or Child.
Parent.clean_out() method is connected to the pre_delete signal of the
Parent model.
The purpose of the method is more or less documented below.
I've tried this a number of different ways and always get the "Select a
valid choice ..." error mentioned below.
Post by Mike Dewhirst
This is the error ... Select a valid choice. That choice is not one of
the available choices.
I want to delete a bunch of "child" records when a "parent" record is
deleted. While I'm using that terminology they are not actually related
in the usual sense. All however are in foreign key relationships with
the same owner/master.
The child records all know which parents they have because the parent
added its mark to a field in the child when the child record got created
and linked to the master. In fact if that child had been added by
another parent, the next parent just adds its mark instead of adding
another child.
When a parent gets deleted from the master, its mark is removed from all
the child records it was involved with and if it was the only mark the
child gets deleted too. Or at least that is what I want to happen.
In overview, how should I be doing this?
At the moment I'm trying to do it all via model methods calling various
managers because it feels like the right place to do it.
I have tried to make a custom manager with use_for_related_fields = True
but still get the same error.
Thanks for any help
Mike
--
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
.
Visit this group at http://groups.google.com/**group/django-users?hl=en<http://groups.google.com/group/django-users?hl=en>
.
For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/opt_out>
.
--
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Mike Dewhirst
2013-02-06 03:14:13 UTC
Permalink
Pankaj, thank you

I have tried the code in a number of ways - including the way you wrote
it[1] - and located in either Master[2] or Parent and it always runs to
completion without raising its own exception. It happily prints out
progress flags in the dev server and then finally delivers the 500
ValidationError mentioned below.

My conclusion is the Admin doesn't like me.

My code (equivalent with yours) seems to be working but the entire
transaction seems to be getting rolled back when it is nearly finished.
I think it must be something to do with the data so I'm simplifying as
hard as I can and ...

I'm currently studying the traceback - which is *all* Django code and
none of mine.

More later

Thanks again.

Mike

[1] Your version was what I tried first because that is what the docs
illustrate. I eventually used the list to make sure the query_set
actually ran and I was deleting actual objects. I have now gone back to
the way you wrote it because I'm convinced the problem is elsewhere.

[2] It now lives in the Master and is called with the 'mark' from the
Parent on the pre-delete signal. I do this despite using pre-delete
because of the warning in docs about deleted objects trying to do
things. I know the Master won't be deleted.
Post by Pankaj Singh
Hey Mike,
I tried to replicate what you were trying to do and I got it working.
By the way, you can directly delete filtered child objects, no need to
create a list. And you don't need to create a list for iterating over a
queryset.
Queryset supports iteration by
default(https://docs.djangoproject.com/en/dev/topics/db/queries/#querysets-are-lazy).
|from django.dbimport models
from django.db.models.signalsimport pre_delete
from django.dispatchimport receiver
name= models.CharField(max_length=200)
return self.name
name= models.CharField(max_length=200)
master= models.ForeignKey(Master)
mark= models.CharField(max_length=40)
return self.name
Child.objects.filter(master=self.master, tags=self.mark).delete()
child_lst= Child.objects.filter(master=self.master,
tags__contains=self.mark)
marks= child.tags.split()
marks.remove(self.mark)
child.tags= ''.join(marks)
child.save()
name= models.CharField(max_length=200)
tags= models.TextField()
master= models.ForeignKey(Master)
return self.name
@receiver(pre_delete, sender=Parent)
instance.clean_out()|
Sincerely,
Pankaj Singh
http://about.me/psjinx
Could someone please point out my mistake?
child_lst = list(Child.objects.filter(__master=self.master,
tags=self.mark))
child.delete()
child_lst = list(Child.objects.filter(__master=self.master,
tags__contains=self.mark))
marks = child.tags.split()
marks = marks.remove(self.mark)
child.tags = ' '.join(marks)
child.save()
The "self" in this case is an instance of the Parent class and
clean_out() is a Parent model method. Both Parent and Child have a
foreign key relationship with the Master model. Nothing has a
foreign key pointing to either Parent or Child.
Parent.clean_out() method is connected to the pre_delete signal of
the Parent model.
The purpose of the method is more or less documented below.
I've tried this a number of different ways and always get the
"Select a valid choice ..." error mentioned below.
This is the error ... Select a valid choice. That choice is not one of
the available choices.
I want to delete a bunch of "child" records when a "parent" record is
deleted. While I'm using that terminology they are not actually related
in the usual sense. All however are in foreign key relationships with
the same owner/master.
The child records all know which parents they have because the parent
added its mark to a field in the child when the child record got created
and linked to the master. In fact if that child had been added by
another parent, the next parent just adds its mark instead of adding
another child.
When a parent gets deleted from the master, its mark is removed from all
the child records it was involved with and if it was the only mark the
child gets deleted too. Or at least that is what I want to happen.
In overview, how should I be doing this?
At the moment I'm trying to do it all via model methods calling various
managers because it feels like the right place to do it.
I have tried to make a custom manager with
use_for_related_fields = True
but still get the same error.
Thanks for any help
Mike
--
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,
Visit this group at
http://groups.google.com/__group/django-users?hl=en
<http://groups.google.com/group/django-users?hl=en>.
For more options, visit https://groups.google.com/__groups/opt_out
<https://groups.google.com/groups/opt_out>.
--
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
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
--
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Mike Dewhirst
2013-02-06 07:44:14 UTC
Permalink
Solved

I was culling children based on redundancy but a missing child was being
automatically inserted again. The error was being correctly reported as
a DoesNotExist problem but until I noticed the incremented pk in the
database I was looking in the wrong places.

Thanks again for your effort - I'm sorry to waste your time.

Mike
Post by Mike Dewhirst
Pankaj, thank you
it[1] - and located in either Master[2] or Parent and it always runs to
completion without raising its own exception. It happily prints out
progress flags in the dev server and then finally delivers the 500
ValidationError mentioned below.
My conclusion is the Admin doesn't like me.
My code (equivalent with yours) seems to be working but the entire
transaction seems to be getting rolled back when it is nearly finished.
I think it must be something to do with the data so I'm simplifying as
hard as I can and ...
I'm currently studying the traceback - which is *all* Django code and
none of mine.
More later
Thanks again.
Mike
[1] Your version was what I tried first because that is what the docs
illustrate. I eventually used the list to make sure the query_set
actually ran and I was deleting actual objects. I have now gone back to
the way you wrote it because I'm convinced the problem is elsewhere.
[2] It now lives in the Master and is called with the 'mark' from the
Parent on the pre-delete signal. I do this despite using pre-delete
because of the warning in docs about deleted objects trying to do
things. I know the Master won't be deleted.
Post by Pankaj Singh
Hey Mike,
I tried to replicate what you were trying to do and I got it working.
By the way, you can directly delete filtered child objects, no need to
create a list. And you don't need to create a list for iterating over a
queryset.
Queryset supports iteration by
default(https://docs.djangoproject.com/en/dev/topics/db/queries/#querysets-are-lazy).
|from django.dbimport models
from django.db.models.signalsimport pre_delete
from django.dispatchimport receiver
name= models.CharField(max_length=200)
return self.name
name= models.CharField(max_length=200)
master= models.ForeignKey(Master)
mark= models.CharField(max_length=40)
return self.name
Child.objects.filter(master=self.master,
tags=self.mark).delete()
child_lst= Child.objects.filter(master=self.master,
tags__contains=self.mark)
marks= child.tags.split()
marks.remove(self.mark)
child.tags= ''.join(marks)
child.save()
name= models.CharField(max_length=200)
tags= models.TextField()
master= models.ForeignKey(Master)
return self.name
@receiver(pre_delete, sender=Parent)
instance.clean_out()|
Sincerely,
Pankaj Singh
http://about.me/psjinx
Could someone please point out my mistake?
child_lst = list(Child.objects.filter(__master=self.master,
tags=self.mark))
child.delete()
child_lst = list(Child.objects.filter(__master=self.master,
tags__contains=self.mark))
marks = child.tags.split()
marks = marks.remove(self.mark)
child.tags = ' '.join(marks)
child.save()
The "self" in this case is an instance of the Parent class and
clean_out() is a Parent model method. Both Parent and Child have a
foreign key relationship with the Master model. Nothing has a
foreign key pointing to either Parent or Child.
Parent.clean_out() method is connected to the pre_delete signal of
the Parent model.
The purpose of the method is more or less documented below.
I've tried this a number of different ways and always get the
"Select a valid choice ..." error mentioned below.
This is the error ... Select a valid choice. That choice is not one of
the available choices.
I want to delete a bunch of "child" records when a "parent" record is
deleted. While I'm using that terminology they are not actually related
in the usual sense. All however are in foreign key relationships with
the same owner/master.
The child records all know which parents they have because the parent
added its mark to a field in the child when the child record got created
and linked to the master. In fact if that child had been added by
another parent, the next parent just adds its mark instead of adding
another child.
When a parent gets deleted from the master, its mark is removed from all
the child records it was involved with and if it was the only mark the
child gets deleted too. Or at least that is what I want to happen.
In overview, how should I be doing this?
At the moment I'm trying to do it all via model methods calling various
managers because it feels like the right place to do it.
I have tried to make a custom manager with
use_for_related_fields = True
but still get the same error.
Thanks for any help
Mike
--
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,
Visit this group at
http://groups.google.com/__group/django-users?hl=en
<http://groups.google.com/group/django-users?hl=en>.
For more options, visit https://groups.google.com/__groups/opt_out
<https://groups.google.com/groups/opt_out>.
--
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
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
--
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+***@googlegroups.com.
To post to this group, send email to django-***@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
Loading...