Search code examples
djangosignals

How to create field with information from another field


I have model and i have foreign key to another model and in that model i have company_name and i'm looking for way to create custom_id with some letters and then add company name into that id it should look like this:

123456GOOGLE

OR

123456AMAZON

I tried to use signals but thats not what i need so how can i solve that?

models.py

class CompanyUserPhysicalCard(models.Model):
    card = models.ForeignKey(Cards, on_delete=models.CASCADE, related_name='company_physical_user_cards')
    company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True, verbose_name='компания')
    custom_id = models.CharField(max_length=7, unique=True, default=company_card_code, editable=False, null=True,
                                 blank=True)

with that function i've got an error

 'ForeignKey' object has no attribute 'company_name'

def company_card_code(company):
    letters = '01234567890QLUBOK'
    result_str = ''.join(random.choice(letters) for i in range(9)) + str(company.company_name)

    return result_str

Solution

  • I would advise to calculate the name on-demand, like:

    from random import choices
    
    
    class CompanyUserPhysicalCard(models.Model):
        def company_card_code(self):
            letters = '01234567890QLUBOK'
            return ''.join(choices(letters, k=6))
    
        card = models.ForeignKey(
            Cards,
            on_delete=models.CASCADE,
            related_name='company_physical_user_cards',
        )
        company = models.ForeignKey(
            Company, on_delete=models.SET_NULL, null=True, verbose_name='компания'
        )
        _custom_id = models.CharField(
            max_length=6, default=company_card_code, editable=False, blank=True
        )
    
        @property
        def custom_id(self):
            return f'{self._custom_id}{self.company.company_name}'

    We thus generate the code prefix, and when we need it, we append the company name.

    If the company later changes its name, for example 'Facebook' to 'Meta', without having to alter the table, it will also change the custom_id.

    You can filter by concatenating with Concat [Django-doc], for example:

    from django.db.models.functions import Concat
    
    CompanyUserPhysicalCard.objects.alias(
        custom_id=Concat('_custom_id', 'company__company_name')
    ).filter(custom_id='123456GOOGLE')