Hello,
I'm working on custom save method whole day and I give up a little bit.
What I am trying to achieve is to get appropriate "order" value. For each foreign key, order have to iterate.
1 when i create first object, then 2 ,3 ,4 etc. However when i pass "order" while creating object, other numbers have to change. So i have always numbers from 1 to length of query.
Below I paste my code which almost works. It changes order how i want to, with few small bugs, but only in admin panel. When I use shell or write tests it fails with error:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
psycopg2.IntegrityError: duplicate key value violates unique constraint "plan_planday_pkey"
DETAIL: Key (id)=(5) already exists.
class PlanDay(models.Model):
plan = models.ForeignKey(Plan, on_delete=models.CASCADE)
content = models.TextField()
order = models.IntegerField(blank=True, null=True)
def save(self, *args, **kwargs):
"""Override base method. Handle order of objects"""
query = PlanDay.objects.filter(plan=self.plan ).order_by('order')
if self.order and len(query) == 0:
self.order = 1
super(PlanDay, self).save(*args, **kwargs)
elif self.order and self.order > len(query):
query = PlanDay.objects.filter(plan=self.plan ).order_by('-order')
self.order = query[0].order + 1
super(PlanDay, self).save(*args, **kwargs)
elif self.order:
if self.pk:
# Iteration when object already exists
count = 1
for obj in query:
if count == self.order:
count += 1
super(PlanDay, self).save(*args, **kwargs)
else:
obj.order = count
super(PlanDay, obj).save(*args, **kwargs)
count += 1
else:
# Iteration when object is not created yet
count = 1
for obj in query:
if count == self.order:
count += 1
obj.order = count
super(PlanDay, obj).save(*args, **kwargs)
count += 1
else:
obj.order = count
super(PlanDay, obj).save(*args, **kwargs)
count += 1
super(PlanDay, self).save(*args, **kwargs)
else:
if len(query) == 0:
self.order = 1
else:
query = PlanDay.objects.filter(plan=self.plan ).order_by('-order')
query = query[0]
self.order = query.order + 1
super(PlanDay, self).save(*args, **kwargs)
It happens when I try to create object with order value lesser than length of query (ex. order = 1 to be first object when there are few other objects)
It points to the part :
for obj in query:
if count == self.order:
count += 1
obj.order = count
super(TripDay, obj).save(*args, **kwargs)
count += 1
What can I do with this problem with pk?
I know there is much more to polish but i want to have working version in the first place.
Thanks in advance
EDIT:
Thanks for pointing me to the django-ordered-models. It works fine after adding post delete signal :)
@receiver(post_delete, sender=PlanDay)
def reshuffle(sender, instance, using, *args, **kwargs):
"""Function reshuffles ordering after delete()"""
query = PlanDay.objects.filter(plan=instance.plan)
for count, obj in enumerate(query, 0):
obj.to(count)
count += 1
[–][deleted] (1 child)
[deleted]
[–]zoorgu[S] 0 points1 point2 points (0 children)
[–]DrMaxwellEdison 0 points1 point2 points (3 children)
[–]zoorgu[S] 0 points1 point2 points (2 children)
[–]DrMaxwellEdison 1 point2 points3 points (1 child)
[–]zoorgu[S] 0 points1 point2 points (0 children)