Tuesday, January 6, 2015

prob. with non-related objects deleted

from django.db import models, IntegrityError, transaction
import time

# Create your models here.

DB_Transaction_Tries = 5
DB_Transaction_Sleep = 0.8 # seconds

class EntryCollection(models.Model):
name = models.CharField(max_length=10)

def save(self, *args, **kwargs):
super(EntryCollection, self).save(*args, **kwargs)
if BasicEntry.objects.filter(entry_col=self).count() == 0:
entry = BasicEntry(entry_col=self, next_entry=None, prev_entry=None)
entry.save()
entry.next_entry = entry
entry.prev_entry = entry
entry.save()


class BasicEntry(models.Model):
name = models.CharField(max_length=10)
entry_col = models.ForeignKey(EntryCollection)
next_entry = models.ForeignKey('BasicEntry', related_name='next', null=True, default=None)
prev_entry = models.ForeignKey('BasicEntry', related_name='prev', null=True, default=None)

def addEntry(self, name):
try_nr = 1
new_entry = None
while True:
try:
with transaction.atomic():
new_entry = BasicEntry(name=name,
entry_col=self.entry_col,
next_entry=self.next_entry,
prev_entry=self)
new_entry.save()
self.next_entry.prev_entry = new_entry
self.next_entry.save()
self.next_entry = new_entry
if self.prev_entry == self:
self.prev_entry = new_entry
self.save()
except IntegrityError as e:
print('addEntry: try %d' %(try_nr))
try_nr += 1
if try_nr >= DB_Transaction_Tries:
raise(e)
time.sleep(DB_Transaction_sleep)
else:
break
return(new_entry)

def removeEntry(self):
if self.name == '':
print('** The "virtual" first track can not be removed!')
return
try_nr = 1
while True:
try:
with transaction.atomic():
self.prev_entry.next_entry = self.next_entry
self.prev_entry.save()
self.next_entry.prev_entry = self.prev_entry
self.next_entry.save()
self.next_entry = None
self.prev_entry = None
self.save()
self.delete()
except IntegrityError as e:
print('removeEntry: try %d' %(try_nr))
try_nr += 1
if try_nr >= DB_Transaction_Tries:
raise(e)
time.sleep(DB_Transaction_sleep)
else:
break
hello all,

my problem is the following (the models.py is attached):
i want to implement a double-linked list (type BasicEntry) with the first entry having an empty name. each entry has two attributes prev_entry and next_entry to its neigbours. the first entry is created automaticaly and should never be removed. upon removing the second to last entry (using the function removeEntry), the last entry is also removed, although i do not know why. i tracked it down to the "collect" function in "deletion.py" on line 190:

for related in model._meta.get_all_related_objects(
include_hidden=True, include_proxy_eq=True):

do i misunderstand django or is this a known problem or "feature"? although i think i removed all references from the to be removed entry to the other entries...


class BasicEntry(models.Model):
name = models.CharField(max_length=10)
entry_col = models.ForeignKey(EntryCollection)
next_entry = models.ForeignKey('BasicEntry', related_name='next', null=True, default=None)
prev_entry = models.ForeignKey('BasicEntry', related_name='prev', null=True, default=None)

def addEntry(self, name):
try_nr = 1
new_entry = None
while True:
try:
with transaction.atomic():
new_entry = BasicEntry(name=name,
entry_col=self.entry_col,
next_entry=self.next_entry,
prev_entry=self)
new_entry.save()
self.next_entry.prev_entry = new_entry
self.next_entry.save()
self.next_entry = new_entry
if self.prev_entry == self:
self.prev_entry = new_entry
self.save()
except IntegrityError as e:
print('addEntry: try %d' %(try_nr))
try_nr += 1
if try_nr >= DB_Transaction_Tries:
raise(e)
time.sleep(DB_Transaction_sleep)
else:
break
return(new_entry)

def removeEntry(self):
if self.name == '':
print('** The "virtual" first track can not be removed!')
return
try_nr = 1
while True:
try:
with transaction.atomic():
self.prev_entry.next_entry = self.next_entry
self.prev_entry.save()
self.next_entry.prev_entry = self.prev_entry
self.next_entry.save()
self.next_entry = None
self.prev_entry = None
self.save()
self.delete()
except IntegrityError as e:
print('removeEntry: try %d' %(try_nr))
try_nr += 1
if try_nr >= DB_Transaction_Tries:
raise(e)
time.sleep(DB_Transaction_sleep)
else:
break



a few details:
linux (debian amd64)
python3 (v3.4.2-2)
django (v1.7.1-1)

here's an example in postgres:

django=> select * from entry_test_basicentry order by id;
id | name | entry_col_id | next_entry_id | prev_entry_id
----+-------+--------------+---------------+---------------
33 | | 14 | 34 | 35
34 | test1 | 14 | 35 | 33
35 | test2 | 14 | 33 | 34
(3 rows)


after removing ID 34:

django=> select * from entry_test_basicentry order by id;
id | name | entry_col_id | next_entry_id | prev_entry_id
----+-------+--------------+---------------+---------------
33 | | 14 | 35 | 35
35 | test2 | 14 | 33 | 33
(2 rows)


after removing ID 35:

django=> select * from entry_test_basicentry order by id;
id | name | entry_col_id | next_entry_id | prev_entry_id
----+------+--------------+---------------+---------------
(0 rows)


thanks in advance and best regards


tom

--
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+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/trinity-29b3450f-f209-4d1d-8406-9f7ff205766a-1420541277592%403capp-gmx-bs67.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment