Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django autoincrement based on foreignkey

Let's say I have a model Issue that looks like this:

class Issue(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    text = models.TextField()

And another one called Comment like so:

class Comment(models.Model):
    issue = models.ForeignKey(Issue)
    text = models.TextField()
    number = models.AutoField()

I want the comment number field to be relative to the issue.

Which means that every issue will have its separate comment#1, comment#2, comment#3...etc.

Can this be done in Django?

like image 277
Mahmoud Hanafy Avatar asked Apr 05 '14 00:04

Mahmoud Hanafy


2 Answers

If you removed the number field from your Comment model and replaced it with a date_added field, you could still query the DB to pull all comments associated with a certain entry in order.

class Comment(models.Model):
    issue = models.ForeignKey(Issue)
    text = models.TextField()
    date_added = models.DateField(auto_now_add = True)

Then if you wanted to get all of the comments associated with a certain issue:

i = Issue.object.get(pk=1)    #pk = primary key id for whatever issue you want

comments_by_issue = i.comment_set.all().order_by('date_added')

Now you have some comments that you can refer to by index location (comments_by_issue[0] would get you the first comment attached to the issue, for instance).

That index location is the closest way I can figure to get what you're looking for. Someone else mentioned comment.id, but this is just going to be an autoincrementing integer that goes up for every comment. The fifth comment added to your system might have comment.id = 5, but it might be the first comment attached to issue 2 - if I'm reading your query right, having the comment ID doesn't help in that context.

This is more of a workaround than a direct answer, but I hope it helps.

like image 100
souldeux Avatar answered Nov 09 '22 00:11

souldeux


I prefer soundeux's solution. That said, here is the idea...

class Comment(models.Model):
    # ...
    number = models.PositiveIntegerField(default=1)

    def save(self, *args, **kwargs):
        obj = super(Comment, self).save(*args, **kwargs)
        try:
            last_comment = self.issue.comment_set.all().orderby('-number')[0]
        except KeyError:  # I think it's KeyError... for when there is no comments
            pass
        else:
            Comment.objects.filter(id=self.id).update(number=last_comment.number+1)
        return obj

Be careful - this will not be executed when Comments are being updated using the ORM's update method. Indeed, that's what I've used to avoid recursion (which is not a very good solution either). You might wanna implement it as a pre_save event instead of the save() (still won't respond to the update(), but will be more robust about potential recursion problems).

like image 34
frnhr Avatar answered Nov 09 '22 01:11

frnhr