I have this model structure:
models.py
class Region(models.Model):
code = models.CharField(max_length=10, unique=True, verbose_name=_('code'))
name = models.CharField(max_length=255, verbose_name=_('name'))
class Province(models.Model):
code = models.CharField(max_length=10, unique=True, verbose_name=_('Code'))
name = models.CharField(max_length=255, verbose_name=_('Name'))
parent_region = models.ForeignKey('Region', on_delete=models.CASCADE, related_name='province', verbose_name=_('Regione'))
class City(models.Model):
code = models.CharField(max_length=10, unique=True, verbose_name=_('Code'))
name = models.CharField(max_length=255, verbose_name=_('Name'))
parent_province = models.ForeignKey('Province', on_delete=models.CASCADE, related_name='city', verbose_name=_('Province'))
class CustomArea(models.Model):
cities = models.ManyToManyField("City", verbose_name=_("Cities"), blank=True, related_name="in_area")
provinces = models.ManyToManyField("Province", verbose_name=_("Provinces"), blank=True, related_name="in_area")
regions = models.ManyToManyField("Region", verbose_name=_("Regions"), blank=True, related_name="in_area")
I want to write a method for CustomArea
model that returns a queryset with all the single City
element in it.
this is what I came up with:
def list_cities(self):
pks_provinces= self.provinces.all().values_list('id', flat=True)
pks_regions= self.regions.all().values_list('id', flat=True)
comuni = City.objects.filter(provincia__pk__in=pks_provinces).values_list('id', flat=True) | City.objects.filter(provincia__regione__pk__in=pks_regions).values_list('id', flat=True) | self.cities.all().values_list('id', flat=True)
return comuni.distinct()
Is this efficent enough? How can I improve this query to have all the single City
element?
You can try something like this:
from django.apps import apps
from django.conf import settings
from django.db.models import OneToOneField, ForeignKey, ManyToManyField
from <path to your models>.models import Region, Province, City, CustomArea
class RelatedModelManager:
def __init__(self, base_model):
self.base_model = base_model
self.all_models = apps.get_models()
self.result = {}
self.checked = []
def get_related(self, check_model=None):
check_model = check_model or self.base_model
ref = []
for m in self.all_models:
for f in m._meta.fields:
if isinstance(
f, (OneToOneField, ForeignKey, ManyToManyField)
) and (f.related_model == check_model) and m not in self.checked:
self.checked.append(m)
ref.append(m)
self.result[check_model] = ref
if ref:
for m in ref:
self.get_related(m)
obj = RelatedModelManager(Region)
obj.get_related()
obj.result
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.