Exemple #1
0
class MultiFields(NamedModel):
    city = models.ForeignKey(City)
    point = models.PointField()
    poly = models.PolygonField()
Exemple #2
0
class Locazione(ConMarcaTemporale, models.Model):
    class Meta:
        verbose_name = "Locazione Geografica"
        verbose_name_plural = "Locazioni Geografiche"
        permissions = (("view_locazione", "Can view locazione"), )

    indirizzo = models.CharField("Indirizzo", max_length=255, db_index=True)

    objects = models.GeoManager()
    geo = models.PointField(blank=True,
                            default='POINT(0.0 0.0)',
                            db_index=True,
                            spatial_index=True,
                            srid=4326,
                            geography=True)

    via = models.CharField("Via", max_length=64, blank=True)
    civico = models.CharField("Civico", max_length=16, blank=True)
    comune = models.CharField("Comune",
                              max_length=64,
                              blank=True,
                              db_index=True)
    provincia = models.CharField("Provincia",
                                 max_length=64,
                                 blank=True,
                                 db_index=True)
    provincia_breve = models.CharField("Provincia (breve)",
                                       max_length=64,
                                       blank=True,
                                       db_index=True)
    regione = models.CharField("Regione",
                               max_length=64,
                               blank=True,
                               db_index=True)
    cap = models.CharField("CAP", max_length=32, blank=True, db_index=True)
    stato = CountryField("Stato", default="IT")

    def __str__(self):
        return self.indirizzo

    @classmethod
    def scomponi_indirizzo(cls, oggetto):
        INDIRIZZO_PARTI = (('civico', ('street_number', 'long_name')),
                           ('via', ('route', 'long_name')),
                           ('comune', ('locality', 'long_name')),
                           ('provincia', ('administrative_area_level_2',
                                          'long_name')),
                           ('provincia_breve',
                            ('administrative_area_level_2',
                             'short_name')), ('regione',
                                              ('administrative_area_level_1',
                                               'long_name')),
                           ('stato', ('country',
                                      'short_name')), ('cap', ('postal_code',
                                                               'long_name')))
        parti = {a[0]: None for a in INDIRIZZO_PARTI}
        for (parte, nomenclatura) in INDIRIZZO_PARTI:
            (a, b) = nomenclatura
            for p in oggetto['address_components']:
                if not a in p['types']:
                    continue
                parti[parte] = p[b].replace('Provincia di ', '').replace('Province of ', '')\
                    .replace('Provincia della ', 'La ').replace('Provincia dell\'', 'L\'')
        return parti

    @classmethod
    def controlla_posizione(cls, coordinate):
        """
        Valida le coordinate. L'unico controllo possibile è che le coordinate non devono essere
        entrambe zero
        :param coordinate: vettore lat / lng ritornato da google geocoding
        :return: coordinate inalterate o '0'
        """
        try:
            if coordinate['lat'] and coordinate['lng']:
                return coordinate
        except (KeyError, ValueError, TypeError):
            return '0'
        return '0'

    @classmethod
    def cerca(cls, indirizzo):
        """
        Usa le API di Google (Geocode) per cercare l'indirizzo,
        ritorna una stringa (indirizzo formattato) per ogni risultato.
        :param indirizzo: Indirizzo da cercare
        :return: Lista di risultati.
        """
        gmaps = googlemaps.Client(key=GOOGLE_KEY)
        risultati = gmaps.geocode(indirizzo, region="it", language="it")
        return [(x['formatted_address'],
                 cls.controlla_posizione(x['geometry']['location']),
                 cls.scomponi_indirizzo(x)) for x in risultati]

    @classmethod
    def oggetto(self, indirizzo):
        """
        Cerca un oggetto per indirizzo. Se esistente, ritorna
        la referenza. Altrimenti, interroga Google, scompone
        l'indirizzo e ritorna una nuova istanza di Locazione (salvata).
        :param indirizzo: Una stringa da ricercare.
        :return: Oggetto Locazione o None se non trovato.
        """
        if not indirizzo:
            return None

        j = Locazione.objects.filter(indirizzo=indirizzo).first()
        if j:
            return j

        risultati = Locazione.cerca(indirizzo)
        if not len(risultati):
            return None
        risultato = risultati[0]

        j = Locazione.objects.filter(indirizzo=risultato[0]).first()
        if j:
            return j

        l = Locazione(indirizzo=risultato[0],
                      geo=Point(risultato[1]['lng'], risultato[1]['lat']),
                      **{
                          k: risultato[2][k] if risultato[2][k] else ''
                          for k in risultato[2]
                      })
        l.save()
        return l

    def cerca_e_aggiorna(self):
        """
        Cerca indirizzo in 'indirizzo' e aggiorna indirizzo e coordinate.
        """
        risultati = Locazione.cerca(self.indirizzo)
        if not len(risultati):
            return False
        risultato = risultati[0]

        self.indirizzo = risultato[0]
        self.geo = Point(risultato[1]['lng'], risultato[1]['lat'])
        valori = {
            k: risultato[2][k] if risultato[2][k] else ''
            for k in risultato[2]
        }
        for k in valori:
            setattr(self, k, valori[k])
        return self.save()

    @property
    def formattato(self):
        return self.indirizzo.replace("Italy", "Italia")
Exemple #3
0
class RegMun(LayerModel):
    name = 'reg_mun'
    ags = models.IntegerField(primary_key=True)
    geom = geomodels.MultiPolygonField(srid=3035)
    geom_centroid = geomodels.PointField(srid=3035, null=True)
    gen = models.CharField(max_length=254)
Exemple #4
0
class DummyModel(gismodels.Model):
    geom = gismodels.PointField()
Exemple #5
0
class PlanetOsmPoint(models.Model):
    osm_id = models.BigIntegerField(primary_key=True)
    access = models.TextField(blank=True, null=True)
    addr_housename = models.TextField(
        db_column='addr:housename', blank=True,
        null=True)  # Field renamed to remove unsuitable characters.
    addr_housenumber = models.TextField(
        db_column='addr:housenumber', blank=True,
        null=True)  # Field renamed to remove unsuitable characters.
    addr_interpolation = models.TextField(
        db_column='addr:interpolation', blank=True,
        null=True)  # Field renamed to remove unsuitable characters.
    admin_level = models.TextField(blank=True, null=True)
    aerialway = models.TextField(blank=True, null=True)
    aeroway = models.TextField(blank=True, null=True)
    amenity = models.TextField(blank=True, null=True)
    area = models.TextField(blank=True, null=True)
    barrier = models.TextField(blank=True, null=True)
    bicycle = models.TextField(blank=True, null=True)
    brand = models.TextField(blank=True, null=True)
    bridge = models.TextField(blank=True, null=True)
    boundary = models.TextField(blank=True, null=True)
    building = models.TextField(blank=True, null=True)
    capital = models.TextField(blank=True, null=True)
    construction = models.TextField(blank=True, null=True)
    covered = models.TextField(blank=True, null=True)
    culvert = models.TextField(blank=True, null=True)
    cutting = models.TextField(blank=True, null=True)
    denomination = models.TextField(blank=True, null=True)
    disused = models.TextField(blank=True, null=True)
    ele = models.TextField(blank=True, null=True)
    embankment = models.TextField(blank=True, null=True)
    foot = models.TextField(blank=True, null=True)
    generator_source = models.TextField(
        db_column='generator:source', blank=True,
        null=True)  # Field renamed to remove unsuitable characters.
    harbour = models.TextField(blank=True, null=True)
    highway = models.TextField(blank=True, null=True)
    historic = models.TextField(blank=True, null=True)
    horse = models.TextField(blank=True, null=True)
    intermittent = models.TextField(blank=True, null=True)
    junction = models.TextField(blank=True, null=True)
    landuse = models.TextField(blank=True, null=True)
    layer = models.TextField(blank=True, null=True)
    leisure = models.TextField(blank=True, null=True)
    lock = models.TextField(blank=True, null=True)
    man_made = models.TextField(blank=True, null=True)
    military = models.TextField(blank=True, null=True)
    motorcar = models.TextField(blank=True, null=True)
    name = models.TextField(blank=True, null=True)
    natural = models.TextField(blank=True, null=True)
    office = models.TextField(blank=True, null=True)
    oneway = models.TextField(blank=True, null=True)
    operator = models.TextField(blank=True, null=True)
    place = models.TextField(blank=True, null=True)
    population = models.TextField(blank=True, null=True)
    power = models.TextField(blank=True, null=True)
    power_source = models.TextField(blank=True, null=True)
    public_transport = models.TextField(blank=True, null=True)
    railway = models.TextField(blank=True, null=True)
    ref = models.TextField(blank=True, null=True)
    religion = models.TextField(blank=True, null=True)
    route = models.TextField(blank=True, null=True)
    service = models.TextField(blank=True, null=True)
    shop = models.TextField(blank=True, null=True)
    sport = models.TextField(blank=True, null=True)
    surface = models.TextField(blank=True, null=True)
    toll = models.TextField(blank=True, null=True)
    tourism = models.TextField(blank=True, null=True)
    tower_type = models.TextField(
        db_column='tower:type', blank=True,
        null=True)  # Field renamed to remove unsuitable characters.
    tunnel = models.TextField(blank=True, null=True)
    water = models.TextField(blank=True, null=True)
    waterway = models.TextField(blank=True, null=True)
    wetland = models.TextField(blank=True, null=True)
    width = models.TextField(blank=True, null=True)
    wood = models.TextField(blank=True, null=True)
    z_order = models.IntegerField(blank=True, null=True)
    way = models.PointField(srid=4326, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'planet_osm_point'
Exemple #6
0
class Device(BaseAccessLevel):
    """
    Device Model
    Represents a network device
    eg: an outdoor point-to-point wifi device, a BGP router, a server, and so on
    """
    name = models.CharField(_('name'), max_length=50)
    node = models.ForeignKey('nodes.Node', verbose_name=_('node'))
    type = models.CharField(_('type'),
                            max_length=50,
                            choices=DEVICE_TYPES_CHOICES)
    status = models.SmallIntegerField(_('status'),
                                      choices=DEVICE_STATUS_CHOICES,
                                      default=DEVICE_STATUS.get('unknown'))

    # geographic data
    location = models.PointField(
        _('location'),
        blank=True,
        null=True,
        help_text=_("""specify device coordinates (if different from node);
                                    defaults to node coordinates if node is a point,
                                    otherwise if node is a geometry it will default to che centroid of the geometry"""
                    ))
    elev = models.FloatField(_('elevation'), blank=True, null=True)

    # device specific
    routing_protocols = models.ManyToManyField('net.RoutingProtocol',
                                               blank=True)

    os = models.CharField(_('operating system'),
                          max_length=128,
                          blank=True,
                          null=True)
    os_version = models.CharField(_('operating system version'),
                                  max_length=128,
                                  blank=True,
                                  null=True)

    first_seen = models.DateTimeField(_('first time seen on'),
                                      blank=True,
                                      null=True,
                                      default=None)
    last_seen = models.DateTimeField(_('last time seen on'),
                                     blank=True,
                                     null=True,
                                     default=None)

    # text
    description = models.CharField(_('description'),
                                   max_length=255,
                                   blank=True,
                                   null=True)
    notes = models.TextField(_('notes'), blank=True, null=True)

    # extra data
    data = DictionaryField(
        _('extra data'),
        null=True,
        blank=True,
        help_text=_('store extra attributes in JSON string'))
    shortcuts = ReferencesField(null=True, blank=True)

    objects = DeviceManager()

    # list indicating if any other module has extended this model
    extended_by = []

    class Meta:
        app_label = 'net'

    def __unicode__(self):
        return '%s' % self.name

    def save(self, *args, **kwargs):
        """
        Custom save method does the following:
            * automatically inherit node coordinates and elevation
            * save shortcuts if HSTORE is enabled
        """
        custom_checks = kwargs.pop('custom_checks', True)

        super(Device, self).save(*args, **kwargs)

        if custom_checks is False:
            return

        changed = False

        if not self.location:
            self.location = self.node.point
            changed = True

        if not self.elev and self.node.elev:
            self.elev = self.node.elev
            changed = True

        original_user = self.shortcuts.get('user')

        if self.node.user:
            self.shortcuts['user'] = self.node.user

        if original_user != self.shortcuts.get('user'):
            changed = True

        if 'nodeshot.core.layers' in settings.INSTALLED_APPS:
            original_layer = self.shortcuts.get('layer')
            self.shortcuts['layer'] = self.node.layer

            if original_layer != self.shortcuts.get('layer'):
                changed = True

        if changed:
            self.save(custom_checks=False)

    @property
    def owner(self):
        if 'user' not in self.shortcuts:
            if self.node or self.node_id:
                self.save()
            else:
                raise Exception('Instance does not have a node set yet')
        return self.shortcuts['user']

    @property
    def layer(self):
        if 'nodeshot.core.layers' not in settings.INSTALLED_APPS:
            return False
        if 'layer' not in self.shortcuts:
            if self.node or self.node_id:
                self.save()
            else:
                raise Exception('Instance does not have a node set yet')
        return self.shortcuts['layer']

    if 'grappelli' in settings.INSTALLED_APPS:

        @staticmethod
        def autocomplete_search_fields():
            return ('name__icontains', )
Exemple #7
0
class Comercio(models.Model):
    nombre = models.CharField(max_length=100)
    latlng = models.PointField()
    ciudad = models.ForeignKey(Ciudad)
    objects = models.GeoManager()
Exemple #8
0
class VD(models.Model):
    authOwner = models.ForeignKey(User,
                                  on_delete=models.SET_DEFAULT,
                                  null=True,
                                  default=None,
                                  related_name='vds')
    realOwner = models.ForeignKey(RealUser,
                                  on_delete=models.SET_DEFAULT,
                                  null=True,
                                  default=None,
                                  related_name='vds')

    lastLonLat = models.PointField(blank=True,
                                   null=True,
                                   default=None,
                                   geography=True)
    data = JSONField(blank=True, null=True, default=None, db_index=False)

    deviceName = models.CharField(max_length=254,
                                  blank=True,
                                  null=True,
                                  default=None)
    deviceTypeName = models.CharField(max_length=36,
                                      blank=True,
                                      null=True,
                                      default=None)

    country = models.CharField(max_length=2,
                               blank=True,
                               null=True,
                               default=None)
    language = models.CharField(max_length=2,
                                blank=True,
                                null=True,
                                default=None)
    timezone = models.CharField(max_length=5,
                                blank=True,
                                null=True,
                                default=None)

    parent = models.ForeignKey('self',
                               on_delete=models.SET_DEFAULT,
                               null=True,
                               default=None,
                               related_name='childs')
    mask = models.SmallIntegerField(blank=True, null=True, default=None)

    accessHistory = JSONField(blank=True,
                              null=True,
                              default=None,
                              db_index=False)

    def __init__(self, *args, **kwargs):
        super(VD, self).__init__(*args, **kwargs)

    def __unicode__(self):
        email = (self.realOwner and self.realOwner.email) or (
            self.authOwner and self.authOwner.email) or 'unknown@email'
        deviceTypeName = self.deviceTypeName or 'unknown device'
        deviceNameCaption = (self.deviceName
                             and ' (%s)' % self.deviceName) or ''
        return '%s\'s %s%s' % (email, deviceTypeName, deviceNameCaption)

    @property
    def aid(self):
        encrypter = Fernet(self.authOwner.crypto_key)
        result = encrypter.encrypt(unicode(self.id).encode(encoding='utf-8'))
        return result

    def aid2id(self, aid):
        return self.authOwner.aid2id(aid)

    @property
    def realOwner_vd_ids(self):
        if self.realOwner:
            result, is_created = cache_get_or_create(
                self, 'realOwner_vd_ids', None, lambda: self.realOwner.vd_ids)
            return result
        return [self.id]

    @property
    def realOwner_publisher_ids(self):
        def helper(vd_ids):
            from importer.models import Importer
            importers = Importer.objects.filter(subscriber_id__in=vd_ids)
            if importers:
                return sum(
                    [importer.publisher.vd_ids for importer in importers], [])
            else:
                return []

        result, is_created = cache_get_or_create(self,
                                                 'realOwner_publisher_ids',
                                                 None, helper,
                                                 self.realOwner_vd_ids)
        return result

    @property
    def realOwner_place_ids(self):
        def helper(vd_ids):
            from place.models import Place
            return [
                place.id
                for place in Place.objects.filter(uplaces__vd_id__in=vd_ids)
            ]

        result, is_created = cache_get_or_create(self, 'realOwner_place_ids',
                                                 None, helper,
                                                 self.realOwner_vd_ids)
        return result

    @property
    def realOwner_duplicated_uplace_ids(self):
        def helper(vd_ids):
            from place.libs import get_valid_uplaces_qs
            base = get_valid_uplaces_qs().exclude(place_id=None).filter(
                vd_id__in=vd_ids)
            group_by = base.values('place_id').annotate(cnt=Count(1)).filter(
                cnt__gte=2)
            result = list()
            before = None
            for uplace in base.filter(
                    place_id__in=[row['place_id']
                                  for row in group_by]).order_by(
                                      'place_id', '-id'):
                if uplace.place_id == (before and before.place_id):
                    result.append(uplace.id)
                before = uplace
            return result

        result, is_created = cache_get_or_create(
            self, 'realOwner_duplicated_uplace_ids', None, helper,
            self.realOwner_vd_ids)
        return result

    @property
    def realOwner_duplicated_iplace_ids(self):
        def helper(vd_ids):
            from importer.models import ImportedPlace
            base = ImportedPlace.objects.all().exclude(place_id=None).filter(
                vd_id__in=vd_ids)
            group_by = base.values('place_id').annotate(cnt=Count(1)).filter(
                cnt__gte=2)
            result = list()
            before = None
            for iplace in base.filter(
                    place_id__in=[row['place_id']
                                  for row in group_by]).order_by(
                                      'place_id', '-id'):
                if iplace.place_id == (before and before.place_id):
                    result.append(iplace.id)
                before = iplace
            return result

        result, is_created = cache_get_or_create(
            self, 'realOwner_duplicated_iplace_ids', None, helper,
            self.realOwner_publisher_ids)
        return result

    @property
    def is_private(self):
        return (self.mask or 0) & 1 != 0

    @is_private.setter
    def is_private(self, value):
        if value:
            self.mask = (self.mask or 0) | 1
        else:
            self.mask = (self.mask or 0) & (~1)

    @property
    def is_public(self):
        return (self.mask or 0) & 2 != 0

    @is_public.setter
    def is_public(self, value):
        if value:
            self.mask = (self.mask or 0) | 2
        else:
            self.mask = (self.mask or 0) & (~2)

    def save(self, *args, **kwargs):
        if not self.mask:
            self.mask = 0
        self.data = convert_to_json(self.data)
        self.accessHistory = convert_to_json(self.accessHistory)
        cache_expire_ru(self, 'realOwner_vd_ids')
        super(VD, self).save(*args, **kwargs)

    # TODO : 제대로 구현하기
    @property
    def error_tagging_ratio(self):
        # P(D|~H) / P(D|H)
        return 0.2

    def getToken(self):
        raw_token = '%s|%s' % (self.id, self.authOwner_id)
        encrypter = Fernet(self.authOwner.crypto_key)
        return encrypter.encrypt(raw_token.encode(encoding='utf-8'))

    def getEmailConfirmToken(self, email):
        from pks.settings import VD_ENC_KEY
        raw_token = '%s|%s' % (self.id, email)
        encrypter = Fernet(VD_ENC_KEY)
        return encrypter.encrypt(raw_token.encode(encoding='utf-8'))

    def add_access_history(self, uplaces):
        if not self.accessHistory:
            self.accessHistory = dict(uplaces=[])
        if not type(uplaces) is list:
            uplaces = [uplaces]
        for uplace in uplaces:
            uuid = uplace.uuid
            timestamp = get_timestamp()
            self.accessHistory['uplaces'].insert(
                0, dict(uuid=uuid, timestamp=timestamp))
        super(VD, self).save()

    @property
    def accessUplaces(self):
        from place.models import UserPlace
        result = []
        if self.accessHistory and 'uplaces' in self.accessHistory:
            for d in self.accessHistory['uplaces']:
                uplace = UserPlace.get_from_uuid(d['uuid'])
                uplace.accessed = d['timestamp']
                result.append(uplace)
        return result

    def send_confirm_email(self, email):
        # send email for confirm
        # TODO : 관련 테스트 보강
        from account.task_wrappers import EmailTaskWrapper
        from pks.settings import SERVER_HOST
        task = EmailTaskWrapper()
        to = email
        title = '사진 공유 서비스 포플(PHOPL) 이메일 인증'
        confirm_link = '%s/vds/confirm/?email_confirm_token=%s' % (
            SERVER_HOST, self.getEmailConfirmToken(to))
        msg = '안녕하세요. 사진 공유 서비스 포플(PHOPL) 입니다.\n이메일 인증을 위해 하기 링크를 터치해 주세요.\n\n%s' % confirm_link
        r = task.delay(to, title, msg)
        return not r.failed()
Exemple #9
0
class SignpostPlan(UpdatePlanLocationMixin, SourceControlModel,
                   SoftDeleteModel, UserControlModel):
    id = models.UUIDField(primary_key=True,
                          unique=True,
                          editable=False,
                          default=uuid.uuid4)
    location = models.PointField(_("Location (2D)"), srid=settings.SRID)
    height = models.DecimalField(_("Height"),
                                 max_digits=5,
                                 decimal_places=2,
                                 blank=True,
                                 null=True)
    direction = models.IntegerField(_("Direction"), default=0)
    device_type = models.ForeignKey(
        TrafficControlDeviceType,
        verbose_name=_("Device type"),
        on_delete=models.PROTECT,
        limit_choices_to=Q(
            Q(target_model=None)
            | Q(target_model=DeviceTypeTargetModel.SIGNPOST)),
    )
    value = models.IntegerField(_("Signpost value"), blank=True, null=True)
    txt = models.CharField(_("Signpost txt"),
                           max_length=254,
                           blank=True,
                           null=True)
    parent = models.ForeignKey(
        "self",
        verbose_name=_("Parent Signpost Plan"),
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )
    mount_plan = models.ForeignKey(
        MountPlan,
        verbose_name=_("Mount Plan"),
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )
    mount_type = models.ForeignKey(
        MountType,
        verbose_name=_("Mount type"),
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
    )
    decision_date = models.DateField(_("Decision date"))
    decision_id = models.CharField(_("Decision id"),
                                   max_length=254,
                                   blank=True,
                                   null=True)
    validity_period_start = models.DateField(_("Validity period start"),
                                             blank=True,
                                             null=True)
    validity_period_end = models.DateField(_("Validity period end"),
                                           blank=True,
                                           null=True)
    plan = models.ForeignKey(
        Plan,
        verbose_name=_("Plan"),
        on_delete=models.PROTECT,
        related_name="signpost_plans",
        blank=True,
        null=True,
    )
    owner = models.ForeignKey(
        "traffic_control.Owner",
        verbose_name=_("Owner"),
        blank=False,
        null=False,
        on_delete=models.PROTECT,
    )
    size = EnumField(
        Size,
        verbose_name=_("Size"),
        max_length=1,
        default=Size.MEDIUM,
        blank=True,
        null=True,
    )
    reflection_class = EnumField(
        Reflection,
        verbose_name=_("Reflection"),
        max_length=2,
        default=Reflection.R1,
        blank=True,
        null=True,
    )
    seasonal_validity_period_start = models.DateField(
        _("Seasonal validity period start"), blank=True, null=True)
    seasonal_validity_period_end = models.DateField(
        _("Seasonal validity period end"), blank=True, null=True)
    attachment_class = models.CharField(_("Attachment class"),
                                        max_length=254,
                                        blank=True,
                                        null=True)
    target_id = models.CharField(_("Target ID"),
                                 max_length=254,
                                 blank=True,
                                 null=True)
    target_txt = models.CharField(_("Target txt"),
                                  max_length=254,
                                  blank=True,
                                  null=True)
    responsible_entity = models.CharField(_("Responsible entity"),
                                          max_length=254,
                                          blank=True,
                                          null=True)
    electric_maintainer = models.CharField(_("Electric maintainer"),
                                           max_length=254,
                                           blank=True,
                                           null=True)
    lifecycle = EnumIntegerField(Lifecycle,
                                 verbose_name=_("Lifecycle"),
                                 default=Lifecycle.ACTIVE)
    road_name = models.CharField(_("Road name"),
                                 max_length=254,
                                 blank=True,
                                 null=True)
    lane_number = EnumField(LaneNumber,
                            verbose_name=_("Lane number"),
                            default=LaneNumber.MAIN_1,
                            blank=True)
    lane_type = EnumField(
        LaneType,
        verbose_name=_("Lane type"),
        default=LaneType.MAIN,
        blank=True,
    )
    location_specifier = EnumIntegerField(
        LocationSpecifier,
        verbose_name=_("Location specifier"),
        default=LocationSpecifier.RIGHT,
        blank=True,
        null=True,
    )

    objects = SoftDeleteQuerySet.as_manager()

    class Meta:
        db_table = "signpost_plan"
        verbose_name = _("Signpost Plan")
        verbose_name_plural = _("Signpost Plans")
        unique_together = ["source_name", "source_id"]

    def __str__(self):
        return f"{self.id} {self.device_type} {self.txt}"

    def save(self, *args, **kwargs):
        if not self.device_type.validate_relation(
                DeviceTypeTargetModel.SIGNPOST):
            raise ValidationError(
                f'Device type "{self.device_type}" is not allowed for signposts'
            )

        super().save(*args, **kwargs)
 class FakePoint(models.Model):
     fake_id = models.IntegerField(primary_key=True)
     name = models.TextField()
     point = models.PointField(srid=4326)
Exemple #11
0
class SprayDay(models.Model):
    """
    SprayDay model  - IRS HH submission data model.
    """

    submission_id = models.PositiveIntegerField(unique=True)
    osmid = models.BigIntegerField(null=True, db_index=True)
    spray_date = models.DateField(db_index=True)
    geom = models.PointField(srid=4326, db_index=True, null=True)
    bgeom = models.GeometryField(srid=4326, db_index=True, null=True)
    data = JSONField(default=dict)
    location = models.ForeignKey("Location",
                                 db_index=True,
                                 null=True,
                                 on_delete=models.CASCADE)
    rhc = models.ForeignKey(
        "Location",
        db_index=True,
        null=True,
        related_name="visited_rhc",
        on_delete=models.CASCADE,
    )
    district = models.ForeignKey(
        "Location",
        db_index=True,
        null=True,
        related_name="visited_district",
        on_delete=models.CASCADE,
    )
    team_leader = models.ForeignKey("TeamLeader",
                                    db_index=True,
                                    null=True,
                                    on_delete=models.CASCADE)
    team_leader_assistant = models.ForeignKey(
        "TeamLeaderAssistant",
        db_index=True,
        null=True,
        on_delete=models.CASCADE,
    )
    spray_operator = models.ForeignKey("SprayOperator",
                                       db_index=True,
                                       null=True,
                                       on_delete=models.CASCADE)
    household = models.ForeignKey("Household",
                                  null=True,
                                  on_delete=models.SET_NULL)
    start_time = models.DateTimeField(null=True)
    end_time = models.DateTimeField(null=True)

    was_sprayed = models.BooleanField(default=False)
    sprayable = models.BooleanField(default=False)
    created_on = models.DateTimeField(auto_now_add=True)
    modified_on = models.DateTimeField(auto_now=True)

    class Meta:
        app_label = "main"

    def __str__(self):
        return self.spray_date.isoformat()

    def _set_sprayed_status(self):
        # pylint: disable=no-member
        was_sprayed_field = getattr(settings, "MSPRAY_WAS_SPRAYED_FIELD",
                                    WAS_SPRAYED_FIELD)
        sprayed_values = getattr(settings, "SPRAYED_VALUES", [])
        if self.data.get(was_sprayed_field):
            if sprayed_values:
                self.was_sprayed = (self.data.get(was_sprayed_field)
                                    in sprayed_values)
            else:
                self.was_sprayed = (
                    self.data.get(was_sprayed_field) == SPRAYED_VALUE)
        elif self.data.get(NEW_WAS_SPRAYED_FIELD):
            self.was_sprayed = (
                self.data.get(NEW_WAS_SPRAYED_FIELD) == SPRAYED_VALUE)

    def _set_sprayable_status(self):
        # pylint: disable=no-member
        sprayable_field = getattr(settings, "SPRAYABLE_FIELD", SPRAYABLE_FIELD)
        new_sprayable_field = getattr(settings,
                                      "NEW_STRUCTURE_SPRAYABLE_FIELD",
                                      NEW_STRUCTURE_GPS_FIELD)
        not_sprayable_value = getattr(settings, "NOT_SPRAYABLE_VALUE",
                                      NOT_SPRAYABLE_VALUE)
        if self.data.get(sprayable_field):
            self.sprayable = (self.data.get(sprayable_field) !=
                              not_sprayable_value)
        elif self.data.get(new_sprayable_field):
            self.sprayable = (self.data.get(new_sprayable_field) !=
                              not_sprayable_value)

    def _set_parent_locations(self):
        if self.location:
            if self.rhc != self.location.parent:  # pylint: disable=no-member
                self.rhc = self.location.parent  # pylint: disable=no-member
            if self.district != self.rhc.parent:  # pylint: disable=no-member
                self.district = self.rhc.parent  # pylint: disable=no-member

    def has_osm_data(self):
        """
        Check if OSM data has been received for this record
        we assume that if settings.MSPRAY_OSM_PRESENCE_FIELD is present
        then this record has received OSM data
        """
        return settings.MSPRAY_OSM_PRESENCE_FIELD in self.data

    # pylint: disable=arguments-differ
    def save(self, *args, **kwargs):
        from mspray.apps.main.utils import get_formid  # noqa

        self._set_sprayed_status()
        self._set_sprayable_status()
        self._set_parent_locations()

        if "sprayformid" and self.spray_operator:
            self.data.update({  # pylint: disable=no-member
                "sprayformid":
                get_formid(self.spray_operator, self.spray_date)
            })
        osmid = get_osmid(self.data)
        try:
            if osmid and int(osmid) != self.osmid and not self.location:
                self.osmid = osmid
        except ValueError:
            pass

        return super(SprayDay, self).save(*args, **kwargs)
 class FakePoint(models.Model):
     name = models.CharField(max_length=30)
     point = models.PointField()
     objects = models.GeoManager()
Exemple #13
0
class Map(NamedModel):
    """
    A single thematical map.
    """
    ANONYMOUS = 1
    EDITORS = 2
    OWNER = 3
    PUBLIC = 1
    OPEN = 2
    PRIVATE = 3
    EDIT_STATUS = (
        (ANONYMOUS, _('Everyone can edit')),
        (EDITORS, _('Only editors can edit')),
        (OWNER, _('Only owner can edit')),
    )
    SHARE_STATUS = (
        (PUBLIC, _('everyone (public)')),
        (OPEN, _('anyone with link')),
        (PRIVATE, _('editors only')),
    )
    slug = models.SlugField(db_index=True)
    description = models.TextField(blank=True,
                                   null=True,
                                   verbose_name=_("description"))
    center = models.PointField(geography=True, verbose_name=_("center"))
    zoom = models.IntegerField(default=7, verbose_name=_("zoom"))
    locate = models.BooleanField(default=False,
                                 verbose_name=_("locate"),
                                 help_text=_("Locate user on load?"))
    licence = models.ForeignKey(Licence,
                                help_text=_("Choose the map licence."),
                                verbose_name=_('licence'),
                                on_delete=models.SET_DEFAULT,
                                default=get_default_licence)
    modified_at = models.DateTimeField(auto_now=True)
    tilelayer = models.ForeignKey(TileLayer,
                                  blank=True,
                                  null=True,
                                  related_name="maps",
                                  verbose_name=_("background"))
    owner = models.ForeignKey(settings.AUTH_USER_MODEL,
                              blank=True,
                              null=True,
                              related_name="owned_maps",
                              verbose_name=_("owner"))
    editors = models.ManyToManyField(settings.AUTH_USER_MODEL,
                                     blank=True,
                                     verbose_name=_("editors"))
    edit_status = models.SmallIntegerField(choices=EDIT_STATUS,
                                           default=OWNER,
                                           verbose_name=_("edit status"))
    share_status = models.SmallIntegerField(choices=SHARE_STATUS,
                                            default=PUBLIC,
                                            verbose_name=_("share status"))
    settings = DictField(blank=True, null=True, verbose_name=_("settings"))

    objects = models.GeoManager()
    public = PublicManager()

    def get_absolute_url(self):
        return reverse("map",
                       kwargs={
                           'slug': self.slug or "map",
                           'pk': self.pk
                       })

    def get_anonymous_edit_url(self):
        signer = Signer()
        signature = signer.sign(self.pk)
        return reverse('map_anonymous_edit_url',
                       kwargs={'signature': signature})

    def is_anonymous_owner(self, request):
        if self.owner:
            # edit cookies are only valid while map hasn't owner
            return False
        key, value = self.signed_cookie_elements
        try:
            has_anonymous_cookie = int(request.get_signed_cookie(
                key, False)) == value
        except ValueError:
            has_anonymous_cookie = False
        return has_anonymous_cookie

    def can_edit(self, user=None, request=None):
        """
        Define if a user can edit or not the instance, according to his account
        or the request.
        """
        can = False
        if request and not self.owner:
            if (getattr(settings, "LEAFLET_STORAGE_ALLOW_ANONYMOUS", False)
                    and self.is_anonymous_owner(request)):
                can = True
                if user and user.is_authenticated():
                    # if user is authenticated, attach as owner
                    self.owner = user
                    self.save()
                    msg = _(
                        "Your anonymous map has been attached to your account %s"
                        % user)
                    messages.info(request, msg)
        if self.edit_status == self.ANONYMOUS:
            can = True
        elif not user.is_authenticated():
            pass
        elif user == self.owner:
            can = True
        elif self.edit_status == self.EDITORS and user in self.editors.all():
            can = True
        return can

    def can_view(self, request):
        if self.owner is None:
            can = True
        elif self.share_status in [self.PUBLIC, self.OPEN]:
            can = True
        elif request.user == self.owner:
            can = True
        else:
            can = not (self.share_status == self.PRIVATE
                       and request.user not in self.editors.all())
        return can

    @property
    def signed_cookie_elements(self):
        return ('anonymous_owner|%s' % self.pk, self.pk)

    def get_tilelayer(self):
        return self.tilelayer or TileLayer.get_default()

    def clone(self, **kwargs):
        new = self.__class__.objects.get(pk=self.pk)
        new.pk = None
        new.name = u"%s %s" % (_("Clone of"), self.name)
        if "owner" in kwargs:
            # can be None in case of anonymous cloning
            new.owner = kwargs["owner"]
        new.save()
        for editor in self.editors.all():
            new.editors.add(editor)
        for datalayer in self.datalayer_set.all():
            datalayer.clone(map_inst=new)
        return new
Exemple #14
0
class NonConcreteModel(NamedModel):
    non_concrete = NonConcreteField()
    point = models.PointField(geography=True)
class TrafficSignPlan(UpdatePlanLocationMixin, SourceControlModel,
                      SoftDeleteModel, UserControlModel):
    id = models.UUIDField(primary_key=True,
                          unique=True,
                          editable=False,
                          default=uuid.uuid4)
    location = models.PointField(_("Location (3D)"), dim=3, srid=settings.SRID)
    height = models.IntegerField(_("Height"), blank=True, null=True)
    direction = models.IntegerField(_("Direction"), default=0)
    device_type = models.ForeignKey(
        TrafficControlDeviceType,
        verbose_name=_("Device type"),
        on_delete=models.PROTECT,
        limit_choices_to=Q(
            Q(target_model=None)
            | Q(target_model=DeviceTypeTargetModel.TRAFFIC_SIGN)),
    )
    value = models.IntegerField(_("Traffic Sign Code value"),
                                blank=True,
                                null=True)
    txt = models.CharField(_("Txt"), max_length=254, blank=True, null=True)
    mount_plan = models.ForeignKey(
        MountPlan,
        verbose_name=_("Mount Plan"),
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )
    mount_type = models.ForeignKey(
        MountType,
        verbose_name=_("Mount type"),
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
    )
    decision_date = models.DateField(_("Decision date"))
    decision_id = models.CharField(_("Decision id"),
                                   max_length=254,
                                   blank=True,
                                   null=True)
    validity_period_start = models.DateField(_("Validity period start"),
                                             blank=True,
                                             null=True)
    validity_period_end = models.DateField(_("Validity period end"),
                                           blank=True,
                                           null=True)
    affect_area = models.PolygonField(_("Affect area (2D)"),
                                      srid=settings.SRID,
                                      blank=True,
                                      null=True)
    plan = models.ForeignKey(
        Plan,
        verbose_name=_("Plan"),
        on_delete=models.PROTECT,
        related_name="traffic_sign_plans",
        blank=True,
        null=True,
    )
    size = EnumField(
        Size,
        verbose_name=_("Size"),
        max_length=1,
        default=Size.MEDIUM,
        blank=True,
        null=True,
    )
    reflection_class = EnumField(
        Reflection,
        verbose_name=_("Reflection"),
        max_length=2,
        default=Reflection.R1,
        blank=True,
        null=True,
    )
    surface_class = EnumField(
        Surface,
        verbose_name=_("Surface"),
        max_length=6,
        default=Surface.FLAT,
        blank=True,
        null=True,
    )
    seasonal_validity_period_start = models.DateField(
        _("Seasonal validity period start"), blank=True, null=True)
    seasonal_validity_period_end = models.DateField(
        _("Seasonal validity period end"), blank=True, null=True)
    owner = models.ForeignKey(
        "traffic_control.Owner",
        verbose_name=_("Owner"),
        blank=False,
        null=False,
        on_delete=models.PROTECT,
    )
    lifecycle = EnumIntegerField(Lifecycle,
                                 verbose_name=_("Lifecycle"),
                                 default=Lifecycle.ACTIVE)
    road_name = models.CharField(_("Road name"),
                                 max_length=254,
                                 blank=True,
                                 null=True)
    lane_number = EnumField(LaneNumber,
                            verbose_name=_("Lane number"),
                            default=LaneNumber.MAIN_1,
                            blank=True)
    lane_type = EnumField(
        LaneType,
        verbose_name=_("Lane type"),
        default=LaneType.MAIN,
        blank=True,
    )
    location_specifier = EnumIntegerField(
        LocationSpecifier,
        verbose_name=_("Location specifier"),
        default=LocationSpecifier.RIGHT,
        blank=True,
        null=True,
    )

    objects = TrafficSignPlanQuerySet.as_manager()

    class Meta:
        db_table = "traffic_sign_plan"
        verbose_name = _("Traffic Sign Plan")
        verbose_name_plural = _("Traffic Sign Plans")
        unique_together = ["source_name", "source_id"]

    def __str__(self):
        return f"{self.id} {self.device_type}"

    def save(self, *args, **kwargs):
        if not self.device_type.validate_relation(
                DeviceTypeTargetModel.TRAFFIC_SIGN):
            raise ValidationError(
                f'Device type "{self.device_type}" is not allowed for traffic signs'
            )

        super().save(*args, **kwargs)

    def has_additional_signs(self):
        return self.additional_signs.active().exists()

    @transaction.atomic
    def soft_delete(self, user):
        super().soft_delete(user)
        self.additional_signs.soft_delete(user)
Exemple #16
0
class Leaflet(geo_model.Model):
    def __init__(self, *args, **kwargs):
        super(Leaflet, self).__init__(*args, **kwargs)
        self._initial = model_to_dict(
            self, fields=[field.name for field in self._meta.fields]
        )

    title = models.CharField(blank=True, max_length=765)
    description = models.TextField(blank=True, null=True)
    publisher_party = models.ForeignKey(
        Party, blank=True, null=True, on_delete=models.CASCADE
    )
    ynr_party_id = models.CharField(
        blank=True, null=True, max_length=255, db_index=True
    )
    ynr_party_name = models.CharField(blank=True, null=True, max_length=255)
    publisher_person = models.ForeignKey(
        Person, blank=True, null=True, on_delete=models.CASCADE
    )
    ynr_person_id = models.IntegerField(blank=True, null=True, db_index=True)
    ynr_person_name = models.CharField(blank=True, null=True, max_length=255)
    ballot_id = models.CharField(
        blank=True, null=True, max_length=255, db_index=True
    )
    election = models.ForeignKey(Election, null=True, on_delete=models.CASCADE)
    constituency = models.ForeignKey(
        Constituency, blank=True, null=True, on_delete=models.CASCADE
    )
    imprint = models.TextField(blank=True, null=True)
    postcode = models.CharField(max_length=150, blank=True)
    location = geo_model.PointField(null=True, blank=True)
    name = models.CharField(blank=True, max_length=300)
    email = models.CharField(blank=True, max_length=300)
    date_uploaded = models.DateTimeField(auto_now_add=True)
    date_delivered = models.DateTimeField(blank=True, null=True)
    status = models.CharField(
        choices=constants.LEAFLET_STATUSES,
        null=True,
        blank=True,
        max_length=255,
    )
    reviewed = models.BooleanField(default=False)

    objects = models.Manager()

    def __unicode__(self):
        return self.title

    class Meta:
        ordering = ("-date_uploaded",)

    def get_absolute_url(self):
        from django.contrib.sites.models import Site

        return "http://%s/leaflets/%s/" % (
            Site.objects.get_current().domain,
            self.id,
        )

    def get_first_image(self):
        try:
            return self.images.all()[0]
        except IndexError:
            # TODO: Set image_key to value for 'empty' image
            return None

    def get_title(self):
        if self.title and len(self.title):
            return self.title
        elif self.publisher_party:
            return "%s leaflet" % self.publisher_party.party_name
        else:
            "Untitled leaflet"

    def get_person(self):
        if (
            self.ynr_person_id
            and self.ynr_person_name
            and not self.publisher_person
        ):
            return {
                "link": reverse(
                    "person", kwargs={"remote_id": self.ynr_person_id}
                ),
                "name": self.ynr_person_name,
            }
        elif self.publisher_person:
            return {
                "link": reverse(
                    "person",
                    kwargs={"remote_id": self.publisher_person.remote_id},
                ),
                "name": self.publisher_person.name,
            }

    def get_party(self):
        if self.ynr_party_id and self.ynr_party_name:
            pp_id = "PP{}".format(re.sub(r"party:", "", self.ynr_party_id))
            return {
                "link": reverse("party-view", kwargs={"pk": pp_id}),
                "name": self.ynr_party_name,
            }
        elif self.publisher_party:
            return {
                "link": reverse(
                    "party-view", kwargs={"pk": self.publisher_party.pk}
                ),
                "name": self.publisher_party.party_name,
            }

    def get_ballot(self):
        if self.ballot_id:
            r = devs_dc_helper.ballot_request(self.ballot_id)
            if r.status_code == 200:
                ballot = r.json()
                return {
                    "name": "{} in {}".format(
                        ballot["election_title"],
                        ballot["election_type"]["name"],
                    ),
                    "link": "https://whocanivotefor.co.uk/elections/{}".format(
                        self.ballot_id
                    ),
                }

    def geocode(self, postcode):
        data = geocode(postcode)
        if data:
            self.constituency = data["constituency"]
            self.location = Point(data["wgs84_lon"], data["wgs84_lat"],)

    def save(self, *args, **kwargs):
        if self.postcode:
            if self.postcode != self._initial["postcode"]:
                self.geocode(self.postcode)

        super(Leaflet, self).save(*args, **kwargs)
Exemple #17
0
class DummyInlineModel(gismodels.Model):
    geom = gismodels.PointField()

    class Meta:
        app_label = "leaflet"
Exemple #18
0
class PlanetOsmPoint(models.Model):
    """
    osm point model
    """

    osm_fields: dict = {
        "access": str,
        "addr:housename": str,
        "addr:housenumber": str,
        "admin_level": str,
        "aerialway": str,
        "aeroway": str,
        "amenity": str,
        "barrier": str,
        "boundary": str,
        "building": str,
        "highway": str,
        "historic": str,
        "junction": str,
        "landuse": str,
        "layer": int,
        "leisure": str,
        "lock": str,
        "man_made": str,
        "military": str,
        "name": str,
        "natural": str,
        "oneway": str,
        "place": str,
        "power": str,
        "railway": str,
        "ref": str,
        "religion": str,
        "shop": str,
        "tourism": str,
        "water": str,
        "waterway": str,
    }

    id = models.BigAutoField(primary_key=True)
    osm_id = models.BigIntegerField(blank=True, null=True)
    version = models.IntegerField(blank=True, null=True)
    visible = models.BooleanField(blank=True, null=True)
    geoobject = models.BigIntegerField(blank=True, null=True)
    access = models.TextField(blank=True, null=True)
    addr_housename = models.TextField(db_column="addr:housename",
                                      blank=True,
                                      null=True)
    addr_housenumber = models.TextField(db_column="addr:housenumber",
                                        blank=True,
                                        null=True)
    admin_level = models.TextField(blank=True, null=True)
    aerialway = models.TextField(blank=True, null=True)
    aeroway = models.TextField(blank=True, null=True)
    amenity = models.TextField(blank=True, null=True)
    barrier = models.TextField(blank=True, null=True)
    boundary = models.TextField(blank=True, null=True)
    building = models.TextField(blank=True, null=True)
    highway = models.TextField(blank=True, null=True)
    historic = models.TextField(blank=True, null=True)
    junction = models.TextField(blank=True, null=True)
    landuse = models.TextField(blank=True, null=True)
    layer = models.IntegerField(blank=True, null=True)
    leisure = models.TextField(blank=True, null=True)
    lock = models.TextField(blank=True, null=True)
    man_made = models.TextField(blank=True, null=True)
    military = models.TextField(blank=True, null=True)
    name = models.TextField(blank=True, null=True)
    natural = models.TextField(blank=True, null=True)
    oneway = models.TextField(blank=True, null=True)
    place = models.TextField(blank=True, null=True)
    power = models.TextField(blank=True, null=True)
    railway = models.TextField(blank=True, null=True)
    ref = models.TextField(blank=True, null=True)
    religion = models.TextField(blank=True, null=True)
    shop = models.TextField(blank=True, null=True)
    tourism = models.TextField(blank=True, null=True)
    water = models.TextField(blank=True, null=True)
    waterway = models.TextField(blank=True, null=True)
    tags = HStoreField(default=dict)
    way = models.PointField(srid=3857, blank=True, null=True)
    valid_since = models.DateField(blank=True, null=True)
    valid_until = models.DateField(blank=True, null=True)

    class Meta:
        db_table = "planet_osm_point"
Exemple #19
0
class PimpUser(AbstractEmailUser):

    MARKETER = 0
    CAUSE = 1
    ADMIN = 2
    USER_TYPE_CHOICES = ((MARKETER, "Marketer"), (CAUSE, "Cause"), (ADMIN,
                                                                    "Admin"))
    REQUIRED_FIELDS = ['usertype']

    # basic info
    name = models.CharField(max_length=240, blank=True, null=True)
    surname = models.CharField(max_length=240, blank=True, null=True)
    phone = models.CharField(max_length=250, blank=True, null=True)
    image = S3DirectField(dest='user-profile-images', blank=True, null=True)

    # location info
    country = CountryField(blank=True, null=True, blank_label='Select country')
    city = models.CharField(max_length=1000, blank=True, null=True)
    postcode = models.CharField(max_length=120, blank=True, null=True)
    location = models.PointField(blank=True, null=True)

    # professional info
    position = models.CharField(max_length=1000, blank=True, null=True)
    usertype = models.IntegerField(
        choices=USER_TYPE_CHOICES,
        default=MARKETER,
    )
    bio = models.TextField(max_length=10000, blank=True, null=True)
    cause_name = models.CharField(max_length=1000, blank=True, null=True)

    # social accounts
    twitter = models.URLField(max_length=1000, blank=True, null=True)
    linkedin = models.URLField(max_length=1000, blank=True, null=True)
    website = models.URLField(max_length=1000, blank=True, null=True)

    featured = models.BooleanField(default=False)
    # storing old geo data
    geo_data = models.TextField(max_length=300, blank=True, null=True)
    has_reactivated = models.BooleanField(default=False)

    def __str__(self):
        if (self.usertype == self.CAUSE):
            return '%s' % (self.cause_name)
        else:
            return '%s %s' % (self.surname, self.name)

    def save(self, **kwargs):
        if (self.usertype == self.CAUSE and not self.cause_name):
            raise ValidationError("Invalid value: Cause name is required",
                                  code='invalid')

        super(PimpUser, self).save(**kwargs)

    @property
    def is_admin(self):
        return self.usertype in [PimpUser.ADMIN]

    @property
    def is_marketer(self):
        return self.usertype in [PimpUser.MARKETER]

    @property
    def is_cause(self):
        return self.usertype in [PimpUser.CAUSE]

    @property
    def is_geolocated(self):
        if (not self.location):
            return False
        else:
            return True
Exemple #20
0
class Location(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    localization = models.PointField(srid=4326, )
    elevation = models.FloatField(default=0.0)
Exemple #21
0
class Earthquake(BaseEventModel):
    """Earthquake model."""

    INITIAL_SOURCE_TYPE = 'initial'
    CORRECTED_SOURCE_TYPE = 'corrected'

    class Meta:
        """Meta class."""
        app_label = 'realtime'
        unique_together = (('shake_id', 'source_type'), )
        ordering = ['-time', '-shake_id', '-source_type']

    # Shake ID of corrected shakemaps can go as far as:
    # 20180316015829_52_-6050_142170_20180316015829
    shake_id = models.CharField(
        verbose_name=_('The Shake ID'),
        help_text=_('The Shake ID, which represents the time of the event.'),
        max_length=50,
        blank=False)
    shake_grid = models.FileField(verbose_name=_('Shake Grid XML File'),
                                  help_text=_('The Shake Grid to process'),
                                  upload_to='earthquake/grid',
                                  blank=True,
                                  null=True)
    shake_grid_xml = models.TextField(
        verbose_name=_('Shake Grid XML File Contents'),
        help_text=_('The content of shake grid file'),
        blank=True,
        null=True)
    mmi_output = models.FileField(
        verbose_name=_('MMI related file zipped'),
        help_text=_('MMI related file, layers, and data, zipped.'),
        upload_to='earthquake/mmi_output',
        blank=True,
        null=True)
    mmi_output_path = models.CharField(
        verbose_name=_('MMI related file path'),
        help_text=_('MMI related file path location'),
        max_length=255,
        blank=True,
        null=True,
        default=None)
    magnitude = models.FloatField(verbose_name=_('The magnitude'),
                                  help_text=_('The magnitude of the event.'))
    time = models.DateTimeField(verbose_name=_('Date and Time'),
                                help_text=_('The time the shake happened.'),
                                blank=False)
    generated_time = models.DateTimeField(
        verbose_name=_('Report Generated Date and Time'),
        help_text=_('The time the shake report generated.'),
        blank=True,
        null=True,
        default=None)
    depth = models.FloatField(
        verbose_name=_('The depth'),
        help_text=_('The depth of the event in km unit.'))
    location = models.PointField(
        verbose_name=_('Location'),
        help_text=_(
            'The location of the shake event in longitude and latitude.'),
        srid=4326,
        max_length=255,
        null=False,
        blank=False)
    location_description = models.CharField(
        verbose_name=_('Location Description'),
        help_text=_('The description of the location e.g "Bali".'),
        max_length=255)
    felt = models.BooleanField(
        verbose_name=_('Felt Earthquake'),
        help_text=_("Set to True if this particular event showed up as felt "
                    "Earthquake in BMKG's List"),
        default=False)
    source_type = models.CharField(verbose_name=_('Source Type'),
                                   help_text=_('Source type of shake grid'),
                                   max_length=30,
                                   default='initial')
    has_corrected = models.BooleanField(verbose_name=_(
        'Cache flag to tell that this shakemap has a corrected version.'),
                                        default=False)
    mmi_layer_saved = models.BooleanField(verbose_name=_(
        'Cache flag to tell that this shakemap already saved its '
        'contours.'),
                                          default=False)
    shake_grid_saved = models.BooleanField(
        verbose_name=_('Cache flag to tell that shakemap grid already saved.'),
        default=False)

    objects = EarthquakeManager()

    def __unicode__(self):
        shake_string = u'Shake event [{0}]'.format(self.event_id_formatted)
        if self.location_description.strip():
            shake_string += u' in {0}'.format(self.location_description)
        return shake_string

    @property
    def reports_queryset(self):
        return self.reports

    @property
    def report_class(self):
        return EarthquakeReport

    def delete(self, using=None):
        # delete all report
        if self.shake_grid:
            self.shake_grid.delete()
        if self.mmi_output:
            self.mmi_output.delete()
        for report in self.reports.all():
            report.delete(using=using)
        super(Earthquake, self).delete(using=using)

    def mark_shakemaps_has_corrected(self):
        """Mark cache flag of has_corrected.
        This is to tell that this shakemaps have shakemaps corrected.
        """
        # Only for initial shakemaps
        if self.source_type == self.INITIAL_SOURCE_TYPE:
            has_corrected = bool(self.corrected_shakemaps)
            Earthquake.objects.filter(id=self.id).update(
                has_corrected=has_corrected)

    def mark_shakemaps_has_contours(self, layer_saved=False):
        """Mark cache flag of mmi_layer_saved.
        This is to tell that this shakemaps have contours saved in database.
        """
        if layer_saved:
            mmi_layer_saved = layer_saved
        else:
            mmi_layer_saved = bool(self.contours.all().count() > 0)
        Earthquake.objects.filter(id=self.id).update(
            mmi_layer_saved=mmi_layer_saved)

    @property
    def shake_grid_exists(self):
        return bool(self.shake_grid or self.shake_grid_saved)

    @property
    def mmi_layer_exists(self):
        """Return bool to indicate existences of impact layers"""
        if self.impact_file_path:
            return os.path.exists(self.mmi_output_path)
        return False

    @property
    def analysis_zip_path(self):
        """Return analysis zip path for download."""
        dirname = os.path.dirname(self.impact_file_path)
        basename = os.path.basename(self.impact_file_path)
        basename_without_ext = split_layer_ext(basename)[0]
        zip_path = os.path.join(dirname, basename_without_ext + '.zip')
        if os.path.exists(zip_path):
            return zip_path
        return None

    @property
    def shake_grid_download_url(self):
        return reverse('realtime:shake_grid',
                       kwargs={
                           'shake_id': self.shake_id,
                           'source_type': self.source_type
                       })

    @property
    def mmi_layer_download_url(self):
        return reverse('realtime:earthquake_mmi_contours_list',
                       kwargs={
                           'shake_id': self.shake_id,
                           'source_type': self.source_type
                       })

    @property
    def analysis_zip_download_url(self):
        return reverse('realtime:analysis_zip',
                       kwargs={
                           'shake_id': self.shake_id,
                           'source_type': self.source_type
                       })

    @property
    def event_id_formatted(self):
        return EARTHQUAKE_EVENT_ID_FORMAT.format(shake_id=self.shake_id,
                                                 source_type=self.source_type)

    @property
    def grid_xml_filename(self):
        return '{event_id_formatted}-grid.xml'.format(
            event_id_formatted=self.event_id_formatted)

    @property
    def mmi_layer_filename(self):
        return '{event_id_formatted}-mmi.geojson'.format(
            event_id_formatted=self.event_id_formatted)

    def shakemaps_matching_queryset(self, source_type):
        """Return a proper queryset match to retrieve matching shakemaps."""
        # return a combination of querysets

        # Find exact info match
        exact_combination_match = Earthquake.objects.filter(
            time=self.time,
            location=self.location,
            magnitude=self.magnitude,
            source_type=source_type)

        if exact_combination_match:
            return exact_combination_match

        # Find exact time match
        exact_time_match = Earthquake.objects.filter(time=self.time,
                                                     source_type=source_type)

        return exact_time_match

        # The following section were commented out until we have a proper
        # algorithm

        # # find a range of shakemaps in a given range, sorted with:
        # # - least time diff
        # # - least magnitude diff
        # # - least location diff
        #
        # # it is difficult to have an absolute time diff using sql alone, so
        # # will try to find the match using date range
        # # Use a maximum of an hour difference
        # delta_time = datetime.timedelta(minutes=30)
        # end_time = self.time + delta_time
        # start_time = self.time - delta_time
        #
        # # A range of 1 MMI
        # magnitude_delta = 1
        # # A range of 10 km
        # distance_delta = 10000
        #
        # within_time_range_with_location_match = Earthquake.objects\
        #     .filter(
        #         time__range=[start_time, end_time],
        #         source_type=self.CORRECTED_SOURCE_TYPE)\
        #     .annotate(
        #         # add magnitude diff
        #         magnitude_diff=Func(
        #             F('magnitude') - self.magnitude,
        #             function='ABS'))\
        #     .distance(self.location)\
        #     .filter(
        #         magnitude_diff__lte=magnitude_delta,
        #         distance__lte=distance_delta
        #     )\
        #     .order_by('-time', 'distance', 'magnitude_diff')
        #
        # return within_time_range_with_location_match

    def corrected_shakemaps_queryset(self):
        """Find a corrected shakemaps matching this one."""
        return self.shakemaps_matching_queryset(self.CORRECTED_SOURCE_TYPE)

    def initial_shakemaps_queryset(self):
        """Find initial shakemaps matching this one."""
        return self.shakemaps_matching_queryset(self.INITIAL_SOURCE_TYPE)

    @property
    def corrected_shakemaps(self):
        """Return the corrected version of the shakemaps if any."""
        if self.source_type == self.CORRECTED_SOURCE_TYPE:
            # Not Applicable
            return None

        # Return only the latest one
        return self.corrected_shakemaps_queryset().order_by(
            '-shake_id').first()

    @property
    def initial_shakemaps(self):
        """Return the initial version of the shakemaps if any."""
        if self.source_type == self.INITIAL_SOURCE_TYPE:
            # Not Applicable
            return None

        # There should be only one
        return self.initial_shakemaps_queryset().first()
Exemple #22
0
class CampusLocation(models.Model):
    """
    A general location of the campus
    """
    street_address = models.CharField(max_length=240)
    additional_address = models.CharField(
        max_length=240, blank=True, help_text="Apartment or Suite Number")
    locality = models.CharField(
        help_text="The city or municipality of the campus", max_length=240)
    region = models.CharField(
        help_text="State or Province of the campus (Abbreviation preffered)",
        max_length=100)
    telephone = models.CharField(help_text="Phone number of the campus",
                                 max_length=50,
                                 blank=True)
    zip_code = models.CharField(help_text="Zip or Postal Code of the campus",
                                max_length=10,
                                blank=True)

    lat = models.FloatField(blank=True, null=True)
    lon = models.FloatField(blank=True, null=True)
    point = models.PointField(blank=True, null=True)

    objects = models.GeoManager()

    def __str__(self):
        return "{0} \n {1}, {2}".format(self.street_address, self.locality,
                                        self.region)

    def save(self, *args, **kwargs):
        if self.point is None:
            from haystack.utils.geo import Point
            if self.lon is not None and self.lat is not None:
                self.point = Point(self.lon, self.lat)
            elif self.full_address != "":
                try:
                    from geopy.geocoders import GoogleV3
                    geolocator = GoogleV3()
                    try:
                        lat, lon = geolocator.geocode(self.full_address)[1]
                        self.lat = lat
                        self.lon = lon
                        self.point = Point(lon, lat)
                    except IndexError:
                        pass
                except Exception:
                    pass

            # TODO: else with the street address and geo encoder via google or something
        super(CampusLocation, self).save(*args, **kwargs)

    @property
    def full_address(self):
        ctx = {
            'street_address': self.street_address,
            'additional_address': self.additional_address,
            'locality': self.locality,
            'region': self.region,
            'zip_code': self.zip_code,
        }
        full_address = """
        {street_address} {additional_address}, {locality}, {region}, {zip_code}
        """.format(**ctx)
        return full_address
Exemple #23
0
class TaxLotState(models.Model):
    # The state field names should match pretty close to the pdf, just
    # because these are the most 'public' fields in terms of
    # communicating with the cities.

    # Support finding the property by the import_file
    import_file = models.ForeignKey(ImportFile,
                                    on_delete=models.CASCADE,
                                    null=True,
                                    blank=True)

    # Add organization to the tax lot states
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
    data_state = models.IntegerField(choices=DATA_STATE,
                                     default=DATA_STATE_UNKNOWN)
    merge_state = models.IntegerField(choices=MERGE_STATE,
                                      default=MERGE_STATE_UNKNOWN,
                                      null=True)

    custom_id_1 = models.CharField(max_length=255, null=True, blank=True)

    jurisdiction_tax_lot_id = models.CharField(max_length=2047,
                                               null=True,
                                               blank=True)
    block_number = models.CharField(max_length=255, null=True, blank=True)
    district = models.CharField(max_length=255, null=True, blank=True)
    address_line_1 = models.CharField(max_length=255, null=True, blank=True)
    address_line_2 = models.CharField(max_length=255, null=True, blank=True)
    normalized_address = models.CharField(max_length=255,
                                          null=True,
                                          blank=True,
                                          editable=False)

    city = models.CharField(max_length=255, null=True, blank=True)
    state = models.CharField(max_length=255, null=True, blank=True)
    postal_code = models.CharField(max_length=255, null=True, blank=True)
    number_properties = models.IntegerField(null=True, blank=True)

    extra_data = JSONField(default=dict, blank=True)
    hash_object = models.CharField(max_length=32,
                                   null=True,
                                   blank=True,
                                   default=None)

    # taxlots can now have lat/long and polygons, points.
    latitude = models.FloatField(null=True, blank=True)
    longitude = models.FloatField(null=True, blank=True)
    long_lat = geomodels.PointField(geography=True, null=True, blank=True)
    centroid = geomodels.PolygonField(geography=True, null=True, blank=True)
    bounding_box = geomodels.PolygonField(geography=True,
                                          null=True,
                                          blank=True)
    taxlot_footprint = geomodels.PolygonField(geography=True,
                                              null=True,
                                              blank=True)
    # A unique building identifier as defined by DOE's UBID project (https://buildingid.pnnl.gov/)
    # Note that ulid is not an actual project at the moment, but it is similar to UBID in that it
    # is a unique string that represents the bounding box of the Land (or Lot)
    ulid = models.CharField(max_length=255, null=True, blank=True)

    geocoding_confidence = models.CharField(max_length=32,
                                            null=True,
                                            blank=True)

    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    class Meta:
        index_together = [['hash_object'], ['import_file', 'data_state'],
                          ['import_file', 'data_state', 'merge_state']]

    def __str__(self):
        return 'TaxLot State - %s' % self.pk

    def promote(self, cycle):
        """
            Promote the TaxLotState to the view table for the given cycle

            Args:
                cycle: Cycle to assign the view

            Returns:
                The resulting TaxLotView (note that it is not returning the
                TaxLotState)

        """
        # First check if the cycle and the PropertyState already have a view
        tlvs = TaxLotView.objects.filter(cycle=cycle, state=self)

        if len(tlvs) == 0:
            # _log.debug("Found 0 TaxLotViews, adding TaxLot, promoting")
            # There are no PropertyViews for this property state and cycle.
            # Most likely there is nothing to match right now, so just
            # promote it to the view

            # Need to create a property for this state
            if self.organization is None:
                _log.error("organization is None")

            taxlot = TaxLot.objects.create(organization=self.organization)

            tlv = TaxLotView.objects.create(taxlot=taxlot,
                                            cycle=cycle,
                                            state=self)

            # This is legacy but still needed here to have the tests pass.
            self.data_state = DATA_STATE_MATCHING

            self.save()

            return tlv
        elif len(tlvs) == 1:
            # _log.debug("Found 1 PropertyView... Nothing to do")
            # PropertyView already exists for cycle and state. Nothing to do.

            return tlvs[0]
        else:
            _log.error("Found %s PropertyView" % len(tlvs))
            _log.error("This should never occur, famous last words?")

            return None

    def to_dict(self, fields=None, include_related_data=True):
        """
        Returns a dict version of the TaxLotState, either with all fields
        or masked to just those requested.
        """

        # TODO: make this a serializer and/or merge with PropertyState.to_dict
        if fields:
            model_fields, ed_fields = split_model_fields(self, fields)
            extra_data = self.extra_data
            ed_fields = list(filter(lambda f: f in extra_data, ed_fields))

            result = {field: getattr(self, field) for field in model_fields}
            result['extra_data'] = {
                field: extra_data[field]
                for field in ed_fields
            }

            # always return id's
            result['id'] = result['pk'] = self.pk

            return result

        d = obj_to_dict(self, include_m2m=include_related_data)

        return d

    def save(self, *args, **kwargs):
        # Calculate and save the normalized address
        if self.address_line_1 is not None:
            self.normalized_address = normalize_address_str(
                self.address_line_1)
        else:
            self.normalized_address = None

        # save a hash of the object to the database for quick lookup
        from seed.data_importer.tasks import hash_state_object
        self.hash_object = hash_state_object(self)
        return super().save(*args, **kwargs)

    def history(self):
        """
        Return the history of the taxlot state by parsing through the auditlog. Returns only the ids
        of the parent states and some descriptions.

              master
              /    \
             /      \
          parent1  parent2

        In the records, parent2 is most recent, so make sure to navigate parent two first since we
        are returning the data in reverse over (that is most recent changes first)

        :return: list, history as a list, and the master record
        """
        """Return history in reverse order."""
        history = []
        master = {
            'state_id': self.id,
            'state_data': self,
            'date_edited': None,
        }

        def record_dict(log):
            filename = None if not log.import_filename else path.basename(
                log.import_filename)
            if filename:
                # Attempt to remove NamedTemporaryFile suffix
                name, ext = path.splitext(filename)
                pattern = re.compile('(.*?)(_[a-zA-Z0-9]{7})$')
                match = pattern.match(name)
                if match:
                    filename = match.groups()[0] + ext
            return {
                'state_id': log.state.id,
                'state_data': log.state,
                'date_edited': convert_to_js_timestamp(log.created),
                'source': log.get_record_type_display(),
                'filename': filename,
                # 'changed_fields': json.loads(log.description) if log.record_type == AUDIT_USER_EDIT else None
            }

        log = TaxLotAuditLog.objects.select_related(
            'state', 'parent1',
            'parent2').filter(state_id=self.id).order_by('-id').first()

        if log:
            master = {
                'state_id': log.state.id,
                'state_data': log.state,
                'date_edited': convert_to_js_timestamp(log.created),
            }

            # Traverse parents and add to history
            if log.name in [
                    'Manual Match', 'System Match',
                    'Merge current state in migration'
            ]:
                done_searching = False

                while not done_searching:
                    # if there is no parents, then break out immediately
                    if (log.parent1_id is None and log.parent2_id is None
                        ) or log.name == 'Manual Edit':
                        break

                    # initalize the tree to None everytime. If not new tree is found, then we will not iterate
                    tree = None

                    # Check if parent2 has any other parents or is the original import creation. Start with parent2
                    # because parent2 will be the most recent import file.
                    if log.parent2:
                        if log.parent2.name in [
                                'Import Creation', 'Manual Edit'
                        ]:
                            record = record_dict(log.parent2)
                            history.append(record)
                        elif log.parent2.name == 'System Match' and log.parent2.parent1.name == 'Import Creation' and log.parent2.parent2.name == 'Import Creation':
                            # Handle case where an import file matches within itself, and proceeds to match with
                            # existing records
                            record = record_dict(log.parent2.parent2)
                            history.append(record)
                            record = record_dict(log.parent2.parent1)
                            history.append(record)
                        else:
                            tree = log.parent2

                    if log.parent1:
                        if log.parent1.name in [
                                'Import Creation', 'Manual Edit'
                        ]:
                            record = record_dict(log.parent1)
                            history.append(record)
                        elif log.parent1.name == 'System Match' and log.parent1.parent1.name == 'Import Creation' and log.parent1.parent2.name == 'Import Creation':
                            # Handle case where an import file matches within itself, and proceeds to match with
                            # existing records
                            record = record_dict(log.parent1.parent2)
                            history.append(record)
                            record = record_dict(log.parent1.parent1)
                            history.append(record)
                        else:
                            tree = log.parent1

                    if not tree:
                        done_searching = True
                    else:
                        log = tree
            elif log.name == 'Manual Edit':
                record = record_dict(log.parent1)
                history.append(record)
            elif log.name == 'Import Creation':
                record = record_dict(log)
                history.append(record)

        return history, master

    @classmethod
    def coparent(cls, state_id):
        """
        Return the coparent of the TaxLotState. This will query the TaxLotAuditLog table to
        determine if there is a coparent and return it if it is found. The state_id needs to be
        the base ID of when the original record was imported

        :param state_id: integer, state id to find coparent.
        :return: dict
        """

        coparents = list(
            TaxLotState.objects.raw(
                """
                    WITH creation_id AS (
                        SELECT
                          pal.id,
                          pal.state_id AS original_state_id
                        FROM seed_taxlotauditlog pal
                        WHERE pal.state_id = %s AND
                              pal.name = 'Import Creation' AND
                              pal.import_filename IS NOT NULL
                    ), audit_id AS (
                        SELECT
                          audit_log.id,
                          audit_log.state_id,
                          audit_log.parent1_id,
                          audit_log.parent2_id,
                          audit_log.parent_state1_id,
                          audit_log.parent_state2_id,
                          cid.original_state_id
                        FROM creation_id cid, seed_taxlotauditlog audit_log
                        WHERE audit_log.parent1_id = cid.id OR audit_log.parent2_id = cid.id
                    )
                    SELECT
                      ps.id,
                      ps.custom_id_1,
                      ps.block_number,
                      ps.district,
                      ps.address_line_1,
                      ps.address_line_2,
                      ps.city,
                      ps.state,
                      ps.postal_code,
                      ps.extra_data,
                      ps.number_properties,
                      ps.jurisdiction_tax_lot_id,
                      ps.geocoding_confidence,
                      NULL
                    FROM seed_taxlotstate ps, audit_id aid
                    WHERE (ps.id = aid.parent_state1_id AND
                           aid.parent_state1_id <> aid.original_state_id) OR
                          (ps.id = aid.parent_state2_id AND
                           aid.parent_state2_id <> aid.original_state_id);""",
                [int(state_id)]))

        # reduce this down to just the fields that were returns and convert to dict. This is
        # important because the fields that were not queried will be deferred and require a new
        # query to retrieve.
        keep_fields = [
            'id', 'custom_id_1', 'jurisdiction_tax_lot_id', 'block_number',
            'district', 'address_line_1', 'address_line_2', 'city', 'state',
            'postal_code', 'number_properties', 'extra_data'
        ]
        coparents = [{key: getattr(c, key)
                      for key in keep_fields} for c in coparents]

        return coparents, len(coparents)

    @classmethod
    def merge_relationships(cls, merged_state, state1, state2):
        """Stub to implement if merging TaxLotState relationships is needed"""
        return None
class Place(models.Model):
    name = models.TextField()
    place_id = models.TextField(primary_key=True)
    lat = models.FloatField()
    lng = models.FloatField()
    user_rating = models.FloatField()
    num_ratings = models.FloatField()
    address = models.TextField()
    area = models.ForeignKey(to='Area',
                             null=True,
                             blank=True,
                             on_delete=models.SET_NULL)
    email_contact = models.EmailField(null=True, blank=True)
    place_url = models.URLField(null=True, blank=True, max_length=1000)
    image_url = models.URLField(null=True, blank=True, max_length=1000)
    image_attribution = models.TextField(null=True, blank=True)
    gift_card_url = models.URLField(null=True, blank=True, max_length=1000)
    takeout_url = models.URLField(null=True, blank=True, max_length=1000)
    donation_url = models.URLField(null=True, blank=True, max_length=1000)
    geom = models.PointField(srid=4326, null=True, blank=True)
    place_types = models.TextField(null=True, blank=True)

    @classmethod
    def dump_names_for_site(cls, out_fl):
        all_places = cls.objects.all()
        output = []
        for place in all_places:
            info = (
                """{{key: "{place_id}", address: "{address}", name: "{name}"}},"""
                .format(name=place.name,
                        address=place.get_short_address(),
                        place_id=place.place_id))
            output.append(info)
        with open(out_fl, 'w') as fl:
            fl.writelines(output)

    @classmethod
    def dump_places_missing_photos(cls, out_fl):
        missing_photo = cls.objects.filter(image_url=None)
        names = ['%s\n' % place.place_id for place in missing_photo]
        with open(out_fl, 'w') as fl:
            fl.writelines(names)

    @classmethod
    def dump_places_missing_website(cls, out_fl):
        missing_photo = cls.objects.filter(place_url=None)
        names = ['%s\n' % place.place_id for place in missing_photo]
        with open(out_fl, 'w') as fl:
            fl.writelines(names)

    def get_image_url(self):
        return self.image_url or "http://TODO/placeholder"

    def get_collage_picture(self):
        from places.helper import get_place_collage_picture
        filename = get_place_collage_picture(self.place_id)
        return filename

    def get_short_address(self):
        return self.address.split(', CA')[0]

    def to_json(self):
        return {
            'name': self.name,
            'address': self.get_short_address(),
            'giftCardURL': self.gift_card_url,
            'takeoutURL': self.takeout_url,
            'donationURL': self.donation_url,
            'placeURL': self.place_url,
            'emailContact': self.email_contact,
            'imageURL': self.get_image_url(),
            'placeID': self.place_id,
            'area': self.area.key if self.area else None
        }

    def to_typeahead_json(self):
        return {
            'name': self.name,
            'address': self.get_short_address(),
            'key': self.place_id,
            'image_attribution': self.image_attribution
        }

    def __str__(self):
        return '%s (%s)' % (self.name, self.address)

    def save(self, *args, **kwargs):
        from places.helper import check_link_against_blacklist
        if self.gift_card_url and not check_link_against_blacklist(
                self.gift_card_url):
            raise Exception("Bad Link Saved")
        if (self.lat and self.lng):
            self.geom = Point([float(x) for x in (self.lng, self.lat)],
                              srid=4326)
        super(self.__class__, self).save(*args, **kwargs)
 class MinusOneSRID(models.Model):
     geom = models.PointField(srid=-1)  # Minus one SRID.
     objects = models.GeoManager()
class Neighborhood(models.Model):
    name = models.TextField()
    key = models.TextField(primary_key=True)
    places = models.ManyToManyField(through='NeighborhoodEntry', to='Place')
    lat = models.FloatField()
    lng = models.FloatField()
    geom = models.PointField(srid=4326, null=True)
    bounds = models.PolygonField(srid=4326, null=True, blank=True)
    photo_url = models.URLField(blank=True, null=True, max_length=1000)
    photo_attribution = models.TextField(blank=True, null=True)
    area = models.ForeignKey(to='Area',
                             on_delete=models.SET_NULL,
                             blank=True,
                             null=True)
    rank = models.IntegerField(null=True, blank=True)

    def place_list(self, limit, offset):
        hardcoded = [
            x.place for x in NeighborhoodEntry.objects.filter(
                neighborhood=self).order_by('rank')
        ]
        if offset == 0:
            to_fetch = (limit - len(hardcoded)) + 1
        else:
            to_fetch = limit + 1
        if self.bounds:
            close_by = Place.objects.filter(
                Q(geom__within=self.bounds)
            ).annotate(has_card=models.Count('gift_card_url')).annotate(
                has_donation=models.Count('donation_url')).annotate(
                    has_takeout=models.Count('takeout_url')).exclude(
                        place_id__in=[x.place_id for x in hardcoded]).order_by(
                            '-has_card', '-has_takeout', '-has_donation',
                            '-num_ratings')[offset:offset + to_fetch]
        else:
            close_by = Place.objects.filter(
                Q(geom__distance_lt=(self.geom, D(m=2500)))
            ).exclude(place_id__in=[x.place_id for x in hardcoded]).annotate(
                has_card=models.Count('gift_card_url')).annotate(
                    has_donation=models.Count('donation_url')).annotate(
                        has_takeout=models.Count('takeout_url')).annotate(
                            distance=Distance('geom', self.geom)).order_by(
                                '-has_card', '-has_takeout', '-has_donation',
                                'distance')[offset:offset + to_fetch]
        more_available = len(close_by) == to_fetch
        if offset == 0:
            joined = (hardcoded + list(close_by))
        else:
            joined = list(close_by)
        end_list = -1 if more_available else len(joined)
        return joined[0:end_list], more_available

    def to_json(self):
        return {"name": self.name, "key": self.key, "image": self.photo_url}

    def save(self, *args, **kwargs):
        if (self.lat and self.lng):
            self.geom = Point([float(x) for x in (self.lng, self.lat)],
                              srid=4326)

        super(self.__class__, self).save(*args, **kwargs)
class Alert(models.Model):
    timestamp = models.DateTimeField(default=timezone.now)
    geolocation = models.PointField(dim=2)
    active = models.BooleanField(default=True)
class TrafficSignReal(SourceControlModel, SoftDeleteModel, UserControlModel):
    id = models.UUIDField(primary_key=True,
                          unique=True,
                          editable=False,
                          default=uuid.uuid4)
    traffic_sign_plan = models.ForeignKey(
        TrafficSignPlan,
        verbose_name=_("Traffic Sign Plan"),
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )
    location = models.PointField(_("Location (3D)"), dim=3, srid=settings.SRID)
    height = models.IntegerField(_("Height"), blank=True, null=True)
    direction = models.IntegerField(_("Direction"), default=0)
    device_type = models.ForeignKey(
        TrafficControlDeviceType,
        verbose_name=_("Device type"),
        on_delete=models.PROTECT,
        limit_choices_to=Q(
            Q(target_model=None)
            | Q(target_model=DeviceTypeTargetModel.TRAFFIC_SIGN)),
        blank=False,
        null=True,
    )
    value = models.IntegerField(_("Traffic Sign Code value"),
                                blank=True,
                                null=True)
    legacy_code = models.CharField(_("Legacy Traffic Sign Code"),
                                   max_length=32,
                                   blank=True,
                                   null=True)
    txt = models.CharField(_("Txt"), max_length=254, blank=True, null=True)
    mount_real = models.ForeignKey(
        MountReal,
        verbose_name=_("Mount Real"),
        on_delete=models.PROTECT,
        blank=True,
        null=True,
    )
    mount_type = models.ForeignKey(
        MountType,
        verbose_name=_("Mount type"),
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
    )
    installation_date = models.DateField(_("Installation date"),
                                         blank=True,
                                         null=True)
    installation_status = EnumField(
        InstallationStatus,
        verbose_name=_("Installation status"),
        max_length=10,
        blank=True,
        null=True,
    )
    installation_id = models.CharField(_("Installation id"),
                                       max_length=254,
                                       blank=True,
                                       null=True)
    installation_details = models.CharField(_("Installation details"),
                                            max_length=254,
                                            blank=True,
                                            null=True)
    permit_decision_id = models.CharField(_("Permit decision id"),
                                          max_length=254,
                                          blank=True,
                                          null=True)
    validity_period_start = models.DateField(_("Validity period start"),
                                             blank=True,
                                             null=True)
    validity_period_end = models.DateField(_("Validity period end"),
                                           blank=True,
                                           null=True)
    condition = EnumIntegerField(
        Condition,
        verbose_name=_("Condition"),
        blank=True,
        null=True,
    )
    affect_area = models.PolygonField(_("Affect area (2D)"),
                                      srid=settings.SRID,
                                      blank=True,
                                      null=True)
    scanned_at = models.DateTimeField(_("Scanned at"), blank=True, null=True)
    size = EnumField(
        Size,
        verbose_name=_("Size"),
        max_length=1,
        blank=True,
        null=True,
    )
    reflection_class = EnumField(
        Reflection,
        verbose_name=_("Reflection"),
        max_length=2,
        blank=True,
        null=True,
    )
    surface_class = EnumField(
        Surface,
        verbose_name=_("Surface"),
        max_length=6,
        blank=True,
        null=True,
    )
    seasonal_validity_period_start = models.DateField(
        _("Seasonal validity period start"), blank=True, null=True)
    seasonal_validity_period_end = models.DateField(
        _("Seasonal validity period end"), blank=True, null=True)
    owner = models.ForeignKey(
        "traffic_control.Owner",
        verbose_name=_("Owner"),
        blank=False,
        null=False,
        on_delete=models.PROTECT,
    )
    manufacturer = models.CharField(_("Manufacturer"),
                                    max_length=254,
                                    blank=True,
                                    null=True)
    rfid = models.CharField(_("RFID"), max_length=254, blank=True, null=True)
    lifecycle = EnumIntegerField(Lifecycle,
                                 verbose_name=_("Lifecycle"),
                                 default=Lifecycle.ACTIVE)
    road_name = models.CharField(_("Road name"),
                                 max_length=254,
                                 blank=True,
                                 null=True)
    lane_number = EnumField(LaneNumber,
                            verbose_name=_("Lane number"),
                            default=LaneNumber.MAIN_1,
                            blank=True)
    lane_type = EnumField(
        LaneType,
        verbose_name=_("Lane type"),
        default=LaneType.MAIN,
        blank=True,
    )
    location_specifier = EnumIntegerField(
        LocationSpecifier,
        verbose_name=_("Location specifier"),
        default=LocationSpecifier.RIGHT,
        blank=True,
        null=True,
    )
    operation = models.CharField(_("Operation"),
                                 max_length=64,
                                 blank=True,
                                 null=True)
    attachment_url = models.URLField(_("Attachment url"),
                                     max_length=500,
                                     blank=True,
                                     null=True)

    objects = TrafficSignRealQuerySet.as_manager()

    class Meta:
        db_table = "traffic_sign_real"
        verbose_name = _("Traffic Sign Real")
        verbose_name_plural = _("Traffic Sign Reals")
        unique_together = ["source_name", "source_id"]

    def __str__(self):
        return f"{self.id} {self.device_type}"

    def save(self, *args, **kwargs):
        if self.device_type and not self.device_type.validate_relation(
                DeviceTypeTargetModel.TRAFFIC_SIGN):
            raise ValidationError(
                f'Device type "{self.device_type}" is not allowed for traffic signs'
            )

        if not self.device_type:
            self.device_type = (
                TrafficControlDeviceType.objects.for_target_model(
                    DeviceTypeTargetModel.TRAFFIC_SIGN).filter(
                        legacy_code=self.legacy_code).order_by("code").first())

        super().save(*args, **kwargs)

    def has_additional_signs(self):
        return self.additional_signs.active().exists()

    @transaction.atomic
    def soft_delete(self, user):
        super().soft_delete(user)
        self.additional_signs.soft_delete(user)
Exemple #29
0
class Powerplant(models.Model):
    """Power plants (status quo)

    Attributes
    ----------
    id :
        DB id
    ags :
        Municipality key (Amtlicher Gemeindeschlüssel),
        refers to :class:`stemp_abw.models.RegMun`
    capacity :
        Nominal power in MW
    chp :
        Indicates if plant is of type CHP (combined heat and power)
    com_month :
        Month of commissioning
    com_year :
        Year of commissioning
    comment :
        Comment
    decom_month :
        Month of decommissioning
    decom_year :
        Year of decommissioning
    efficiency :
        Efficiency
    energy_source_level_1 :
        Indicates if renewable or conventional
    energy_source_level_2 :
        Indicates energy source
    energy_source_level_3 :
        More specific energy source
    geometry : Geometry
        SRID: EPSG:4326 (WGS84)
    technology :
        Technology
    thermal_capacity :
        Nominal thermal nominal power, if applicable
    coastdat2 :
        No. of coastdat2 weather cell (reegis)
    capacity_in :
        Capacity of inflow
    federal_state :
        Abbreviation of federal state name (2 letters according to ISO
        3166-2:DE)

    Notes
    -----
    Most of the attributes correspond to the OPSD dataset, some were added by reegis.
    """
    id = models.BigIntegerField(primary_key=True)
    ags = models.ForeignKey(RegMun, on_delete=models.DO_NOTHING)
    capacity = models.FloatField(blank=True, null=True)
    chp = models.TextField(blank=True, null=True)
    com_month = models.FloatField(blank=True, null=True)
    com_year = models.FloatField(blank=True, null=True)
    comment = models.TextField(blank=True, null=True)
    decom_month = models.BigIntegerField(blank=True, null=True)
    decom_year = models.BigIntegerField(blank=True, null=True)
    efficiency = models.FloatField(blank=True, null=True)
    energy_source_level_1 = models.TextField(blank=True, null=True)
    energy_source_level_2 = models.TextField(blank=True, null=True)
    energy_source_level_3 = models.TextField(blank=True, null=True)
    geometry = geomodels.PointField(blank=True, null=True)
    state = models.TextField(blank=True, null=True)
    technology = models.TextField(blank=True, null=True)
    thermal_capacity = models.FloatField(blank=True, null=True)
    coastdat2 = models.FloatField(blank=True, null=True)
    capacity_in = models.FloatField(blank=True, null=True)
    federal_state = models.TextField(blank=True, null=True)
Exemple #30
0
class City(NamedModel):
    point = models.PointField()