Esempio n. 1
0
class Parada(models.Model):
    import_timestamp = models.DateTimeField(blank=True, null=True)
    osm_id = models.BigIntegerField(blank=True, null=True, db_index=True)
    tags = HStoreField(null=True)
    codigo = models.CharField(max_length=15, blank=True, null=True)
    nombre = models.CharField(max_length=200, blank=True, null=True)
    latlng = models.PointField()
    country_code = models.TextField(null=True)

    objects = GeoManager()

    def __str__(self):
        return self.nombre or self.codigo or "{}, {}".format(
            self.latlng.x, self.latlng.y)

    def get_absolute_url(self, argentina=None):
        return reverse(
            'ver_parada',
            kwargs={
                **({
                    'country_code': self.country_code
                } if self.country_code else {}), 'id':
                self.id
            },
        )
Esempio n. 2
0
class Terminal(models.Model):
    linea = models.ForeignKey(Linea, on_delete=models.CASCADE)
    descripcion = models.TextField(blank=True, null=True)
    direccion = models.CharField(max_length=150)
    telefono = models.CharField(max_length=150)
    latlng = models.PointField()
    objects = GeoManager()
Esempio n. 3
0
class Incidences(models.Model):
    name = models.CharField(max_length=50)
    location = models.PointField(srid=4326, max_length=500)
    objects = GeoManager()

    class Meta:
        verbose_name_plural = 'Incidences'
Esempio n. 4
0
class PostcodeMapping(models.Model):
    postcode = models.CharField(max_length=10, primary_key=True)

    # GeoDjango-specific declarations
    point = models.PointField()
    scraped = models.BooleanField(default=False, db_index=True)

    def __str__(self):
        return self.postcode

    @staticmethod
    def match_postcode(postcode, raise_exceptions=True):
        try:
            return PostcodeMapping.objects.get(
                postcode=postcode.upper().replace(' ', ''))
        except PostcodeMapping.DoesNotExist:
            try:
                PostcodeMapping.objects.get(postcode=postcode)
            except PostcodeMapping.DoesNotExist:
                if raise_exceptions:
                    raise
        return None

    @staticmethod
    def make_postcodemapping(postcode, lat, long):
        return PostcodeMapping(postcode=postcode, point=Point(long, lat))

    objects = GeoManager()

    def save(self, *args, **kwargs):
        self.postcode = self.postcode.upper().replace(' ', '')
        super(PostcodeMapping, self).save(*args, **kwargs)
Esempio n. 5
0
class AdministrativeArea(models.Model):
    """ Class that defines an area where a user has administrative power to mark infrastructure hazards as resolved """
    date = models.DateTimeField(
        'Date created',
        auto_now_add=True  # Date is set automatically when object created
    )
    # Spatial fields
    # Default CRS -> WGS84
    geom = models.MultiPolygonField()
    objects = GeoManager()  # Required to conduct geographic queries

    users = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                   verbose_name=_("users"),
                                   blank=True)
    description = models.CharField(max_length=200)

    def latlngList(self):
        return list(list(latlng)[::-1] for latlng in self.geom[0])

    # toString()
    def __unicode__(self):
        return str(self.description)

    class Meta:
        app_label = 'mapApp'
Esempio n. 6
0
class Webmap(models.Model):

    geom = models.PointField(srid=4326, blank=True, default=None)
    Nom = models.CharField(max_length=50)
    Département = models.CharField(max_length=300,
                                   null=False,
                                   default="",
                                   blank=True)
    Services = models.CharField(max_length=200,
                                null=False,
                                default="",
                                blank=True)
    Description_si_disop = models.CharField(max_length=200,
                                            null=False,
                                            default="",
                                            blank=True)
    Adress = models.CharField(max_length=200, default="", blank=True)
    Tel = models.CharField(max_length=200, default="", blank=True)
    Latitude = models.FloatField(max_length=8, default=30)
    Longitude = models.FloatField(max_length=8, default=-8)
    img = models.ImageField(null=True)
    link = models.URLField(null=True, blank=True)
    object = GeoManager()

    def save(self, *args, **kwargs):
        self.Latitude = self.geom.y
        self.Longitude = self.geom.x
        super(Webmap, self).save(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.link = self.img.url  #make a way to the media folder where images are being saved
        super(Webmap, self).save(*args, **kwargs)
Esempio n. 7
0
class Interseccion(models.Model):
    """ Una "Interseccion" es entre 2 calles de osm
    """
    nom_normal = models.TextField()
    nom = models.TextField()
    slug = models.SlugField(max_length=200, null=True)
    latlng = models.GeometryField(srid=4326, geography=True)
    osm_id1 = models.BigIntegerField(blank=True, null=True)
    osm_id2 = models.BigIntegerField(blank=True, null=True)
    country_code = models.TextField(null=True)
    objects = GeoManager()

    def save(self, *args, **kwargs):
        slug = slugify(self.nom)
        self.slug = slug
        suffix = 2
        while Interseccion.objects.filter(slug=self.slug).exists():
            self.slug = "%s-%d" % (slug, suffix)
            suffix = suffix + 1
        super(Interseccion, self).save(*args, **kwargs)

    def get_absolute_url(self, argentina=None):
        return reverse(
            'interseccion',
            kwargs={
                **({
                    'country_code': self.country_code
                } if self.country_code else {}),
                'slug':
                self.slug,
            },
        )
Esempio n. 8
0
class BusStop(gismodels.Model):
    name = models.TextField()
    geom = gismodels.PointField()
    objects = GeoManager()

    def __unicode__(self):
        return self.name
Esempio n. 9
0
class Sage_wcel(models.Model):
    id = models.AutoField(primary_key=True)
    uarfcn = models.SmallIntegerField(blank=True, null=True)
    name = models.TextField(blank=True, null=True)
    lat_site = models.FloatField(blank=True, null=True)
    lon_site = models.FloatField(blank=True, null=True)
    az = models.SmallIntegerField(blank=True, null=True)
    bw = models.SmallIntegerField(blank=True, null=True)
    rd = models.FloatField(blank=True, null=True)
    expr1 = models.TextField(blank=True, null=True)
    bsc_rnc_mme_name = models.TextField(blank=True, null=True)
    rncid = models.IntegerField(blank=True, null=True)
    wbtsid = models.IntegerField(blank=True, null=True)
    lcrid = models.IntegerField(blank=True, null=True)
    te = models.FloatField(blank=True, null=True)
    tm = models.FloatField(blank=True, null=True)
    alt = models.FloatField(blank=True, null=True)
    priscrcode = models.IntegerField(blank=True, null=True)
    lac = models.IntegerField(blank=True, null=True)
    rac = models.IntegerField(blank=True, null=True)
    rootseqindex = models.IntegerField(blank=True, null=True)
    admincellstate = models.TextField(blank=True, null=True)
    wcelstate = models.IntegerField(blank=True, null=True)
    sector = models.PolygonField(srid=4326, blank=True,
                                 null=True)  # This field type is a guess.
    objects = GeoManager()

    class Meta:
        managed = True
        db_table = 'sage_wcel'

    def __str__(self):
        return self.name
Esempio n. 10
0
class Events(models.Model):
    name = models.CharField(max_length=20)
    location = models.PointField(srid=4326)
    objects = GeoManager()

    def __str__(self):
        return self.name
Esempio n. 11
0
class Neighborhood(models.Model):
    """Auto-generated model for Zillow neighorhood shapefiles"""
    state = models.CharField(max_length=2)
    county = models.CharField(max_length=43)
    city = models.CharField(max_length=64)
    name = models.CharField(max_length=64)
    regionid = models.IntegerField()
    geom = models.MultiPolygonField(geography=True)

    objects = GeoManager()

    def __unicode__(self):
        return '{name}, {city}, {state}'.format(name=self.name,
                                                city=self.city,
                                                state=self.state)

    @property
    def feature(self):
        """
        Return a GeoJSON Feature object for this neighborhood.

        See: http://www.geojson.org/geojson-spec.html#feature-objects
        """
        return {
            'type': 'Feature',
            'geometry': {
                'type': self.geom.geom_type,
                'coordinates': self.geom.coords,
            },
            'properties': {
                'description': self.name,
            }
        }
Esempio n. 12
0
class information(models.Model):
    title = models.CharField(max_length=30)
    location = gis_models.PointField(srid = 4326)
    objects = GeoManager()
    
    def __str__(self):
        return self.title
Esempio n. 13
0
class Threat(CommonCoreModel):
    name = models.CharField(max_length=50)
    description = models.TextField(max_length=250, null=True, blank=True)
    date_reported = models.DateTimeField(null=True, blank=True)
    color = models.CharField(max_length=20, null=True, blank=True)
    # from (county)
    origin = models.CharField(max_length=250, null=True, blank=True)
    # to (county)
    destination = models.CharField(max_length=250, null=True, blank=True)
    # Threat type
    threat_type = models.CharField(max_length=100, null=True, blank=True)
    # Enable filtering by region from geoserver
    from_region = models.CharField(max_length=50, null=True, blank=True)
    to_region = models.CharField(max_length=50, null=True, blank=True)
    is_active = models.BooleanField(default=True, db_index=True)
    delete_reason = models.TextField(max_length=1000, null=True, blank=True)


    # Geo Field
    location = gis_models.LineStringField(srid=4326, null=True)

    objects = GeoManager()

    def delete(self):
        self.deactivate()
        super(Threat, self).delete()

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = " Threats"
Esempio n. 14
0
class Dam(models.Model):
    name = models.CharField(max_length=20)
    abbr = models.CharField(max_length=5)
    location = models.PointField(srid=4326)
    # deprecated
    objects = GeoManager()

    def __str__(self):
        return self.abbr

    def create_map(self):
        coords = self.location.coords
        coords = [coords[1], coords[0]]
        m = folium.Map(location=coords, zoom_start=11)
        folium.CircleMarker(location=coords,
                            radius=50,
                            popup=self.name,
                            color='#3186cc',
                            fill=True,
                            fill_color='#3186cc').add_to(m)
        m.save(f"reporter/static/maps/{self.abbr}.html")

    def save(self, *args, **kwargs):
        created = self.pk is None
        super(Dam, self).save(*args, **kwargs)
        if os.path.isfile(f"reporter/static/maps/{self.abbr}.html"):
            os.remove(f"reporter/static/maps/{self.abbr}.html")
            self.create_map()
        else:
            self.create_map()

    def map_path(self):
        return f"{self.abbr}.html"
Esempio n. 15
0
class Marker(models.Model):
    markerID = models.AutoField(primary_key=True)
    name = models.CharField("Place Name", max_length=40)
    # text=models.CharField("Text",max_length=100)
    mpoint = gismodels.PointField()
    objects = GeoManager()
    latitude = models.DecimalField(max_digits=10, decimal_places=6, blank=True)
    longitude = models.DecimalField(max_digits=10,
                                    decimal_places=6,
                                    blank=True)
    image = ProcessedImageField(
        upload_to="webmapping/place_img/%y/%m/%d/",
        null=True,
        # blank=True,
        processors=[ResizeToFill(200, 200)],
        format="JPEG",
        options={'quality': 100},
        verbose_name="Picture")
    thumbnail = ImageSpecField(source='image',
                               processors=[ResizeToFill(50, 50)],
                               format="JPEG",
                               options={'quality': 90})
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        verbose_name="user",
        blank=True,
        null=True,
    )

    def save(self, *args, **kwargs):
        self.latitude = self.mpoint.y
        self.longitude = self.mpoint.x
        super(Marker, self).save(*args, **kwargs)
Esempio n. 16
0
class shop(models.Model):
    spname = models.CharField(max_length=150, default=" ")
    spownm = models.CharField(max_length=100, default=" ")
    mob = models.BigIntegerField(blank=False, null=False, unique=True)
    city = models.CharField(max_length=255)
    location = models.PointField(srid=4326)
    objects = GeoManager()
Esempio n. 17
0
class Link(models.Model):
    """
    Metadata is stored in a PostgreSQL HStore field, which allows us     to store arbitrary key-value pairs with a link record.
    """
    metadata = HStoreField(blank=True, null=True, default=dict)
    geo = models.LineStringField()
    objects = GeoManager()
Esempio n. 18
0
class Provincia(models.Model):
    # Obligatorios
    nombre = models.CharField(max_length=100, blank=False, null=False)
    slug = models.SlugField(max_length=120, blank=True, null=False)

    # Opcionales
    variantes_nombre = models.CharField(max_length=150, blank=True, null=True)
    longitud_poligono = models.DecimalField(max_digits=7,
                                            decimal_places=2,
                                            blank=True,
                                            null=True)
    area_poligono = models.DecimalField(max_digits=7,
                                        decimal_places=2,
                                        blank=True,
                                        null=True)
    centro = models.PointField(blank=True, null=True)
    poligono = models.PolygonField(blank=True, null=True)

    objects = GeoManager()

    def save(self, *args, **kwargs):
        self.slug = slugify(self.nombre)
        if self.poligono:
            self.centro = self.poligono.centroid
        super(Provincia, self).save(*args, **kwargs)

    def __str__(self):
        return self.nombre
Esempio n. 19
0
class Etablissements(models.Model):
    cycle_choices= (
    ( "Primaire","Primaire"),
    ("College","College"),
    ("Lycee","Lycee"),
    ("Université","Université")
)
    type_choices=(
    ("Public","Public"),
    ("Privé","Privé")

    )

    Nom= models.CharField(max_length=50)
    geom= models.PointField(srid=4326, blank= True,default=None)
    Cycle= models.CharField(max_length=200, choices= cycle_choices,null=False,default="Not selected" )
    Type= models.CharField(max_length=200, choices= type_choices,null=False,default="Not selected")
    Adress= models.CharField(max_length=200,default="Taroudant")
    Effectif_total= models.IntegerField(null=True,default=0)
    Nombre_Enseignant= models.IntegerField(null=True,default=0)
    Superficie= models.IntegerField(null=True,default=0)
    Latitude = models.FloatField(max_length=8,default=30)
    Longitude = models.FloatField(max_length=8,default=-8)

    object= GeoManager()

    def save(self, *args, **kwargs):
         self.Latitude  = self.geom.y
         self.Longitude = self.geom.x
         super(Etablissements, self).save(*args, **kwargs)
Esempio n. 20
0
class Obstacles(gis_models.Model):
    class Meta:
        """Meta definition for Obstacles."""

        verbose_name = "Obstacle"
        verbose_name_plural = "Obstacles"

    OBSTACLE_TYPE = (
        ("PWL", "Power Lines"),
        ("TRS", "Trees"),
        ("BLD", "Building"),
        ("TWR", "Tower"),
    )

    obstacle_type = models.CharField(max_length=4, choices=OBSTACLE_TYPE, null=False)
    height = models.FloatField(help_text="estimated height in meters")
    objects = GeoManager()
    description = models.CharField(max_length=120, blank=True, null=True)
    geom = gis_models.GeometryField()
    status = gis_models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        if self.geom.geom_type == "Point":
            center = self.geom
            radius = (15 * 0.008) / 1000
            circle = center.buffer(radius)
            self.geom = circle
        super().save(*args, **kwargs)

    def __str__(self):
        return self.get_obstacle_type_display()

    @property
    def type(self):
        return str(self.get_obstacle_type_display())
Esempio n. 21
0
class Line(models.Model):

    calques_choices = [
        (0, 'UNKNOWN'),
        (1, 'FACILE'),
        (2, 'DIFFICILE'),
        (3, 'ASSEZ_DIFFICILE'),
        (4, 'TRES_DIFFICILE'),
        (5, 'EXTREMEMENT_DIFFICILE'),
    ]
    line_info = models.ForeignKey(LineInfo,
                                  on_delete=models.CASCADE,
                                  null=True)
    line_nb = models.IntegerField(default=0)
    cota = models.CharField(max_length=10, blank=True)
    calque = models.IntegerField(choices=calques_choices, default=0)
    geom = models.PointField(null=True)
    objects = GeoManager()
    name = models.CharField(max_length=100, blank=True)
    bloc = models.ForeignKey(Bloc, on_delete=models.CASCADE, null=True)

    @property
    def printInfo(self):
        html = self.name
        return print_info_gen(html)
Esempio n. 22
0
class Store(models.Model):
    name = models.CharField(max_length=50)
    tel = models.CharField(max_length=50, null=True)
    lat = models.FloatField(null=True)
    lng = models.FloatField(null=True)
    location = models.PointField(null=True, srid=4326)
    code = models.CharField(max_length=20)
    country = models.ForeignKey('Country',
                                on_delete=models.SET_NULL,
                                null=True)
    city = models.ForeignKey('City', on_delete=models.SET_NULL, null=True)
    district = models.ForeignKey('District',
                                 on_delete=models.SET_NULL,
                                 null=True)
    address1 = models.CharField(max_length=100)
    address2 = models.CharField(max_length=100)
    open_time = models.TimeField(null=True)
    close_time = models.TimeField(null=True)
    business_district = models.ForeignKey('BusinessDistrict',
                                          on_delete=models.SET_NULL,
                                          null=True)
    objects = GeoManager()

    class Meta:
        db_table = 'stores'
Esempio n. 23
0
class Incidence(models.Model):
    name = models.CharField(max_length=30)
    location = models.PointField(srid=4326)
    object = GeoManager()

    def __str__(self):
        return self.name
Esempio n. 24
0
class LocationPoints(gis_models.Model):
    name = gis_models.CharField(max_length=120)
    IATA_shortcode = gis_models.CharField(
        max_length=3,
        blank=True,
        null=True,
        help_text="NBO (for JKIA Nairobi)",
        unique=True,
    )
    ICAO_shortcode = gis_models.CharField(
        max_length=4,
        blank=True,
        null=True,
        help_text="HKJK for (JOMO Kenyatta)",
        unique=True,
    )

    radius = models.FloatField(default=5, help_text="km")
    geom = gis_models.PolygonField(blank=True, null=True)
    location = gis_models.PointField()

    objects = GeoManager()

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        center = self.location
        radius = self.radius * 0.008
        circle = center.buffer(radius)
        self.geom = circle
        super().save(*args, **kwargs)
Esempio n. 25
0
class LabelChallenge(models.Model):
    unique_id = models.UUIDField(default=uuid.uuid4,
                                 editable=False,
                                 unique=True)
    user = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    description = models.TextField()
    label_type = models.ManyToManyField(LabelType)
    start_time = models.DateTimeField(null=True, blank=True)
    end_time = models.DateTimeField(null=True, blank=True)
    geometry = models.TextField(default='')
    multipolygon = models.MultiPolygonField(null=True, blank=True)
    is_published = models.BooleanField(default=True)
    zoom = models.FloatField(default=5)
    created_at = models.DateTimeField(default=datetime.now, blank=True)
    updated_at = models.DateTimeField(default=datetime.now, blank=True)

    objects = GeoManager()

    def get_absolute_url(self):
        return reverse('label_challenge.challenge_detail',
                       kwargs={'unique_id': str(self.unique_id)})

    def get_short_description(self):
        description = self.description
        if len(description) > 50:
            return description[0:80] + '...'
        else:
            return description

    def get_label_type_obj(self):
        label_types = self.label_type.all()
        return label_types
Esempio n. 26
0
class Node(OSM_Primitive):
    geom = models.PointField(geography=True, spatial_index=True,
                             null=True)  # geography will force srid to be 4326
    objects = GeoManager()

    def set_cordinates(self, lat, lon):
        self.geom = Point(lat, lon)
        self.save()

    def to_xml(self, outputparams=None):
        attributes = [
            'id', 'geom', 'action', 'timestamp', 'uid', 'user', 'visible',
            'version', 'changeset'
        ]

        return super().base_to_xml(primitive='node', attributes=attributes)

    def single_node_to_xml(self, version_inc, outputparams=None, name=''):

        attributes = ['id', 'geom', 'visible', 'version']
        if outputparams is None:
            _outputparams = {'newline': '\n', 'indent': ' '}
        else:
            _outputparams = outputparams

        self.xml = '{newline}<node action="modify" '.format(**_outputparams)
        print("Version bool in node to xml {}".format(version_inc))
        for attr, value in self.__dict__.items():
            if not attr in attributes:
                continue
            '''elif attr == 'version':
                version_num = int(value)
                print("Version at first {}".format(version_num))
                if version_inc:
                    version_num = version_num + 1
                    print("Version at first {}".format(version_num))
                self.xml += "{}='{}' ".format(attr, version_num)'''
            if attr == 'timestamp':
                ts_main = str(value).split('+')
                ts_value = ts_main[0].replace(' ', 'T') + 'Z'
                self.xml += "{}='{}' ".format(attr, ts_value, **_outputparams)
            elif attr == 'geom':
                lon = str(value[0])
                self.xml += "{}='{}' ".format('lon', lon)
                lat = str(value[1])
                self.xml += "{}='{}' ".format('lat', lat)
            else:
                self.xml += "{}='{}' ".format(attr, str(value),
                                              **_outputparams)

        self.xml += '>'

        tags = self.tags.all()

        for tag in tags:
            self.xml += tag.node_tags_to_xml(outputparams=_outputparams,
                                             name=name)

        self.xml += '{newline}</node>'.format(**_outputparams)
        return self.xml
Esempio n. 27
0
class BlockProducer(models.Model):
    account_name = models.CharField(max_length=12, unique=True)
    producer_key = models.CharField(max_length=60)
    display_name = models.CharField(max_length=300, blank=True)
    url = models.URLField(blank=True, null=True)
    logo = models.ImageField(null=True,
                             blank=True,
                             upload_to=bp_logo_directory_path)
    email = models.EmailField(blank=True, null=True)
    latitude = models.DecimalField(max_digits=5,
                                   decimal_places=2,
                                   blank=True,
                                   null=True)
    longitude = models.DecimalField(max_digits=5,
                                    decimal_places=2,
                                    blank=True,
                                    null=True)
    lat = models.FloatField(blank=True, null=True)
    lon = models.FloatField(blank=True, null=True)
    geom = models.PointField(srid=4326, blank=True, null=True)
    public_endpoint = models.URLField(blank=True, null=True)
    country = models.CharField(max_length=30, blank=True)
    objects = GeoManager()

    def __str__(self):
        return self.account_name
Esempio n. 28
0
class Photographer(models.Model):
    unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    user = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    business_name = models.CharField(max_length=200)
    business_website = models.TextField()
    description = models.TextField()
    capture_type = models.ManyToManyField(CaptureType)
    capture_method = models.ManyToManyField(CaptureMethod)
    image_quality = models.ManyToManyField(ImageQuality)
    geometry = models.TextField(default='')
    multipolygon = models.MultiPolygonField(null=True, blank=True)
    is_published = models.BooleanField(default=True)
    zoom = models.FloatField(default=5)
    created_at = models.DateTimeField(default=datetime.now, blank=True)
    updated_at = models.DateTimeField(default=datetime.now, blank=True)

    objects = GeoManager()

    def get_absolute_url(self):
        return reverse('photographer.photographer_detail', kwargs={'unique_id': str(self.unique_id)})

    def get_short_description(self):
        description = self.description
        if len(description) > 50:
            return description[0:80] + '...'
        else:
            return description

    def get_capture_type(self):
        captureType = []
        for cType in self.capture_type.all():
            if cType:
                captureType.append(cType.name)

        if len(captureType) > 0:
            return ', '.join(captureType)
        else:
            return ''

    def get_capture_method(self):
        captureMethod = []
        for cMethod in self.capture_method.all():
            if cMethod:
                captureMethod.append(cMethod.name)
        if len(captureMethod) > 0:
            return ', '.join(captureMethod)
        else:
            return ''

    def get_image_quality(self):
        imageQuality = []
        for iQuality in self.image_quality.all():
            if iQuality:
                imageQuality.append(iQuality.name)
        if len(imageQuality) > 0:
            return ', '.join(imageQuality)
        else:
            return ''
Esempio n. 29
0
class Unit(models.Model):
    """ model that saves unit data on a project """
    name = models.CharField(max_length=20)
    location = gis_models.PointField(srid=4326)
    objects = GeoManager()

    def __str__(self):
        return self.name
class Cities(models.Model):
    name = models.CharField(max_length=20)
    location = gismodel.PointField(srid=4326)
    objects = GeoManager()
    def __str__(self):
        return self.name
    class Meta:
        verbose_name_plural = 'cities'