0

I have model like this:

class Company(models.Model):
"""Company model"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
active = models.BooleanField(default=False, blank=True, null=True)
type = models.JSONField(max_length=200, blank=True, null=True)
name = models.CharField(max_length=200, blank=True, null=True)
alias = models.CharField(max_length=200, blank=True, null=True)
telecom = models.JSONField(max_length=200, blank=True, null=True)
address = models.CharField(max_length=200, blank=True, null=True)
part_of = models.ForeignKey("company.Company", on_delete=models.SET_NULL, null=True,
                            blank=True, related_name="parent")
created_at = models.DateTimeField(auto_now_add=True, blank=False, null=True)
updated_at = models.DateTimeField(auto_now_add=True, blank=False, null=True)
deleted_at = models.DateTimeField(default=None, blank=True, null=True)

class Meta:
    db_table = 'organizations'

def __str__(self):
    return self.name

And serializer:

class CompanySerializer(serializers.ModelSerializer):
class Meta:
    model = Company
    fields = '__all__'
    read_only_fields = ("id",)
    part_of = serializers.PrimaryKeyRelatedField(queryset=Company.objects.all())

def create(self, validated_data):

    part_of = validated_data.pop("part_of")

    if part_of:
        company_id = Company.objects.create(**part_of)
        validated_data['part_of'] = company_id

    company = Company.objects.create(**validated_data)
    return company

And view:

class CompanyViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin):
    serializer_class = serializers.CompanySerializer
    queryset = Company.objects.all()

    def get_queryset(self):
        return self.queryset.all()

    def perform_create(self, serializer):
        serializer.save()

It is working fine with empty value of "part_of":"", but doesn't work while I pass value for part_of. part_of is basically a parent company which I am trying to create. so my expectation is create a company(part_of) first, get it's id and make that id as foreign key for another company. Anyone implemented similar to this? Or what I am doing wrong here, suggestions, help is appreciated. Thanks in advance.

The error I am getting is:

{
"part_of": [
    "“{ 'name': 'Parent of Organization', 'telecom': [{'system': 'phone', 'value': '677-7777'}, {'system': 'email', 'value': 'customerservice@abc.com'}], 'address': [{'line': ['3300 Washtenaw Avenue, Suite 227'], 'city': 'Amherst', 'state': 'MA', 'postalCode': '01002', 'country': 'USA'}]}” is not a valid UUID."
]

}

bhattraideb
  • 407
  • 7
  • 25
  • Since `part_of` field has been declared as `PrimaryKeyRelatedField`, it's expecting a primary key and not the company object. In this case you'll need to use `CompanySerializer` for `part_of` as well – Brian Destura Jan 29 '22 at 08:43
  • @BrianDestura, Can I call same serializer inside it like this? `class CompanySerializer(serializers.ModelSerializer): class Meta: model = Company fields = '__all__' read_only_fields = ("id",) part_of = CompanySerializer(many=false, readonly=false)` – bhattraideb Jan 29 '22 at 09:04

2 Answers2

1

I solved this by creating a new serializer for parent company as mentioned in this post:

class ParentCompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = '__all__'


class CompanySerializer(serializers.ModelSerializer):
    """Serializers for Company objects"""
    class Meta:
        model = Company
        fields = '__all__'
        read_only_fields = ("id", )

    part_of = ParentCompanySerializer(many=False, read_only=False)

    def create(self, validated_data):
        part_of = validated_data.pop('part_of') if 'part_of' in validated_data else None
        if part_of:
            company_id = Company.objects.create(**part_of)
            validated_data['part_of'] = company_id
        
company = Company.objects.create(**validated_data)
       return company

Hope this will help someone who stuck in similar situation like me.

bhattraideb
  • 407
  • 7
  • 25
0

I think to make a model also a child os same model we have to do something like -

part_of = models.ForeignKey("self")

and create method should be something like -

def create(self, validated_data): 
    part_of = validated_data.pop("part_of") ## check if part_of exist in validated data then do this step.
    company_id = Company.objects.create(validated_data) ##pop removed part_of data from validated_data so pass validated data here

    if part_of:
        company = Company.objects.create(part_of = company_id, **part_of)
    return company

Well customize it according to your needs.

Ranu Vijay
  • 1,137
  • 9
  • 18
  • The idea is to create part_of data as a parent company and other as a child. I tried this but give me error: def create(self, validated_data): part_of = validated_data.pop("part_of") company_id = Company.objects.create(**part_of) if part_of: company = Company.objects.create(part_of=company_id, **validated_data) return company **Error: Cannot assign "''": "Company.part_of" must be a "Company" instance.** – bhattraideb Jan 30 '22 at 05:18
  • Ok so primaryRelatedKey by default is read-write [link](https://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield). and as you have included it in your serializers it is expecting a value of part_of (Company" instance) everytime a new company is created. make changes to be this as read only . You code seems good it showld work. – Ranu Vijay Jan 30 '22 at 09:56
  • I tried, but its not working. There is no error but not creating part_of(parent) one, other one is being created. – bhattraideb Jan 31 '22 at 12:38
  • CHECK THE id of parent in other one. since you are first creating the parent and then passing its id. so check whether other one has parent id or not. – Ranu Vijay Jan 31 '22 at 13:25
  • I believe parent is getting created and because you have **part_of = serializers.PrimaryKeyRelatedField(queryset=Company.objects.all())** you are not able to see. – Ranu Vijay Jan 31 '22 at 13:27
  • No its not created, I checked in the DB. – bhattraideb Feb 01 '22 at 13:14