How to add prefix to a unique id from another model?

I created two models “Category” and “Item”. There is a field “title” in category model, I want the value of the “title field” to be prefix of my “unique id field” in Item module can anyone suggest me a solution for this problem.

Thank you

1 Like

You could create a property on the Item model:

class Item(models.Model):
    title = models.CharField()

    @property
    def some_other_field(self):
        # Combines title and the auto generated id
        return f"{self.title}_{self.id}"

Check out the docs about it here

can i use the value of title as prefix in Item model
class Category(models.Model): title = models.CharField()” in another model class Item(models.Model):product_id=title(from category)+uniqueid.,
To be more precise i want a unique id as such
for example "the vale of title in category module is= BOOK " and the unique id at Item module is 00000123.I want BOOK as prefix of my unique id and the id should increment as i add a item of same category, and should change if it is different category.
I hope I elaborately explained my problem can you please help me with it.

Thank you

What you’re looking for is possible. Take a look at the example of foreign keys. It’ll show you how to traverse model relationships. You can combine that with the property method above to accomplish it.

The requirement of having a counter for each individual category is a bit more difficult. You’ll want to make use of UniqueConstraint.

class Item(models.Model):
    category = models.ForeignKey(Category)
    index = models.IntegerField()

    class Meta:
        constraints = [UniqueConstraint(fields=['category', 'index'], name='unique_category_id'))
1 Like

Thank you for your response I will try this and let you know if it works

As per the above solution you suggested me I am able to generate an unique id but can’t get prefix as per requirement. So can you please elaborate the above solution
Thank you

Looks like I missed returning the title from the category field.

class Item(models.Model):
    @property
    def some_other_field(self):
        # Combines the category's title and the auto generated id
        return f"{self.category.title}_{self.id}"
1 Like

Sorry for the late response, I will try it and let you know if it works
Thank you.

Hi Sir, Regarding the same issue
This is my Category model
class Category(models.Model):

cat_title = models.CharField(max_length=100, unique=True)

This is my Item model

class Item(models.Model):

product_id = models.CharField(primary_key=True, editable=False, max_length=100)
prefix = models.OneToOneField(Category, to_field='cat_title', related_name='prefix', on_delete=models.CASCADE)

    def save(self, **kwargs):
        if not self.product_id:
            max = Item.objects.aggregate(id_max=Max('product_id'))['id_max']
            self.product_id = "{}{:10}".format(self.prefix, max if max is not None else 1)
        super().save(*kwargs)``

here i am using a foreign key as prefix to my unique id, My issue here is that i can not add multiple items to my Item Module
as the prefix is showing unique, If I remove unique=True from Category module the code is not running so i think incrementing prefix with certain value in Item Module might resolve my issue, Can you please help me with this issue

As a side note - When you post code, to prevent the formatting being lost, enclose the code between two lines consisting only of three backtick ` characters. So you would have a line of ```, then your lines of code, then another line ```. (Make sure you use the backtick - ` and not the apostrophe ’ ) The single-backtick method only works on one line.

Ok Sure, I will follow your instructions while posting code.
Thank you

You’re getting closer - but it’s just one set of three backticks before and after all the lines. Example:

# The line before this one is ```
def function(self):
    return self
# The line after this one is ```

See how that’s formatted?

Now, to address the issue you’ve identified here. You’ve got:

        max = Item.objects.aggregate(id_max=Max('product_id'))['id_max']

the field product_id is a character field, it’s going to hold the max value of that field. (Note: you probably don’t want to use a field named “max” - it’s the name of a built-in python function.)

Then you have:

        self.product_id = "{}{:10}".format(self.prefix, max if max is not None else 1)

This is going to set self.product_id to the same value that you just found in the previous statement, which is why you’re getting the error you’re seeing.

If you need to track the highest number for each Category, what you probably want to do is add an autoincrement field to your Category rather than querying the entire table for the highest number used - that’s going to become increasingly inefficient as the number of rows in your table increases - and subject to race conditions.