Hey there!
I’m looking for a better way of doing some ManyToMany
creation.
I have this set of models.
from django.db import models
from django.utils.translation import gettext_lazy as _
from app.base.models import AutoTimeStampModel, BaseModel
from users.models import User
class Activity(BaseModel):
code = models.CharField(
verbose_name=_("Activity code"),
max_length=25,
unique=True,
)
description = models.CharField(
verbose_name=_("Activity description"),
max_length=255,
)
class Company(AutoTimeStampModel):
federal_entity_id = models.CharField(
verbose_name=_("Federal Entity ID"),
help_text=_("The company federal entity id"),
max_length=14,
primary_key=True,
)
activities = models.ManyToManyField(
to=Activity,
through="CompanyActivity",
verbose_name=_("Activities"),
)
# A lot of fields, not relevant here
class CompanyActivity(BaseModel):
company = models.ForeignKey(
verbose_name=_("Company"),
to=Company,
on_delete=models.CASCADE,
)
activity = models.ForeignKey(
to=Activity,
on_delete=models.CASCADE,
verbose_name=_("Activity"),
)
primary = models.BooleanField(
verbose_name=_("Primary Activity?"),
default=False,
)
Each Company
will have many Activity
that may be primary
or not.
The “problem” i’m facing, it’s that i don’t know if there’s already a Activity
, so i use get_or_create
to create the Activity
i set it to the activities
many to many relation of the Company
that will create primary
with a default=False
and after that i’m doing a update on the activities
to update the primary
field to True
if there is any primary
activities.
Here’s the referenced code.
# services.py
from companies import models
from companies.scrapers.factory import create_scraping_provider
def create_new_company_from_scraping_request(federal_entity_id: str) -> models.Company:
scraper = create_scraping_provider()
scraped_company = scraper.get_federal_entity_by_id(federal_entity_id)
company: models.Company = models.Company.objects.create(**scraped_company.create_kwargs)
models.Address.objects.create(company=company, **scraped_company.address_kwargs)
activities = [
models.Activity.objects.get_or_create(
code=scraped_activity.code, defaults={"description": scraped_activity.description}
)[0]
for scraped_activity in scraped_company.activities
]
company.activities.add(*activities)
primary_activities = [actv.code for actv in scraped_company.activities if actv.primary]
if primary_activities:
company.activities.filter(activity__code__in=primary_activities).update(primary=True)
I’m looking for a better way of doing this creation, it seems repetitive and not idiomatic. I referenced to the Docs, but did not found any related case.
Thanks in advance.