class AbstractFeature(models.Model): """The model class from which all feature objects derive""" name = models.CharField(max_length=140) description = models.CharField(max_length=300, blank=True) theme = models.ForeignKey(Theme, blank=True, null=True, on_delete=models.SET_NULL) banner_image = models.ImageField(upload_to=feature_directory_path, null=True, blank=True, verbose_name='Banner Image') banner_image_copyright = models.CharField(max_length=240, blank=True) popup_image = models.ImageField(upload_to=feature_directory_path, null=True, blank=True) popup_audio_title = models.CharField(max_length=128, blank=True) popup_audio_slug = models.SlugField(max_length=128, blank=True) popup_audio_file = FilerFileField( null=True, blank=True, related_name='%(app_label)s_%(class)s_popup_audio_file', on_delete=models.SET_NULL) weight = models.FloatField(default=1) tags = TaggableManager(blank=True) # When the feature is saved, the tags attached to it are stored as a string so they can be easily serialised as mapbox vector tiles tag_str = models.CharField(max_length=256, blank=True) published = models.BooleanField(default=False) def get_type(self): return self.__class__.__name__.lower() # The get_*_url functions build the urls which are used in the API representation of a feature def get_popup_image_url(self): if self.popup_image: return get_thumbnailer(self.popup_image)['site_small'].url else: return '' def get_popup_audio_file_url(self): if self.popup_audio_file: return self.popup_audio_file.url def get_banner_image_url(self): if self.banner_image: return get_thumbnailer(self.banner_image)['banner'].url else: return '' def get_document_count(self): if self.get_type() == 'point': return Document.objects.filter(point=self.id).count() elif self.get_type() == 'polygon': return Document.objects.filter(polygon=self.id).count() elif self.get_type() == 'line': return Document.objects.filter(line=self.id).count() def __str__(self): return self.name def get_absolute_url(self): feature_type = self.get_type() return '/?feature_type=' + feature_type + '&id=' + str(self.id) class Meta: abstract = True
class AbstractProfile(models.Model): registration_id = models.CharField(_('registration number'), max_length=255, blank=True) acquisition_date = models.DateField(_('acquisition date'), default=today) first_name = models.CharField(_('first name'), max_length=255) last_name = models.CharField(_('last name'), max_length=255) middle_name = models.CharField(_('middle name'), max_length=255, blank=True) gender = models.ForeignKey('hivs_utils.Gender', related_name='clients_profiles', verbose_name='gender', on_delete=models.SET_NULL, null=True) marital_status = models.ForeignKey('hivs_utils.MaritalStatus', related_name='clients_profiles', verbose_name='marital status', on_delete=models.SET_NULL, null=True, blank=True) birthdate = models.DateField(_('birthdate'), blank=True, null=True) phone = PhoneNumberField(_('phone number'), blank=True) other_phones = ArrayField(PhoneNumberField(), blank=True, default=list, verbose_name=_('other phones')) email = models.EmailField(_('email'), blank=True) education_level = models.ForeignKey('hivs_utils.EducationLevel', related_name='clients_profiles', verbose_name='education level', on_delete=models.SET_NULL, null=True, blank=True) occupation = models.ForeignKey('hivs_utils.Occupation', related_name='clients_profiles', verbose_name='occupation', on_delete=models.SET_NULL, null=True, blank=True) area = models.ForeignKey('hivs_administrative.Area', related_name='clients_profiles', verbose_name='administrative area', on_delete=models.SET_NULL, blank=True, null=True) street = models.ForeignKey('hivs_administrative.Street', related_name='clients_profiles', verbose_name='street', on_delete=models.SET_NULL, blank=True, null=True) timestamp = models.DateTimeField('Created at', auto_now_add=True) last_modified = models.DateTimeField(_('Last modified'), auto_now=True, null=True, blank=True) extras = JSONField(_('extras'), blank=True, default=dict) class Meta: verbose_name = _('Profile') verbose_name_plural = _('Profiles') abstract = True def __str__(self): return ' '.join( filter(None, [self.registration_id, self.first_name, self.last_name]))
class AppType(models.Model): name = models.CharField(max_length=200, unique=True) objects = AppTypeManager() def __str__(self): return self.name
class StopPoint(models.Model): """The smallest type of geographical point. A point at which vehicles stop""" atco_code = models.CharField(max_length=16, primary_key=True) naptan_code = models.CharField(max_length=16, db_index=True, blank=True) common_name = models.CharField(max_length=48) landmark = models.CharField(max_length=48, blank=True) street = models.CharField(max_length=48, blank=True) crossing = models.CharField(max_length=48, blank=True) indicator = models.CharField(max_length=48, blank=True) latlong = models.PointField(null=True) stop_area = models.ForeignKey(StopArea, models.SET_NULL, null=True, editable=False) locality = models.ForeignKey('Locality', models.SET_NULL, null=True, editable=False) suburb = models.CharField(max_length=48, blank=True) town = models.CharField(max_length=48, blank=True) locality_centre = models.NullBooleanField() places = models.ManyToManyField(Place, blank=True) heading = models.PositiveIntegerField(null=True, blank=True) BEARING_CHOICES = ( ('N', 'north'), ('NE', 'north-east'), ('E', 'east'), ('SE', 'south-east'), ('S', 'south'), ('SW', 'south-west'), ('W', 'west'), ('NW', 'north-west') ) bearing = models.CharField(max_length=2, choices=BEARING_CHOICES, blank=True) STOP_TYPE_CHOICES = ( ('AIR', 'Airport entrance'), ('GAT', 'Air airside area'), ('FTD', 'Ferry terminal/dock entrance'), ('FER', 'Ferry/dock berth area'), ('FBT', 'Ferry berth'), # ? ('RSE', 'Rail station entrance'), ('RLY', 'Rail platform access area'), ('RPL', 'Rail platform'), # ? ('TMU', 'Tram/metro/underground entrance'), ('MET', 'MET'), # ? ('PLT', 'Metro and underground platform access area'), ('BCE', 'Bus/coach station entrance'), ('BCS', 'Bus/coach bay/stand/stance within bus/coach station'), ('BCQ', 'Bus/coach bay'), # ? ('BCT', 'On street bus/coach/tram stop'), ('TXR', 'Taxi rank (head of)'), ('STR', 'Shared taxi rank (head of)'), ) stop_type = models.CharField(max_length=3, choices=STOP_TYPE_CHOICES, blank=True) BUS_STOP_TYPE_CHOICES = ( ('MKD', 'Marked (pole, shelter etc)'), ('HAR', 'Hail and ride'), ('CUS', 'Custom (unmarked, or only marked on road)'), ('FLX', 'Flexible zone'), ) bus_stop_type = models.CharField(max_length=3, choices=BUS_STOP_TYPE_CHOICES, blank=True) timing_status = models.CharField(max_length=3, choices=TIMING_STATUS_CHOICES, blank=True) admin_area = models.ForeignKey('AdminArea', models.SET_NULL, null=True, blank=True) active = models.BooleanField(db_index=True) osm = JSONField(null=True, blank=True) class Meta(): ordering = ('common_name', 'atco_code') def __str__(self): if self.indicator: return '%s (%s)' % (self.common_name, self.indicator) return self.common_name def get_heading(self): """Return the stop's bearing converted to degrees, for use with Google Street View.""" if self.heading: return self.heading headings = { 'N': 0, 'NE': 45, 'E': 90, 'SE': 135, 'S': 180, 'SW': 225, 'W': 270, 'NW': 315, } return headings.get(self.bearing) prepositions = { 'opp': 'opposite', 'adj': 'adjacent to', 'at': 'at', 'o/s': 'outside', 'nr': 'near', 'before': 'before', 'after': 'after', 'by': 'by', 'on': 'on', 'in': 'in', 'opposite': 'opposite', 'outside': 'outside', } def get_qualified_name(self, short=True): if self.locality: locality_name = self.locality.name.replace(' Town Centre', '') \ .replace(' City Centre', '') if short: locality_name = locality_name.replace('-next-the-Sea', '') \ .replace(' Next The Sea', '') \ .replace('North ', 'N ') \ .replace('East ', 'E ') \ .replace('South ', 'S ') \ .replace('West ', 'W ') if self.common_name in locality_name: return locality_name.replace(self.common_name, str(self)) # Cardiff Airport if slugify(locality_name) not in slugify(self.common_name): if self.indicator in self.prepositions: indicator = self.indicator if not short: indicator = self.prepositions[indicator] return '%s, %s %s' % (locality_name, indicator, self.common_name) return '%s %s' % (locality_name, self) elif self.town not in self.common_name: return '{} {}'.format(self.town, self) return str(self) def get_long_name(self): return self.get_qualified_name(short=False) def get_region(self): if self.admin_area_id: return self.admin_area.region return Region.objects.filter(service__stops=self).first() def get_absolute_url(self): return reverse('stoppoint_detail', args=(self.atco_code,)) def get_line_names(self): return [service.line_name for service in sorted(self.service_set.all(), key=Service.get_order)]
class Service(models.Model): """A bus service""" service_code = models.CharField(max_length=24, primary_key=True) line_name = models.CharField(max_length=64, blank=True) line_brand = models.CharField(max_length=64, blank=True) description = models.CharField(max_length=255, blank=True, db_index=True) outbound_description = models.CharField(max_length=255, blank=True) inbound_description = models.CharField(max_length=255, blank=True) slug = AutoSlugField(populate_from=str, editable=True, unique=True) mode = models.CharField(max_length=11) operator = models.ManyToManyField(Operator, blank=True) net = models.CharField(max_length=3, blank=True) line_ver = models.PositiveIntegerField(null=True, blank=True) region = models.ForeignKey(Region, models.CASCADE, null=True) stops = models.ManyToManyField(StopPoint, editable=False, through=StopUsage) date = models.DateField() current = models.BooleanField(default=True, db_index=True) show_timetable = models.BooleanField(default=False) timetable_wrong = models.BooleanField(default=False) geometry = models.MultiLineStringField(null=True, editable=False) wheelchair = models.NullBooleanField() low_floor = models.NullBooleanField() assistance_service = models.NullBooleanField() mobility_scooter = models.NullBooleanField() source = models.ForeignKey(DataSource, models.SET_NULL, null=True, blank=True) tracking = models.NullBooleanField() payment_methods = models.ManyToManyField('PaymentMethod', blank=True) class Meta(): ordering = ('service_code',) def __str__(self): if self.line_name or self.line_brand or self.description: parts = (self.line_name, self.line_brand, self.description) return ' - '.join(part for part in parts if part) return self.service_code def has_long_line_name(self): "Is this service's line_name more than 4 characters long?" return len(self.line_name) > 4 def get_a_mode(self): if self.mode and self.mode[0].lower() in 'aeiou': return 'An %s' % self.mode # 'An underground service' return 'A %s' % self.mode # 'A bus service' or 'A service' def get_absolute_url(self): return reverse('service_detail', args=(self.slug,)) def get_order(self): groups = SERVICE_ORDER_REGEX.match(self.line_name).groups() return (groups[0], int(groups[1]) if groups[1] else 0, groups[2]) @staticmethod def get_operator_number(code): if code in {'MEGA', 'MBGD'}: return '11' if code in {'NATX', 'NXSH', 'NXAP'}: return '12' return { 'BHAT': '41', 'ESYB': '53', 'WAIR': '20', 'TVSN': '18' }.get(code) def get_tfl_url(self): return 'https://tfl.gov.uk/bus/timetable/%s/' % self.line_name def get_trapeze_link(self, date): if self.region_id == 'Y': domain = 'yorkshiretravel.net' name = 'Yorkshire Travel' else: domain = 'travelinescotland.com' name = 'Traveline Scotland' if date: date = int(time.mktime(date.timetuple()) * 1000) else: date = '' query = ( ('timetableId', self.service_code), ('direction', 'OUTBOUND'), ('queryDate', date), ('queryTime', date) ) return 'http://www.{}/lts/#/timetables?{}'.format(domain, urlencode(query)), name def is_megabus(self): return (self.line_name in {'FALCON', 'Oxford Tube'} or self.pk in {'bed_1-X5-Z-y08', 'YWAX062', 'HIAG010', 'FSAM009', 'FSAG009', 'EDAO900', 'EDAAIR0', 'YSBX010', 'ABAX010', 'ABAO010'} or any(o.pk in {'MEGA', 'MBGD', 'SCMG'} for o in self.operator.all())) def get_megabus_url(self): # Using a tuple of tuples, instead of a dict, because the order of dicts is nondeterministic query = ( ('mid', 2678), ('id', 242611), ('clickref', 'links'), ('clickref2', self.service_code), ('p', 'https://uk.megabus.com'), ) return 'https://www.awin1.com/awclick.php?' + urlencode(query) def get_traveline_link(self, date=None): if self.region_id in ('Y', 'S'): return self.get_trapeze_link(date) if self.region_id == 'W': for service_code in self.servicecode_set.filter(scheme='Traveline Cymru'): query = ( ('routeNum', self.line_name), ('direction_id', 0), ('timetable_key', service_code.code) ) url = 'https://www.traveline.cymru/timetables/?' + urlencode(query) return url, 'Traveline Cymru' query = None if self.net: if self.servicecode_set.filter(scheme='TfL').exists(): return self.get_tfl_url(), 'Transport for London' elif self.net == 'tfl': return None, None parts = self.service_code.split('-') line = parts[0].split('_')[-1].zfill(2) + parts[1].zfill(3) line_ver = self.line_ver or parts[4] query = [('line', line), ('lineVer', line_ver), ('net', self.net), ('project', parts[3])] if parts[2] != '_': query.append(('sup', parts[2])) elif self.region_id == 'GB': parts = self.service_code.split('_') operator_number = self.get_operator_number(parts[1]) if operator_number is not None: query = [('line', operator_number + parts[0][:3].zfill(3)), ('sup', parts[0][3:]), ('net', 'nrc'), ('project', 'y08')] if query is not None: query += [('command', 'direct'), ('outputFormat', 0)] base_url = 'http://www.travelinesoutheast.org.uk/se' return '%s/XSLT_TTB_REQUEST?%s' % (base_url, urlencode(query)), 'Traveline' return None, None def get_filenames(self, archive): if self.region_id == 'NE': return ['{}.xml'.format(self.pk)] if self.region_id in ('S', 'Y'): return ['SVR{}.xml'.format(self.pk)] namelist = archive.namelist() if self.region_id == 'NW': codes = [code.code for code in self.servicecode_set.filter(scheme='NW TNDS')] + [self.pk] return [name for name in namelist if any(name == code + '.xml' or name.startswith(code + '_') for code in codes)] if self.net: return [name for name in namelist if name.startswith('{}-'.format(self.pk))] if self.region_id == 'GB': parts = self.pk.split('_') suffix = '_{}_{}.xml'.format(parts[1], parts[0]) else: suffix = '_{}.xml'.format(self.pk) # Wales return [name for name in namelist if name.endswith(suffix)] def get_files_from_zipfile(self): """Given a Service, return an iterable of open files from the relevant zipfile. """ service_code = self.service_code if self.region_id == 'GB': archive_name = 'NCSD' parts = service_code.split('_') service_code = '_%s_%s' % (parts[-1], parts[-2]) else: archive_name = self.region_id archive_path = os.path.join(settings.TNDS_DIR, archive_name + '.zip') try: with zipfile.ZipFile(archive_path) as archive: filenames = self.get_filenames(archive) return [archive.open(filename) for filename in filenames] except (zipfile.BadZipfile, IOError, KeyError): return [] def get_timetables(self, day=None): """Given a Service, return a list of Timetables.""" if day is None: day = date.today() if self.region_id == 'NI': path = os.path.join(settings.DATA_DIR, 'NI', self.pk + '.json') if os.path.exists(path): return northern_ireland.get_timetable(path, day) return [] if self.region_id in {'UL', 'LE', 'MU', 'CO', 'HI'}: service_codes = self.servicecode_set.filter(scheme__endswith=' GTFS') timetables = [gtfs.get_timetable(service_code.get_routes(), day) for service_code in service_codes] else: cache_key = '{}:{}'.format(self.service_code, self.date) timetables = cache.get(cache_key) if timetables is None: timetables = [] for xml_file in self.get_files_from_zipfile(): with xml_file: timetable = txc.Timetable(xml_file, day, self) del timetable.service del timetable.journeypatterns del timetable.stops del timetable.operators del timetable.element timetables.append(timetable) cache.set(cache_key, timetables) if len(timetables) > 1 and timetables[1].operating_period.start > day: self.timetable_change = timetables[1].operating_period.start timetables = [timetable for timetable in timetables if timetable.operating_period.contains(day)] for timetable in timetables: timetable.service = self timetable.set_date(day) timetable.set_description(self.description) timetable.groupings = [g for g in timetable.groupings if g.rows and g.rows[0].times] return [t for t in timetables if t and t.groupings] or timetables[:1]
class ScopeType(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=255, null=True) def __str__(self): return '{}'.format(self.name)
class Factory(models.Model): """Factories that are potential to be illegal.""" # List of fact_type & status factory_type_list = [ ("2-1", "沖床、銑床、車床、鏜孔"), ("2-2", "焊接、鑄造、熱處理"), ("2-3", "金屬表面處理、噴漆"), ("3", "塑膠加工、射出"), ("4", "橡膠加工"), ("5", "非金屬礦物(石材)"), ("6", "食品"), ("7", "皮革"), ("8", "紡織"), ("9", "其他"), ] cet_report_status_list = [ ("A", "未舉報"), ("B", "已舉報"), ] source_list = [ ("G", "政府"), ("U", "使用者"), ] # All Features id = models.UUIDField( primary_key=True, default=uuid.uuid4, editable=False, verbose_name="ID", ) lat = models.FloatField() lng = models.FloatField() point = models.PointField(srid=settings.POSTGIS_SRID) landcode = models.CharField(max_length=50, blank=True, null=True) name = models.CharField(max_length=50, blank=True, null=True) factory_type = models.CharField( max_length=3, choices=factory_type_list, blank=True, null=True, ) before_release = models.BooleanField( default=False) # 從 full-info.csv 匯入的那些都是 True ,使用者新增的通通是 False source = models.CharField( max_length=1, choices=source_list, default="U", ) cet_report_status = models.CharField( max_length=1, choices=cet_report_status_list, default="A", ) # 地球公民基金會的舉報狀態 status_time = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def save(self, *args, **kwargs): self.point = Point(self.lng, self.lat, srid=4326) self.point.transform(settings.POSTGIS_SRID) super(Factory, self).save(*args, **kwargs)
class Albulm(models.Model): name = models.CharField(max_length=60, blank=False) artist = models.ForeignKey(Artist)
class Desaparecido(models.Model): quien_registra = models.ForeignKey(User) FECHA_ALTA = models.DateTimeField(auto_now_add=True) FECHA_ACTUALIZACION = models.DateTimeField(auto_now=True) fecha_desaparicion= models.DateTimeField() nombre = models.CharField(max_length=50, blank=True) primer_apellido = models.CharField(max_length=50, blank=True) segundo_apellido = models.CharField(max_length=50, blank=True) punto_desaparecido = models.PointField(default='POINT(0 0)', srid=4326) @property def longitude(self): return self.punto_desaparecido[0] @property def latitude(self): return self.punto_desaparecido[1] num_de_identificacion= models.CharField(max_length=50, blank=True) TIPO_DE_IDENTIFICACION_OPT= ( ('I', 'IFE'), ('P', 'PASAPORTE'), ('L', 'LICENCIA DE MANEJO'), ('O', 'OTRO') ) TIPO_DE_IDENTIFICACION=models.CharField(max_length=2, choices= TIPO_DE_IDENTIFICACION_OPT, blank=True) SEXO_OPT= ( ('M', 'Masculino'), ('F', 'Femenino'), ) sexo = models.CharField(max_length=2, choices= SEXO_OPT,blank=True) orientacion_sexual = models.CharField(max_length=50, blank=True) intervencion_quirurgica_modificar_sexo = models.CharField(max_length=50, blank=True) fecha_nacimiento=models.DateTimeField() edad_aproximada=models.IntegerField() nacionalidad=models.CharField(max_length=50, blank=True,default="Mexicano(a)") pais_origen=models.CharField(max_length=50, blank=True, default="México") #ESTADO_PROCEDENCIA= #MUNICIPIO_PROCEDENCIA= #LOCALIDAD_PROCEDENCIA descripcion_fisica_desaparecido=models.CharField(max_length=300, blank=True) estatura=models.IntegerField() complexion= models.CharField(max_length=50, blank=True) tez=models.CharField(max_length=50, blank=True) tipo_de_cabello= models.CharField(max_length=50, blank=True) color_cabello= models.CharField(max_length=50, blank=True) color_de_ojos= models.CharField(max_length=50, blank=True) tiene_muestras_geneticas = models.CharField(max_length=2, blank=True) numero_referencia_de_muestra = models.CharField(max_length=50, blank=True) institucon_que_la_tomo = models.CharField(max_length=50, blank=True) senias_particulares = models.CharField(max_length=300, blank=True) grupo_etnico = models.CharField(max_length=50, blank=True) migrante = models.CharField(max_length=50, blank=True) pais_origen = models.CharField(max_length=50, blank=True) fue_encontrado = models.CharField(max_length=50, blank=True) fecha_encontrado = models.CharField(max_length=50, blank=True) estatus_encontrado = models.CharField(max_length=50, blank=True) SOLO_OPT= ( ('0', 'Sólo'), ('1', 'Acompañado'), ) desaparicion_en_grupo = models.CharField(max_length=2,blank=True, verbose_name='Estaba sólo o acompañado', choices = SOLO_OPT) AVERIGUACION_OPT= ( ('0', 'Sí'), ('1', 'No'), ) tiene_averiguacion_previa = models.CharField(max_length=2,blank=True, choices=AVERIGUACION_OPT, help_text="Tiene averiguacion?") NUM_AVERIGUACION = models.CharField(max_length=100, blank=True) tipo_lugar_ultimavez_visto=models.CharField(max_length=100, blank=True) #ESTADO= #MUNICIPIO= #LOCALIDAD= colonia_barrio_ejido_desaparicion=models.CharField(max_length=100, blank=True) #dsp es desaparicion calle_desaparicion=models.CharField(max_length=100, blank=True) numero_desaparicion=models.CharField(max_length=100, blank=True) def __str__(self): return "%s" % (self.nombre, ' ',self.primer_apellido, ' ', self.segundo_apellido)
class Plan(SourceControlModel, SoftDeleteModel, UserControlModel): # Permissions ADD_PERMISSION = "traffic_control.add_plan" CHANGE_PERMISSION = "traffic_control.change_plan" DELETE_PERMISSION = "traffic_control.delete_plan" VIEW_PERMISSION = "traffic_control.view_plan" id = models.UUIDField(primary_key=True, unique=True, editable=False, default=uuid.uuid4) name = models.CharField(verbose_name=_("Name"), max_length=512) plan_number = models.CharField( verbose_name=_("Plan number"), max_length=16, help_text=_("Year and verdict section separated with a dash"), ) location = models.MultiPolygonField(_("Location (3D)"), dim=3, srid=settings.SRID, null=True, blank=True) planner = models.CharField(_("Planner"), blank=True, max_length=200) decision_maker = models.CharField(_("Decision maker"), blank=True, max_length=200) objects = SoftDeleteQuerySet.as_manager() class Meta: db_table = "plan" verbose_name = _("Plan") verbose_name_plural = _("Plans") unique_together = ["source_name", "source_id"] def __str__(self): return f"{self.plan_number} {self.name}" def _get_related_locations(self) -> List[Point]: """ Get list of Points related to plan instance """ return list( chain( self.barrier_plans.values_list("location", flat=True), self.mount_plans.values_list("location", flat=True), self.road_marking_plans.values_list("location", flat=True), self.signpost_plans.values_list("location", flat=True), self.traffic_light_plans.values_list("location", flat=True), self.traffic_sign_plans.values_list("location", flat=True), self.additional_sign_plans.values_list("location", flat=True), )) def derive_location_from_related_plans(self, buffer: int = 5): """ Derive unified location polygon based on related plan models. Buffer the individual points with N meters. :param buffer: Buffer radius """ locations = self._get_related_locations() if len(locations) == 0: self.location = None else: location_polygons = MultiPolygon( [p.buffer(buffer) for p in self._get_related_locations()], srid=settings.SRID, ) area = location_polygons.convex_hull coords_3d = [(*pt, 0) for pt in area.coords[0]] area_3d = Polygon(coords_3d, srid=settings.SRID) self.location = MultiPolygon(area_3d, srid=settings.SRID) self.save(update_fields=["location"])
class Signal(CreatedUpdatedModel): SOURCE_DEFAULT_ANONYMOUS_USER = '******' uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) source = models.CharField(max_length=128, default=SOURCE_DEFAULT_ANONYMOUS_USER) text = models.CharField(max_length=3000) text_extra = models.CharField(max_length=10000, default='', blank=True) incident_date_start = models.DateTimeField( null=False) # Date of the incident. incident_date_end = models.DateTimeField( null=True) # Date of the incident. operational_date = models.DateTimeField( null=True) # Date action is expected expire_date = models.DateTimeField( null=True) # Date we should have reported back to reporter. extra_properties = models.JSONField(null=True) # Assignments parent = models.ForeignKey(to='self', related_name='children', null=True, blank=True, on_delete=models.SET_NULL) location = models.OneToOneField('signals.Location', related_name='signal', null=True, on_delete=models.SET_NULL) status = models.OneToOneField('signals.Status', related_name='signal', null=True, on_delete=models.SET_NULL) category_assignment = models.OneToOneField('signals.CategoryAssignment', related_name='signal', null=True, on_delete=models.SET_NULL) categories = models.ManyToManyField('signals.Category', through='signals.CategoryAssignment') reporter = models.OneToOneField('signals.Reporter', related_name='signal', null=True, on_delete=models.SET_NULL) priority = models.OneToOneField('signals.Priority', related_name='signal', null=True, on_delete=models.SET_NULL) directing_departments_assignment = models.OneToOneField( 'signals.SignalDepartments', related_name='directing_department_signal', null=True, on_delete=models.SET_NULL) routing_assignment = models.OneToOneField('signals.SignalDepartments', related_name='routing_signal', null=True, on_delete=models.SET_NULL) user_assignment = models.OneToOneField( 'signals.SignalUser', related_name='user_assignment_signal', null=True, on_delete=models.SET_NULL) type_assignment = models.OneToOneField('signals.Type', related_name='signal', null=True, on_delete=models.SET_NULL) # Managers objects = SignalQuerySet.as_manager() actions = SignalManager() class Meta: permissions = ( ('sia_read', 'Leesrechten algemeen'), # SIG-2192 ('sia_write', 'Schrijfrechten algemeen'), # SIG-2194 ('sia_split', 'Splitsen van een melding'), # SIG-2192 ('sia_signal_create_initial', 'Melding aanmaken'), # SIG-2192 ('sia_signal_create_note', 'Notitie toevoegen bij een melding'), # SIG-2192 ('sia_signal_change_status', 'Wijzigen van status van een melding'), # SIG-2192 ('sia_signal_change_category', 'Wijzigen van categorie van een melding'), # SIG-2192 ('sia_signal_export', 'Meldingen exporteren'), # SIG-2192 ('sia_signal_report', 'Rapportage beheren'), # SIG-2192 ) ordering = ('created_at', ) indexes = [ models.Index(fields=['created_at']), models.Index(fields=['id', 'parent']), ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if not self.uuid: self.uuid = uuid.uuid4() def __str__(self): """ Identifying string. DO NOT expose sensitive stuff here. """ # Fix for bug SIG-2486 Timezones were not consistently shown created_at = self.created_at field_timezone = timezone.get_current_timezone( ) if settings.USE_TZ else None if timezone.is_aware(created_at) and field_timezone: created_at = created_at.astimezone(field_timezone) elif timezone.is_aware(created_at): created_at = timezone.make_naive(created_at, utc) return f'{self.id} - ' \ f'{self.status.state if self.status else ""} - ' \ f'{self.location.buurt_code if self.location else ""} - ' \ f'{created_at.isoformat()}' @property def is_parent(self): return self.children.exists() @property def is_child(self): return self.parent is not None @property def sia_id(self): """ SIA identifier used for external communication. """ return f'SIA-{self.id}' @property def siblings(self): """ Returns all siblings, excluded the signal itself. By default it will return a Signal.objects.none() """ if self.is_child: return self.parent.children.exclude( pk=self.pk) if self.pk else self.parent.children.all() return self.__class__.objects.none() def _validate(self): if self.is_parent and self.is_child: # We cannot be a parent and a child at once raise ValidationError('Cannot be a parent and a child at the once') if self.parent and self.parent.is_child: # The parent of this Signal cannot be a child of another Signal raise ValidationError('A child of a child is not allowed') if (self.pk is None and self.is_child and self.siblings.count() >= settings.SIGNAL_MAX_NUMBER_OF_CHILDREN): # we are a new child and our parent already has the max number of children raise ValidationError( 'Maximum number of children reached for the parent Signal') def save(self, *args, **kwargs): self._validate() super().save(*args, **kwargs)
class crops(models.Model): #crop_id=models.IntegerField(primary_key='true') crop_name = models.CharField(max_length=30) def __str__(self): return self.crop_name
class Meteocondition(models.Model): curdate = models.DateField(blank=True, null=True) t = models.FloatField(blank=True, null=True) p0 = models.FloatField(blank=True, null=True) p = models.FloatField(blank=True, null=True) pa = models.FloatField(blank=True, null=True) u = models.SmallIntegerField(blank=True, null=True) dd = models.CharField(max_length=50, blank=True) ff = models.SmallIntegerField(blank=True, null=True) ff10 = models.SmallIntegerField(blank=True, null=True) ff3 = models.SmallIntegerField(blank=True, null=True) n = models.CharField(max_length=50, blank=True) ww = models.CharField(max_length=100, blank=True) w1 = models.CharField(max_length=100, blank=True) w2 = models.CharField(max_length=100, blank=True) tn = models.FloatField(blank=True, null=True) tx = models.FloatField(blank=True, null=True) cl = models.CharField(max_length=100, blank=True) nh = models.CharField(max_length=30, blank=True) h = models.CharField(max_length=20, blank=True) cm = models.CharField(max_length=100, blank=True) ch = models.CharField(max_length=100, blank=True) w = models.FloatField(blank=True, null=True) r = models.FloatField(blank=True, null=True) rrr = models.FloatField(blank=True, null=True) tr = models.SmallIntegerField(blank=True, null=True) e = models.CharField(max_length=100, blank=True) tg = models.FloatField(blank=True, null=True) es = models.CharField(max_length=100, blank=True) sss = models.SmallIntegerField(blank=True, null=True) rain = models.NullBooleanField() kmp = models.FloatField(blank=True, null=True) pjc = models.FloatField(blank=True, null=True) ap = models.FloatField(blank=True, null=True) pm = models.FloatField(blank=True, null=True) pr = models.FloatField(blank=True, null=True) class Meta: managed = False db_table = 'meteocondition'
class MapMeteocondition(models.Model): t = models.DecimalField(max_digits=5, decimal_places=2) p0 = models.DecimalField(max_digits=5, decimal_places=2) p = models.DecimalField(max_digits=5, decimal_places=2) pa = models.DecimalField(max_digits=5, decimal_places=2) u = models.IntegerField() dd = models.CharField(max_length=50) ff = models.IntegerField() ff10 = models.IntegerField() ff3 = models.IntegerField() n = models.CharField(max_length=50) ww = models.CharField(max_length=100) ww1 = models.CharField(max_length=100) ww2 = models.CharField(max_length=100) tn = models.DecimalField(max_digits=5, decimal_places=2) tx = models.DecimalField(max_digits=5, decimal_places=2) cl = models.CharField(max_length=100) nh = models.CharField(max_length=30) h = models.CharField(max_length=20) cm = models.CharField(max_length=100) ch = models.CharField(max_length=100) w = models.DecimalField(max_digits=5, decimal_places=2) r = models.DecimalField(max_digits=5, decimal_places=2) rrr = models.DecimalField(max_digits=5, decimal_places=2) tr = models.IntegerField() e = models.CharField(max_length=100) tg = models.DecimalField(max_digits=5, decimal_places=2) es = models.CharField(max_length=100) sss = models.IntegerField() rain = models.BooleanField() kmp = models.DecimalField(max_digits=5, decimal_places=2) pjc = models.DecimalField(max_digits=5, decimal_places=2) ap = models.DecimalField(max_digits=5, decimal_places=2) pm = models.DecimalField(max_digits=5, decimal_places=2) pr = models.DecimalField(max_digits=5, decimal_places=2) class Meta: managed = False db_table = 'map_meteocondition'
class Property(models.Model): PROPERTY_TYPES = (('lb', 'Landbank'), ('sp', 'County Owned Surplus')) geometry = models.MultiPolygonField(srid=4326, blank=True) centroid_geometry = models.PointField( srid=4326, default='SRID=4326;POINT(39.7684 86.1581)', blank=True) # objects = models.GeoManager() propertyType = models.CharField(choices=PROPERTY_TYPES, max_length=2, verbose_name='property type') parcel = models.CharField( max_length=7, unique=True, help_text="The 7 digit local parcel number for a property, ex 1052714", verbose_name='parcel number') streetAddress = models.CharField( max_length=255, help_text= "Supports partial matching, so you can enter either the full street address (eg 1425 E 11TH ST) to find one property or just the street name (eg 11th st) to find all the properties on that street.", verbose_name='Street Address', blank=True, ) nsp = models.BooleanField( default=False, help_text= "If a property comes with requirements related to the Neighborhood Stabilization Program.", verbose_name='NSP') quiet_title_complete = models.BooleanField( default=False, help_text="If quiet title process has been completed.", verbose_name='Quiet Title Complete') # should restrict this with choices using valid strings as options to catch mis-spellings. structureType = models.CharField(max_length=255, null=True, blank=True, help_text="As classified by the Assessor", verbose_name='Structure Type') cdc = models.ForeignKey( CDC, blank=True, null=True, help_text= "The Community Development Corporation boundries the property falls within.", verbose_name='CDC', on_delete=models.CASCADE) zone = models.ForeignKey(Zoning, blank=True, null=True, help_text="The zoning of the property", on_delete=models.CASCADE) neighborhood = models.ForeignKey( Neighborhood, blank=True, null=True, help_text="The neighborhood the property is in", on_delete=models.CASCADE) zipcode = models.ForeignKey(Zipcode, blank=True, null=True, help_text="The zipcode of the property", on_delete=models.CASCADE) census_tract = models.ForeignKey( census_tract, blank=True, null=True, help_text="The Census Tract of the property", on_delete=models.CASCADE) urban_garden = models.BooleanField( default=False, help_text= "If the property is currently licensed as an urban garden through the Office of Sustainability" ) status = models.CharField( max_length=255, null=True, blank=True, help_text="The property's status with Renew Indianapolis") sidelot_eligible = models.BooleanField( default=False, help_text= "If the property is currently elgibile for the side-lot program") price = models.DecimalField(max_digits=8, decimal_places=2, help_text="The price of the property", null=True, blank=True) area = models.FloatField(help_text="The parcel area in square feet", null=True, blank=True) # change to foreign key when ready applicant = models.CharField( max_length=255, blank=True, null=True, help_text="Name of current applicant for status page") homestead_only = models.BooleanField( default=False, help_text="Only available for homestead applications") bep_demolition = models.BooleanField( default=False, help_text="Slated for demolition under the Blight Elimination Program", verbose_name="Slated for BEP demolition") project_agreement_released = models.BooleanField( default=False, help_text="Has the project agreement on a sold property been released?" ) is_active = models.BooleanField( default=True, help_text="Is this property listing active?") price_obo = models.BooleanField(default=False, help_text="Price is Or Best Offer", verbose_name="Price is 'Or Best Offer'") renew_owned = models.BooleanField( default=False, help_text= "Property is owned directly by Renew Indianapolis or a wholly owned subsidiary.", verbose_name="Owned by Renew Indianapolis directly") hhf_demolition = models.BooleanField( default=False, help_text= "Property was demolished through Hardest Hit Funds/Blight Elimination Program, and may have restrictions on end use.", verbose_name= "Property was demolished through Hardest Hit Funds/Blight Elimination Program" ) vacant_lot_eligible = models.BooleanField( default=False, help_text= "Property is eligible for sale through the vacant lot program.") future_development_program_eligible = models.BooleanField( default=False, help_text= "Property is eligible for sale through the Future Development Lot program." ) short_legal_description = models.CharField(max_length=2048, blank=True) #slug = AutoSlugField(always_update=True, unique=True, populate_from=lambda instance: instance.streetAddress + instance.parcel) number_of_units = models.PositiveIntegerField( default=1, help_text="Number of units in the property, at time of sale", blank=True) acquisition_date = models.DateField(null=True, blank=True, help_text='Date property was acquired') renew_acquisition_date = models.DateField( null=True, blank=True, help_text='Date property was acquired by Renew') buyer_application = models.ForeignKey( 'applications.Application', null=True, blank=True, help_text='The final buyer application.', on_delete=models.CASCADE) property_inspection_group = models.CharField(blank=True, max_length=10) update_from_server = models.BooleanField( default=True, help_text= "Attempt to update street address, etc from remote server on next save." ) class Meta: verbose_name_plural = "properties" ordering = ['streetAddress', 'parcel'] def natural_key(self): return '%s - %s' % (self.streetAddress, self.parcel) def __str__(self): return '%s - %s' % (self.streetAddress, self.parcel) ## added this function to calculate centroid of the geometry on saving, as it not otherwise available. def save(self, *args, **kwargs): if self.parcel is not None and self.parcel != '' and self.update_from_server == True: results = pull_property_info_from_arcgis(self.parcel) if results: self.streetAddress = results['street_address'] self.geometry = results['geometry'] self.centroid_geometry = self.geometry.centroid self.area = float(results['estsqft']) try: aiv = float(results['assessed_improvement_value']) except ValueError: aiv = 0 if aiv > 0: self.structureType = 'Residential Dwelling' else: self.structureType = 'Vacant Lot' self.zipcode = Zipcode.objects.filter( geometry__contains=self.centroid_geometry).first() self.zone = Zoning.objects.filter( geometry__contains=self.centroid_geometry).first() self.cdc = CDC.objects.filter( geometry__contains=self.centroid_geometry).first() self.neighborhood = Neighborhood.objects.filter( geometry__contains=self.centroid_geometry).first() self.census_tract = census_tract.objects.filter( geometry__contains=self.centroid_geometry).first() self.is_active = False self.propertyType = 'lb' self.update_from_server = False super(Property, self).save(*args, **kwargs)
class Incident(Point): ############ # Response options for CharField data types # INCIDENT_CHOICES = ((_('Collision'), ( ('Collision with stationary object or vehicle', _('Collision with a stationary object or vehicle')), ('Collision with moving object or vehicle', _('Collision with a moving object or vehicle')), )), (_('Near miss'), ( ('Near collision with stationary object or vehicle', _('Near miss with a stationary object or vehicle')), ('Near collision with moving object or vehicle', _('Near miss with a moving object or vehicle')), )), (_('Fall'), (('Fall', _('Lost control and fell')), ))) INCIDENT_WITH_CHOICES = ( ( _('Vehicle'), ( ('Vehicle, head on', _('Head on')), ( 'Vehicle, side', _('Side impact') ), # maintained for compativility with the old version of the app ( 'Vehicle, angle', _('Angle impact') ), # maintained for compatibility with the old version of the app ('Vehicle, rear end', _('Rear end')), ('Vehicle, turning right', _('Turning right')), ('Vehicle, turning left', _('Turning left')), ('Vehicle, passing', _('Passing')), ('Vehicle, open door', _('Open vehicle door')), )), (_('Person/animal'), ( ('Another cyclist', _('Another cyclist')), ('Pedestrian', _('Pedestrian')), ('Animal', _('Animal')), ('E-scooter', _('E-scooter')), )), (_('Infrastructure'), ( ('Curb', _('Curb')), ('Train Tracks', _('Train Tracks')), ('Pothole', _('Pothole')), ('Lane divider', _('Lane divider')), ('Sign/Post', _('Sign/Post')), ('Roadway', _('Roadway')), )), ('Other', _('Other (please describe)'))) INJURY_CHOICES = ((_('Yes'), (('Injury, no treatment', _('Medical treatment not required')), ('Injury, saw family doctor', _('Saw a family doctor')), ('Injury, hospital emergency visit', _('Visited the hospital emergency dept.')), ('Injury, hospitalized', _('Overnight stay in hospital')))), (_('No'), (('No injury', _('No injury')), )), (_('Unknown'), (('Unknown', _('I don\'t know')), ))) PURPOSE_CHOICES = (('Commute', _('To/from work or school')), ('Exercise or recreation', _('Exercise or recreation')), ('Social reason', _('Social reason (e.g., movies, visit friends)')), ('Personal business', _('Personal business')), ('During work', _('During work'))) ROAD_COND_CHOICES = (('Dry', _('Dry')), ('Wet', _('Wet')), ('Loose sand, gravel, or dirt', _('Loose sand, gravel, or dirt')), ('Icy', _('Icy')), ('Snowy', _('Snowy')), ('Don\'t remember', _('I don\'t remember'))) SIGHTLINES_CHOICES = (('No obstructions', _('No obstructions')), ('View obstructed', _('View obstructed')), ('Glare or reflection', _('Glare or reflection')), ('Obstruction on road', _('Obstruction on road')), ('Don\'t Remember', _('Don\'t Remember'))) LIGHTS_CHOICES = (('NL', _('No Lights')), ('FB', _('Front and back lights')), ('F', _('Front lights only')), ('B', _('Back lights only')), ('Don\'t remember', _('I don\'t remember'))) TERRAIN_CHOICES = (('Uphill', _('Uphill')), ('Downhill', _('Downhill')), ('Flat', _('Flat')), ('Don\'t remember', _('I don\'t remember'))) BOOLEAN_CHOICES = (('Y', _('Yes')), ('N', _('No')), ('I don\'t know', _('I don\'t know'))) CARDINAL_DIRECTIONS_CHOICES = (('N', _('N')), ('NE', _('NE')), ('E', _('E')), ('SE', _('SE')), ('S', _('S')), ('SW', _('SW')), ('W', _('W')), ('NW', _('NW')), ('I don\'t know', _('I don\'t know'))) TURNING_CHOICES = (('Heading straight', _('Heading straight')), ('Turning left', _('Turning left')), ('Turning right', _('Turning right')), ('I don\'t remember', _('I don\'t remember'))) INCIDENT_IMPACT_CHOICES = ( ('None', _('No impact')), ('More careful', _('I\'m now more careful about where/when/how I ride')), ('Bike less', _('I bike less')), ('More careful and bike less', _('I\'m now more careful about where/when/how I ride AND I bike less') ), ('Stopped biking', _('I haven\'t biked since')), ('Too soon', _('Too soon to say')), ('Witness', _('I was not directly involved'))) BICYCLE_TYPE_CHOICES = (('Personal', _('Personal (my own bicycle or a friend\'s)')), ('Bike share', _('Bike share')), ('Bike rental', _('Bike rental')), ('E-scooter', _('E-scooter'))) EBIKE_CHOICES = (('Yes', _('Yes')), ('No', _('No')), ('I don\'t know', _('I don\'t know'))) PERSONAL_INVOLVEMENT_CHOICES = (('Yes', _('Yes, this happened to me')), ( 'No', _('No, I witnessed this happen to someone else'))) WITNESS_VEHICLE_CHOICES = ( ('Bicycle', _('Bicycle')), ('E-scooter', _('E-scooter')), ('Pedestrian', _('I was a pedestrian')), ('Driving', _('I was driving')), ) RIDING_ON_CHOICES = ( (_('Busy street'), (('Busy street cycle track', _('On a cycle track (separated bike lane)')), ('Busy street bike lane', _('On a painted bike lane')), ('Busy street, no bike facilities', _('On a street with no bicycle facility')))), (_('Quiet street'), (('Quiet street bike lane', _('On a local street bikeway (bike route)')), ('Quiet street, no bike facilities', _('On a street with no bicycle facility')))), (_('Off-Street'), ( ('Cycle track', _('On a physically separated bike lane (cycle track)')), ('Mixed use trail', _('On a multi-use path')), ('Sidewalk', _('On a sidewalk')), )), ('Don\'t remember', _('I don\'t remember'))) ############ # FIELDS point = models.OneToOneField(Point, on_delete=models.CASCADE, parent_link=True) i_type = models.CharField(_('What type of incident was it?'), max_length=150, choices=INCIDENT_CHOICES) incident_with = models.CharField( _('What sort of object did you collide or nearly collide with?'), max_length=100, choices=INCIDENT_WITH_CHOICES) injury = models.CharField( _('Were you injured?'), max_length=50, choices= INJURY_CHOICES # Without this, field has 'Unknown' for None rather than the desired '---------' ) trip_purpose = models.CharField(_('What was the purpose of your trip?'), max_length=50, choices=PURPOSE_CHOICES, blank=True, null=True) regular_cyclist = models.CharField(_('Do you bike at least once a week?'), max_length=50, choices=BOOLEAN_CHOICES, blank=True, null=True) helmet = models.CharField(_('Were you wearing a helmet?'), max_length=50, choices=BOOLEAN_CHOICES, blank=True, null=True) intoxicated = models.CharField(_('Were you intoxicated?'), max_length=50, choices=BOOLEAN_CHOICES, blank=True, null=True) road_conditions = models.CharField(_('What were the road conditions?'), max_length=50, choices=ROAD_COND_CHOICES, blank=True, null=True) sightlines = models.CharField(_('How were the sight lines?'), max_length=50, choices=SIGHTLINES_CHOICES, blank=True, null=True) cars_on_roadside = models.CharField( _('Were there cars parked on the roadside'), max_length=50, choices=BOOLEAN_CHOICES, blank=True, null=True) bike_lights = models.CharField(_('Were you using bike lights?'), max_length=200, choices=LIGHTS_CHOICES, blank=True, null=True) terrain = models.CharField(_('What was the terrain like?'), max_length=50, choices=TERRAIN_CHOICES, blank=True, null=True) direction = models.CharField(_('What direction were you heading?'), max_length=50, choices=CARDINAL_DIRECTIONS_CHOICES, blank=True, null=True) turning = models.CharField(_('How were you moving?'), max_length=50, choices=TURNING_CHOICES, blank=True, null=True) intersection = models.CharField( _('Did the incident occur at an intersection?'), max_length=50, choices=BOOLEAN_CHOICES, blank=True, null=True) aggressive = models.CharField(_('Was the driver aggressive?'), max_length=50, choices=BOOLEAN_CHOICES, blank=True, null=True) impact = models.CharField( _('How did this incident impact your bicycling?'), max_length=50, choices=INCIDENT_IMPACT_CHOICES, null=True) bicycle_type = models.CharField(_('What type of bicycle were you riding?'), max_length=20, choices=BICYCLE_TYPE_CHOICES, blank=True, null=True) ebike = models.CharField( _('Did the incident involve a pedal-assist electric bike (eBike)?'), max_length=20, choices=EBIKE_CHOICES, blank=True, null=True) witness_vehicle = models.CharField(_('What were you riding?'), max_length=20, choices=WITNESS_VEHICLE_CHOICES, blank=True, null=True) personal_involvement = models.CharField( _('Were you directly involved in the incident?'), max_length=20, choices=PERSONAL_INVOLVEMENT_CHOICES) riding_on = models.CharField(_('Where were you riding your bike?'), max_length=50, choices=RIDING_ON_CHOICES, blank=True, null=True) ############## def save(self, *args, **kwargs): self.p_type = self._getIncidentType() super(Incident, self).save(*args, **kwargs) def _getIncidentType(self): """Return "collision" or "nearmiss" pending on the type of incident a user selected.""" usr_choice = self.i_type for t, choice in Incident.INCIDENT_CHOICES: for p, q in choice: if p == usr_choice: if t == _("Near miss"): return "nearmiss" return "collision"
class App(models.Model): def only_filename(instance, filename): return filename name = models.CharField(max_length=200, null=True, blank=True) title = models.CharField(max_length=200, null=True, blank=True) description = models.TextField(null=True, blank=True) short_description = models.TextField(null=True, blank=True) app_url = models.URLField(null=True, blank=True) author = models.CharField(max_length=200, null=True, blank=True) author_website = models.URLField(null=True, blank=True) license = models.CharField(max_length=200, null=True, blank=True) tags = TaggableManager() date_installed = models.DateTimeField('Date Installed', auto_now_add=True, null=True) installed_by = models.ForeignKey(geonode_settings.AUTH_USER_MODEL, null=True, blank=True) single_instance = models.BooleanField(default=False, null=False, blank=False) category = models.ManyToManyField(AppType, related_name='apps') status = models.CharField(max_length=100, blank=False, null=False, default='Alpha') owner_url = models.URLField(null=True, blank=True) help_url = models.URLField(null=True, blank=True) app_img_url = models.TextField(max_length=1000, blank=True, null=True) rating = models.IntegerField(default=0, null=True, blank=True) contact_name = models.CharField(max_length=200, null=True, blank=True) contact_email = models.EmailField(null=True, blank=True) version = models.CharField(max_length=10) store = models.ForeignKey(AppStore, null=True) order = models.IntegerField(null=True, default=0) default_config = JSONField(default={}) class meta(object): ordering = ['order'] def __str__(self): return self.title @property def settings_url(self): try: return reverse("%s_settings" % self.name) except BaseException as e: logger.error(e.message) return None @property def new_url(self): try: return reverse("%s.new" % self.name) except BaseException as e: logger.error(e.message) return None _apps_config = None @property def apps_config(self): if App._apps_config is None: App._apps_config = AppsConfig() return App._apps_config def set_active(self, active=True): self.config.active = active self.apps_config.save() return App._apps_config @property def config(self): return self.apps_config.get_by_name(self.name)
class Reservation(ModifiableModel): CREATED = 'created' CANCELLED = 'cancelled' CONFIRMED = 'confirmed' DENIED = 'denied' REQUESTED = 'requested' STATE_CHOICES = ( (CREATED, _('created')), (CANCELLED, _('cancelled')), (CONFIRMED, _('confirmed')), (DENIED, _('denied')), (REQUESTED, _('requested')), ) resource = models.ForeignKey('Resource', verbose_name=_('Resource'), db_index=True, related_name='reservations', on_delete=models.PROTECT) begin = models.DateTimeField(verbose_name=_('Begin time')) end = models.DateTimeField(verbose_name=_('End time')) duration = pgfields.DateTimeRangeField( verbose_name=_('Length of reservation'), null=True, blank=True, db_index=True) comments = models.TextField(null=True, blank=True, verbose_name=_('Comments')) user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('User'), null=True, blank=True, db_index=True, on_delete=models.PROTECT) state = models.CharField(max_length=16, choices=STATE_CHOICES, verbose_name=_('State'), default=CONFIRMED) approver = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('Approver'), related_name='approved_reservations', null=True, blank=True, on_delete=models.SET_NULL) # access-related fields access_code = models.CharField(verbose_name=_('Access code'), max_length=32, null=True, blank=True) # EXTRA FIELDS START HERE event_subject = models.CharField(max_length=200, verbose_name=_('Event subject'), blank=True) event_description = models.TextField(verbose_name=_('Event description'), blank=True) number_of_participants = models.PositiveSmallIntegerField( verbose_name=_('Number of participants'), blank=True, null=True) participants = models.TextField(verbose_name=_('Participants'), blank=True) host_name = models.CharField(verbose_name=_('Host name'), max_length=100, blank=True) # extra detail fields for manually confirmed reservations reserver_name = models.CharField(verbose_name=_('Reserver name'), max_length=100, blank=True) reserver_id = models.CharField( verbose_name=_('Reserver ID (business or person)'), max_length=30, blank=True) reserver_email_address = models.EmailField( verbose_name=_('Reserver email address'), blank=True) reserver_phone_number = models.CharField( verbose_name=_('Reserver phone number'), max_length=30, blank=True) reserver_address_street = models.CharField( verbose_name=_('Reserver address street'), max_length=100, blank=True) reserver_address_zip = models.CharField( verbose_name=_('Reserver address zip'), max_length=30, blank=True) reserver_address_city = models.CharField( verbose_name=_('Reserver address city'), max_length=100, blank=True) company = models.CharField(verbose_name=_('Company'), max_length=100, blank=True) billing_address_street = models.CharField( verbose_name=_('Billing address street'), max_length=100, blank=True) billing_address_zip = models.CharField( verbose_name=_('Billing address zip'), max_length=30, blank=True) billing_address_city = models.CharField( verbose_name=_('Billing address city'), max_length=100, blank=True) # If the reservation was imported from another system, you can store the original ID in the field below. origin_id = models.CharField(verbose_name=_('Original ID'), max_length=50, editable=False, null=True) objects = ReservationQuerySet.as_manager() class Meta: verbose_name = _("reservation") verbose_name_plural = _("reservations") ordering = ('id', ) def _save_dt(self, attr, dt): """ Any DateTime object is converted to UTC time zone aware DateTime before save If there is no time zone on the object, resource's time zone will be assumed through its unit's time zone """ save_dt(self, attr, dt, self.resource.unit.time_zone) def _get_dt(self, attr, tz): return get_dt(self, attr, tz) @property def begin_tz(self): return self.begin @begin_tz.setter def begin_tz(self, dt): self._save_dt('begin', dt) def get_begin_tz(self, tz): return self._get_dt("begin", tz) @property def end_tz(self): return self.end @end_tz.setter def end_tz(self, dt): """ Any DateTime object is converted to UTC time zone aware DateTime before save If there is no time zone on the object, resource's time zone will be assumed through its unit's time zone """ self._save_dt('end', dt) def get_end_tz(self, tz): return self._get_dt("end", tz) def is_active(self): return self.end >= timezone.now() and self.state not in ( Reservation.CANCELLED, Reservation.DENIED) def is_own(self, user): if not (user and user.is_authenticated): return False return user == self.user def need_manual_confirmation(self): return self.resource.need_manual_confirmation def are_extra_fields_visible(self, user): # the following logic is used also implemented in ReservationQuerySet # so if this is changed that probably needs to be changed as well if self.is_own(user): return True return self.resource.can_view_reservation_extra_fields(user) def can_view_access_code(self, user): if self.is_own(user): return True return self.resource.can_view_access_codes(user) def set_state(self, new_state, user): # Make sure it is a known state assert new_state in (Reservation.REQUESTED, Reservation.CONFIRMED, Reservation.DENIED, Reservation.CANCELLED) old_state = self.state if new_state == old_state: if old_state == Reservation.CONFIRMED: reservation_modified.send(sender=self.__class__, instance=self, user=user) return if new_state == Reservation.CONFIRMED: self.approver = user reservation_confirmed.send(sender=self.__class__, instance=self, user=user) elif old_state == Reservation.CONFIRMED: self.approver = None # Notifications if new_state == Reservation.REQUESTED: self.send_reservation_requested_mail() self.send_reservation_requested_mail_to_officials() elif new_state == Reservation.CONFIRMED: if self.need_manual_confirmation(): self.send_reservation_confirmed_mail() elif self.resource.is_access_code_enabled(): self.send_reservation_created_with_access_code_mail() else: self.send_reservation_created_mail() elif new_state == Reservation.DENIED: self.send_reservation_denied_mail() elif new_state == Reservation.CANCELLED: if user != self.user: self.send_reservation_cancelled_mail() reservation_cancelled.send(sender=self.__class__, instance=self, user=user) self.state = new_state self.save() def can_modify(self, user): if not user: return False # reservations that need manual confirmation and are confirmed cannot be # modified or cancelled without reservation approve permission cannot_approve = not self.resource.can_approve_reservations(user) if self.need_manual_confirmation( ) and self.state == Reservation.CONFIRMED and cannot_approve: return False return self.user == user or self.resource.can_modify_reservations(user) def can_add_comment(self, user): if self.is_own(user): return True return self.resource.can_access_reservation_comments(user) def can_view_field(self, user, field): if field not in RESERVATION_EXTRA_FIELDS: return True if self.is_own(user): return True return self.resource.can_view_reservation_extra_fields(user) def can_view_catering_orders(self, user): if self.is_own(user): return True return self.resource.can_view_catering_orders(user) def format_time(self): tz = self.resource.unit.get_tz() begin = self.begin.astimezone(tz) end = self.end.astimezone(tz) return format_dt_range(translation.get_language(), begin, end) def __str__(self): if self.state != Reservation.CONFIRMED: state_str = ' (%s)' % self.state else: state_str = '' return "%s: %s%s" % (self.format_time(), self.resource, state_str) def clean(self, **kwargs): """ Check restrictions that are common to all reservations. If this reservation isn't yet saved and it will modify an existing reservation, the original reservation need to be provided in kwargs as 'original_reservation', so that it can be excluded when checking if the resource is available. """ if self.end <= self.begin: raise ValidationError( _("You must end the reservation after it has begun")) # Check that begin and end times are on valid time slots. opening_hours = self.resource.get_opening_hours( self.begin.date(), self.end.date()) for dt in (self.begin, self.end): days = opening_hours.get(dt.date(), []) day = next((day for day in days if day['opens'] is not None and day['opens'] <= dt <= day['closes']), None) if day and not is_valid_time_slot(dt, self.resource.min_period, day['opens']): raise ValidationError( _("Begin and end time must match time slots")) original_reservation = self if self.pk else kwargs.get( 'original_reservation', None) if self.resource.check_reservation_collision(self.begin, self.end, original_reservation): raise ValidationError( _("The resource is already reserved for some of the period")) if (self.end - self.begin) < self.resource.min_period: raise ValidationError( _("The minimum reservation length is %(min_period)s") % {'min_period': humanize_duration(self.min_period)}) if self.access_code: validate_access_code(self.access_code, self.resource.access_code_type) def get_notification_context(self, language_code, user=None, notification_type=None): if not user: user = self.user with translation.override(language_code): reserver_name = self.reserver_name if not reserver_name and self.user and self.user.get_display_name( ): reserver_name = self.user.get_display_name() context = { 'resource': self.resource.name, 'begin': localize_datetime(self.begin), 'end': localize_datetime(self.end), 'begin_dt': self.begin, 'end_dt': self.end, 'time_range': self.format_time(), 'number_of_participants': self.number_of_participants, 'host_name': self.host_name, 'reserver_name': reserver_name, 'event_subject': self.event_subject, } if self.resource.unit: context['unit'] = self.resource.unit.name if self.can_view_access_code(user) and self.access_code: context['access_code'] = self.access_code if notification_type == NotificationType.RESERVATION_CONFIRMED: if self.resource.reservation_confirmed_notification_extra: context[ 'extra_content'] = self.resource.reservation_confirmed_notification_extra elif notification_type == NotificationType.RESERVATION_REQUESTED: if self.resource.reservation_requested_notification_extra: context[ 'extra_content'] = self.resource.reservation_requested_notification_extra # Get last main and ground plan images. Normally there shouldn't be more than one of each # of those images. images = self.resource.images.filter( type__in=('main', 'ground_plan')).order_by('-sort_order') main_image = next((i for i in images if i.type == 'main'), None) ground_plan_image = next( (i for i in images if i.type == 'ground_plan'), None) if main_image: main_image_url = main_image.get_full_url() if main_image_url: context['resource_main_image_url'] = main_image_url if ground_plan_image: ground_plan_image_url = ground_plan_image.get_full_url() if ground_plan_image_url: context[ 'resource_ground_plan_image_url'] = ground_plan_image_url return context def send_reservation_mail(self, notification_type, user=None): """ Stuff common to all reservation related mails. If user isn't given use self.user. """ try: notification_template = NotificationTemplate.objects.get( type=notification_type) except NotificationTemplate.DoesNotExist: return if user: email_address = user.email else: if not (self.reserver_email_address or self.user): return email_address = self.reserver_email_address or self.user.email user = self.user language = user.get_preferred_language() if user else DEFAULT_LANG context = self.get_notification_context( language, notification_type=notification_type) try: rendered_notification = notification_template.render( context, language) except NotificationTemplateException as e: logger.error(e, exc_info=True, extra={'user': user.uuid}) return send_respa_mail(email_address, rendered_notification['subject'], rendered_notification['body'], rendered_notification['html_body']) def send_reservation_requested_mail(self): self.send_reservation_mail(NotificationType.RESERVATION_REQUESTED) def send_reservation_requested_mail_to_officials(self): notify_users = self.resource.get_users_with_perm( 'can_approve_reservation') if len(notify_users) > 100: raise Exception("Refusing to notify more than 100 users (%s)" % self) for user in notify_users: self.send_reservation_mail( NotificationType.RESERVATION_REQUESTED_OFFICIAL, user=user) def send_reservation_denied_mail(self): self.send_reservation_mail(NotificationType.RESERVATION_DENIED) def send_reservation_confirmed_mail(self): self.send_reservation_mail(NotificationType.RESERVATION_CONFIRMED) def send_reservation_cancelled_mail(self): self.send_reservation_mail(NotificationType.RESERVATION_CANCELLED) def send_reservation_created_mail(self): self.send_reservation_mail(NotificationType.RESERVATION_CREATED) def send_reservation_created_with_access_code_mail(self): self.send_reservation_mail( NotificationType.RESERVATION_CREATED_WITH_ACCESS_CODE) def save(self, *args, **kwargs): self.duration = DateTimeTZRange(self.begin, self.end, '[)') access_code_type = self.resource.access_code_type if not self.resource.is_access_code_enabled(): self.access_code = '' elif not self.access_code: self.access_code = generate_access_code(access_code_type) return super().save(*args, **kwargs)
class BasicData(models.Model): """Basic model for DISE data""" academic_id = models.ForeignKey('common.AcademicYear') district = models.CharField(max_length=50, blank=True) school_code = models.IntegerField(primary_key=True) school_name = models.CharField(max_length=200, blank=True) block_name = models.CharField(max_length=50, blank=True) cluster_name = models.CharField(max_length=50, blank=True) village_name = models.CharField(max_length=50, blank=True) pincode = models.IntegerField(null=True, blank=True) rural_urban = models.IntegerField(null=True, blank=True) medium_of_instruction = models.IntegerField(null=True, blank=True) distance_brc = models.FloatField(null=True, blank=True) distance_crc = models.FloatField(null=True, blank=True) yeur_estd = models.IntegerField(null=True, blank=True) pre_pry_yn = models.IntegerField(null=True, blank=True) residential_sch_yn = models.IntegerField(null=True, blank=True) sch_management = models.IntegerField(null=True, blank=True) lowest_class = models.IntegerField(null=True, blank=True) highest_class = models.IntegerField(null=True, blank=True) sch_category = models.IntegerField(null=True, blank=True) pre_pry_students = models.IntegerField(null=True, blank=True) school_type = models.IntegerField(null=True, blank=True) shift_school_yn = models.IntegerField(null=True, blank=True) no_of_working_days = models.IntegerField(null=True, blank=True) no_of_acad_inspection = models.IntegerField(null=True, blank=True) residential_sch_type = models.IntegerField(null=True, blank=True) pre_pry_teachers = models.IntegerField(null=True, blank=True) visits_by_brc = models.IntegerField(null=True, blank=True) visits_by_crc = models.IntegerField(null=True, blank=True) school_dev_grant_recd = models.FloatField(null=True, blank=True) school_dev_grant_expnd = models.FloatField(null=True, blank=True) tlm_grant_recd = models.FloatField(null=True, blank=True) tlm_grant_expnd = models.FloatField(null=True, blank=True) funds_from_students_recd = models.FloatField(null=True, blank=True) funds_from_students_expnd = models.FloatField(null=True, blank=True) building_status = models.IntegerField(null=True, blank=True) tot_clrooms = models.IntegerField(null=True, blank=True) classrooms_in_good_condition = models.IntegerField(null=True, blank=True) classrooms_require_major_repair = models.IntegerField(null=True, blank=True) classrooms_require_minor_repair = models.IntegerField(null=True, blank=True) other_rooms_in_good_cond = models.IntegerField(null=True, blank=True) other_rooms_need_major_rep = models.IntegerField(null=True, blank=True) other_rooms_need_minor_rep = models.IntegerField(null=True, blank=True) toilet_common = models.IntegerField(null=True, blank=True) toilet_boys = models.IntegerField(null=True, blank=True) toilet_girls = models.IntegerField(null=True, blank=True) kitchen_devices_grant = models.IntegerField(null=True, blank=True) status_of_mdm = models.IntegerField(null=True, blank=True) computer_aided_learnin_lab = models.IntegerField(null=True, blank=True) separate_room_for_headmaster = models.IntegerField(null=True, blank=True) electricity = models.IntegerField(null=True, blank=True) boundary_wall = models.IntegerField(null=True, blank=True) library_yn = models.IntegerField(null=True, blank=True) playground = models.IntegerField(null=True, blank=True) blackboard = models.IntegerField(null=True, blank=True) books_in_library = models.IntegerField(null=True, blank=True) drinking_water = models.IntegerField(null=True, blank=True) medical_checkup = models.IntegerField(null=True, blank=True) ramps = models.IntegerField(null=True, blank=True) no_of_computers = models.IntegerField(null=True, blank=True) male_tch = models.IntegerField(null=True, blank=True) female_tch = models.IntegerField(null=True, blank=True) noresp_tch = models.IntegerField(null=True, blank=True) head_teacher = models.IntegerField(null=True, blank=True) graduate_teachers = models.IntegerField(null=True, blank=True) tch_with_professional_qualification = models.IntegerField(null=True, blank=True) days_involved_in_non_tch_assgn = models.IntegerField(null=True, blank=True) teachers_involved_in_non_tch_assgn = models.IntegerField(null=True, blank=True) centroid = models.GeometryField(blank=True, null=True) assembly_name = models.CharField(max_length=35, blank=True) parliament_name = models.CharField(max_length=35, blank=True) class1_total_enr_boys = models.IntegerField(blank=True, null=True) class2_total_enr_boys = models.IntegerField(blank=True, null=True) class3_total_enr_boys = models.IntegerField(blank=True, null=True) class4_total_enr_boys = models.IntegerField(blank=True, null=True) class5_total_enr_boys = models.IntegerField(blank=True, null=True) class6_total_enr_boys = models.IntegerField(blank=True, null=True) class7_total_enr_boys = models.IntegerField(blank=True, null=True) class8_total_enr_boys = models.IntegerField(blank=True, null=True) class1_total_enr_girls = models.IntegerField(blank=True, null=True) class2_total_enr_girls = models.IntegerField(blank=True, null=True) class3_total_enr_girls = models.IntegerField(blank=True, null=True) class4_total_enr_girls = models.IntegerField(blank=True, null=True) class5_total_enr_girls = models.IntegerField(blank=True, null=True) class6_total_enr_girls = models.IntegerField(blank=True, null=True) class7_total_enr_girls = models.IntegerField(blank=True, null=True) class8_total_enr_girls = models.IntegerField(blank=True, null=True) total_boys = models.IntegerField(blank=True, null=True) total_girls = models.IntegerField(blank=True, null=True) new_pincode = models.IntegerField(null=True, blank=True) infered_assembly = models.CharField(max_length=256, blank=True, null=True) infered_parliament = models.CharField(max_length=256, blank=True, null=True) def __unicode__(self): return self.school_name
class GeoJsonLayer(models.Model): name = models.CharField(max_length=255) srid = models.PositiveIntegerField(default=WGS84_SRID) created_by = models.ForeignKey(User, null=True, editable=False) created_datetime = models.DateTimeField(auto_now_add=True, help_text="Datetime of when the data was loaded from file") opacity = models.FloatField(default=0.75, help_text="Suggested Layer Opacity") center = models.PointField(null=True, srid=METERS_SRID) description = models.TextField(blank=True) bounds_polygon = models.PolygonField( editable=False, srid=METERS_SRID) data = models.TextField(help_text="GeoJSON Text") objects = models.GeoManager() def clean(self): # try to load as json, if fails raise ValidationError try: loaded_geojson = json.loads(self.data) unique_ids = set() if "features" in loaded_geojson: # check features for 'id' attribute for f in loaded_geojson["features"]: if "id" not in f["properties"]: raise ValidationError("Features do not contain an 'id' attribute! (use 'geojson_increment_id.py' tool to add/increment feature ids)") else: id_value = f["properties"]["id"] if id_value in unique_ids: raise ValidationError("Features do not contain a UNIQUE 'id' properties attribute! (use 'geojson_increment_id.py' tool to add/increment feature ids)") else: unique_ids.add(id_value) except ValueError as e: raise ValidationError("INVALID GeoJSON: {}".format(str(e.args))) def get_data_bounds_polygon(self): parsed_geojson = json.loads(self.data) def get_polygons(obj): polys = [] if "type" in obj: if obj["type"] == "FeatureCollection": for feature in obj["features"]: extent_polys = get_polygons(feature) polys.extend(extent_polys) elif obj["type"] == "Feature": # process "geometry" geom = GEOSGeometry(json.dumps(obj["geometry"])) # get extent_poly of geom extent_poly = Polygon.from_bbox(geom.extent) polys.append(extent_poly) elif obj["type"] in ("Polygon", "LineString", "Point"): # process "geometry" geom = GEOSGeometry(json.dumps(obj)) # get extent_poly of geom extent_poly = Polygon.from_bbox(geom.extent) polys.append(extent_poly) return polys geojson_extent_polygons = [] if isinstance(parsed_geojson, list): for obj in parsed_geojson: polygons = get_polygons(obj) geojson_extent_polygons.extend(polygons) elif "type" in parsed_geojson and parsed_geojson["type"] in ("FeatureCollection", "Feature", "Polygon", "LineString", "Point"): polygons = get_polygons(parsed_geojson) geojson_extent_polygons.extend(polygons) # process polygons into polyons extent mploy = MultiPolygon(geojson_extent_polygons) mploy.srid = WGS84_SRID # Expected... mploy.transform(METERS_SRID) poly = Polygon.from_bbox(mploy.extent) poly.srid = METERS_SRID return poly def get_center(self): if not self.center: self.center = self.bounds_polygon.centroid self.save() return self.center def extent(self, as_wgs84=True): result = self.bounds_polygon.extent if as_wgs84: min_p = Point(*result[:2], srid=settings.METERS_SRID).transform(settings.WGS84_SRID, clone=True) max_p = Point(*result[2:], srid=settings.METERS_SRID).transform(settings.WGS84_SRID, clone=True) result = (min_p.x, min_p.y, max_p.x, max_p.y) return result def info(self): """ layer information dictionary to be converted to json """ layer_center_point = self.bounds_polygon.centroid if layer_center_point: layer_center_point.transform(WGS84_SRID) layer_unique_id = "{}:vector:{}".format(self._state.db, self.id) layer_info = { "name": self.name, "created_datetime": self.created_datetime.isoformat(), "id": layer_unique_id, "url": self.get_absolute_url(), "type": "GeoJSON", "extent": self.extent(), "opacity": self.opacity, } if layer_center_point: layer_info["centerlon"] = round(layer_center_point.x, 6) layer_info["centerlat"] = round(layer_center_point.y, 6) return layer_info def get_absolute_url(self): return "/vector/layer/{}/".format(self.id) def get_layer_url(self): return "http://{}:{}/vector/layer/{}/".format(settings.HOST, settings.PORT, self.id) def save(self, *args, **kwargs): if not self.bounds_polygon: poly = self.get_data_bounds_polygon() self.bounds_polygon = poly super(GeoJsonLayer, self).save(*args, **kwargs) # Call the "real" save() method. def create_map_layer(self): """ Create a layercollections.model.MapLayer for leaflet map display. :return: saved layercollections.model.MapLayer object """ app_label = "layercollections" MapLayer = apps.get_model(app_label, "MapLayer") m = MapLayer(name=str(self), attribution="Nokia", type="GeoJSON", opacity=self.opacity, center=self.get_data_bounds_polygon().centroid, url=self.get_layer_url()) m.save() return m def __str__(self): name = self.name if "/" in name or os.sep in name: name = os.path.split(name)[-1] return "GeoJsonLayer({}-{})".format(name, self.id)
class Signal(CreatedUpdatedModel): SOURCE_DEFAULT_ANONYMOUS_USER = '******' # we need an unique id for external systems. # TODO SIG-563 rename `signal_id` to `signal_uuid` to be more specific. signal_id = models.UUIDField(default=uuid.uuid4, db_index=True) source = models.CharField(max_length=128, default=SOURCE_DEFAULT_ANONYMOUS_USER) text = models.CharField(max_length=3000) text_extra = models.CharField(max_length=10000, default='', blank=True) location = models.OneToOneField('signals.Location', related_name='signal', null=True, on_delete=models.SET_NULL) status = models.OneToOneField('signals.Status', related_name='signal', null=True, on_delete=models.SET_NULL) category_assignment = models.OneToOneField('signals.CategoryAssignment', related_name='signal', null=True, on_delete=models.SET_NULL) categories = models.ManyToManyField('signals.Category', through='signals.CategoryAssignment') reporter = models.OneToOneField('signals.Reporter', related_name='signal', null=True, on_delete=models.SET_NULL) priority = models.OneToOneField('signals.Priority', related_name='signal', null=True, on_delete=models.SET_NULL) directing_departments_assignment = models.OneToOneField( 'signals.SignalDepartments', related_name='directing_department_signal', null=True, on_delete=models.SET_NULL) routing_assignment = models.OneToOneField('signals.SignalDepartments', related_name='routing_signal', null=True, on_delete=models.SET_NULL) user_assignment = models.OneToOneField( 'users.SignalUser', related_name='user_assignment_signal', null=True, on_delete=models.SET_NULL) type_assignment = models.OneToOneField('signals.Type', related_name='signal', null=True, on_delete=models.SET_NULL) # Date of the incident. incident_date_start = models.DateTimeField(null=False) incident_date_end = models.DateTimeField(null=True) # Date action is expected operational_date = models.DateTimeField(null=True) # Date we should have reported back to reporter. expire_date = models.DateTimeField(null=True) # file will be saved to MEDIA_ROOT/uploads/2015/01/30 upload = ArrayField(models.FileField(upload_to='uploads/%Y/%m/%d/'), null=True) # TODO: remove extra_properties = JSONField(null=True) # SIG-884 parent = models.ForeignKey(to='self', related_name='children', null=True, blank=True, on_delete=models.SET_NULL) objects = SignalQuerySet.as_manager() actions = SignalManager() @property def image(self): """ Field for backwards compatibility. The attachment table replaces the old 'image' property """ attachment = self.attachments.filter(is_image=True).first() return attachment.file if attachment else "" @property def image_crop(self): attachment = self.attachments.filter(is_image=True).first() return attachment.image_crop if self.image else '' class Meta: permissions = ( ('sia_read', 'Leesrechten algemeen'), # SIG-2192 ('sia_write', 'Schrijfrechten algemeen'), # SIG-2194 ('sia_split', 'Splitsen van een melding'), # SIG-2192 ('sia_signal_create_initial', 'Melding aanmaken'), # SIG-2192 ('sia_signal_create_note', 'Notitie toevoegen bij een melding'), # SIG-2192 ('sia_signal_change_status', 'Wijzigen van status van een melding'), # SIG-2192 ('sia_signal_change_category', 'Wijzigen van categorie van een melding'), # SIG-2192 ('sia_signal_export', 'Meldingen exporteren'), # SIG-2192 ('sia_signal_report', 'Rapportage beheren'), # SIG-2192 ) ordering = ('created_at', ) indexes = [ models.Index(fields=['created_at']), models.Index(fields=['id', 'parent']), ] def __init__(self, *args, **kwargs): super(Signal, self).__init__(*args, **kwargs) if not self.signal_id: self.signal_id = uuid.uuid4() def __str__(self): """Identifying string. DO NOT expose sensitive stuff here. """ # Fix for bug SIG-2486 Timezones were not consistently shown created_at = self.created_at field_timezone = timezone.get_current_timezone( ) if settings.USE_TZ else None if timezone.is_aware(created_at) and field_timezone: created_at = created_at.astimezone(field_timezone) elif timezone.is_aware(created_at): created_at = timezone.make_naive(created_at, utc) return f'{self.id} - ' \ f'{self.status.state if self.status else ""} - ' \ f'{self.location.buurt_code if self.location else ""} - ' \ f'{created_at.isoformat()}' @property def sia_id(self): """SIA identifier used for external communication. :returns: str """ return 'SIA-{id}'.format(id=self.id) def get_fqdn_image_crop_url(self): """Get FQDN image crop url. :returns: url (str) or None """ if not self.image_crop: return None is_swift = isinstance(self.image_crop.storage, SwiftStorage) if is_swift: return self.image_crop.url # Generated temp url from Swift Object Store. else: # Generating a fully qualified url ourself. current_site = Site.objects.get_current() is_local = 'localhost' in current_site.domain or settings.DEBUG fqdn_url = '{scheme}://{domain}{path}'.format( scheme='http' if is_local else 'https', domain=current_site.domain, path=self.image_crop.url) return fqdn_url def is_parent(self): # If we have children we are a parent return self.children.exists() def is_child(self): # If we have a parent we are a child return self.parent is not None @property def siblings(self): if self.is_child(): # If we are a child return all siblings siblings_qs = self.parent.children.all() if self.pk: # Exclude myself if possible return siblings_qs.exclude(pk=self.pk) return siblings_qs # Return a non queryset return self.__class__.objects.none() def _validate(self): if self.is_parent() and self.is_child(): # We cannot be a parent and a child at once raise ValidationError('Cannot be a parent and a child at the once') if self.parent and self.parent.is_child(): # The parent of this Signal cannot be a child of another Signal raise ValidationError('A child of a child is not allowed') if (self.pk is None and self.is_child() and self.siblings.count() >= settings.SIGNAL_MAX_NUMBER_OF_CHILDREN): # we are a new child and our parent already has the max number of children raise ValidationError( 'Maximum number of children reached for the parent Signal') def save(self, *args, **kwargs): self._validate() super(Signal, self).save(*args, **kwargs)
class price_change(models.Model): Property = models.ForeignKey(Property, on_delete=models.CASCADE) proposed_price = models.DecimalField( max_digits=8, decimal_places=2, help_text="The proposed new price for the property", null=False) notes = models.CharField(max_length=1024, blank=True) # meeting is the PriceChangeMeetingLink accessor datestamp = models.DateField(auto_now_add=True) approved = models.NullBooleanField() acquisition_date = models.DateField(null=True) assessed_land_value = models.IntegerField(null=True) assessed_improvement_value = models.IntegerField(null=True) cma = models.FileField(upload_to=price_change_directory_path, null=True, blank=True) make_fdl_eligible = models.BooleanField(default=False) @property def inquiries_previous_30_days(self): end_day = datetime.date.today() start_day = end_day - datetime.timedelta(30) return apps.get_model( 'property_inquiry', 'propertyInquiry').objects.filter(Property=self.Property).filter( timestamp__range=(start_day, end_day)).count() @property def inquiries_previous_60_days(self): end_day = datetime.date.today() start_day = end_day - datetime.timedelta(60) return apps.get_model( 'property_inquiry', 'propertyInquiry').objects.filter(Property=self.Property).filter( timestamp__range=(start_day, end_day)).count() @property def inquiries_previous_90_days(self): end_day = datetime.date.today() start_day = end_day - datetime.timedelta(90) return apps.get_model( 'property_inquiry', 'propertyInquiry').objects.filter(Property=self.Property).filter( timestamp__range=(start_day, end_day)).count() @property def inquiries_previous_180_days(self): end_day = datetime.date.today() start_day = end_day - datetime.timedelta(180) return apps.get_model( 'property_inquiry', 'propertyInquiry').objects.filter(Property=self.Property).filter( timestamp__range=(start_day, end_day)).count() def __str__(self): return '{0} - {1} - {2}'.format(self.Property, self.datestamp, self.proposed_price) class Meta: verbose_name = 'price change' verbose_name_plural = 'price changes'
class Operator(ValidateOnSaveMixin, models.Model): """An entity that operates public transport services""" id = models.CharField(max_length=10, primary_key=True) # e.g. 'YCST' name = models.CharField(max_length=100, db_index=True) slug = AutoSlugField(populate_from=str, unique=True, editable=True) vehicle_mode = models.CharField(max_length=48, blank=True) parent = models.CharField(max_length=48, blank=True) region = models.ForeignKey(Region, models.CASCADE) address = models.CharField(max_length=128, blank=True) url = models.URLField(blank=True) email = models.EmailField(blank=True) phone = models.CharField(max_length=128, blank=True) twitter = models.CharField(max_length=255, blank=True) payment_methods = models.ManyToManyField('PaymentMethod', blank=True) class Meta(): ordering = ('name',) def __str__(self): return str(self.name or self.id) national_expresses = { 'Hotel Hoppa': '24233768', 'National Express Airport': '24233764', 'National Express': '21039402', } national_expresses['National Express Shuttle'] = national_expresses['National Express'] national_expresses['Woking RailAir'] = national_expresses['National Express Airport'] def is_national_express(self): return self.name in self.national_expresses def get_national_express_url(self): return ( 'https://clkuk.pvnsolutions.com/brand/contactsnetwork/click?p=230590&a=3022528&g=' + self.national_expresses[self.name] ) def get_absolute_url(self): return reverse('operator_detail', args=(self.slug or self.id,)) def mode(self): return self.vehicle_mode def get_a_mode(self): """Return the the name of the operator's vehicle mode, with the correct indefinite article depending on whether it begins with a vowel. 'Airline' becomes 'An airline', 'Bus' becomes 'A bus'. """ mode = str(self.vehicle_mode).lower() if not mode or mode[0].lower() in 'aeiou': return 'An ' + mode # 'An airline' or 'An ' return 'A ' + mode # 'A hovercraft' @cached_property def get_licences(self): return self.operatorcode_set.filter(source__name='Licence')
class CDC(Overlay): CDCtype = models.CharField(max_length=50)
class PaymentMethod(models.Model): name = models.CharField(max_length=48) url = models.URLField(blank=True) def __str__(self): return self.name
class ContextArea(Overlay): disposition_strategy = models.CharField(max_length=50)
class SidconFillLevel(models.Model): """Container with sensors.""" class Meta: managed = settings.TESTING db_table = 'sidcon_container_states' id = models.IntegerField(primary_key=True) scraped_at = models.DateTimeField(blank=True, null=True) placement_date = models.DateTimeField(blank=True, null=True) communication_date_time = models.DateTimeField(blank=True, null=True) geometrie = models.PointField(blank=True, null=True) valid = models.NullBooleanField() _id = models.IntegerField() filling = models.IntegerField(blank=True, null=True) device_id = models.IntegerField(blank=True, null=True) entity_id = models.IntegerField(blank=True, null=True) status_id = models.IntegerField(blank=True, null=True) limit_full = models.IntegerField(blank=True, null=True) limit_near_full = models.IntegerField(blank=True, null=True) nr_press_strokes = models.IntegerField(blank=True, null=True) drum_action_count = models.IntegerField(blank=True, null=True) network_strenght = models.IntegerField(blank=True, null=True) status_incidents = models.IntegerField(blank=True, null=True) max_nr_press_strokes = models.IntegerField(blank=True, null=True) drum_position_status = models.IntegerField(blank=True, null=True) lock_position_status = models.IntegerField(blank=True, null=True) nr_press_strokes_to_go = models.IntegerField(blank=True, null=True) total_nr_press_strokes = models.IntegerField(blank=True, null=True) total_nr_empty_detected = models.IntegerField(blank=True, null=True) max_dump_count_on_dump_location = models.IntegerField(blank=True, null=True) # noqa successfull_transaction_since_reset = models.IntegerField( blank=True, null=True) # noqa unsuccessfull_transaction_since_reset = models.IntegerField( blank=True, null=True) # noqa container_id = models.IntegerField(blank=True, null=True), house_number = models.IntegerField(blank=True, null=True), press_status = models.IntegerField(blank=True, null=True), press_current = models.IntegerField(blank=True, null=True), description = models.CharField(max_length=200, blank=True, null=True) status_device = models.CharField(max_length=50, blank=True, null=True) container_name = models.CharField(max_length=50, blank=True, null=True) status_chip_cards = models.CharField(max_length=50, blank=True, null=True) status_container = models.CharField(max_length=50, blank=True, null=True) status_trigger_name = models.CharField(max_length=100, blank=True, null=True) # noqa status_configuration = models.CharField(max_length=50, blank=True, null=True) # noqa battery_voltage = models.FloatField(blank=True, null=True), volume_correction_factor = models.FloatField(blank=True, null=True), fraction = models.CharField(max_length=50, blank=True, null=True) # stadsdeel = models.CharField(max_length=1, blank=True, null=True) # buurt_code = models.CharField(max_length=4, blank=True, null=True) # first_weight = models.IntegerField(blank=True, null=True) # second_weight = models.IntegerField(blank=True, null=True) # net_weight = models.IntegerField(blank=True, null=True) short_id = models.IntegerField(blank=True, null=True)
class MVAClassifcation(Overlay): mva_cat = models.CharField(max_length=10)
class App(models.Model): name = models.CharField(max_length=200, null=True, blank=True) title = models.CharField(max_length=200, null=True, blank=True) description = models.TextField(null=True, blank=True) short_description = models.TextField(null=True, blank=True) app_url = models.URLField(null=True, blank=True) author = models.CharField(max_length=200, null=True, blank=True) author_website = models.URLField(null=True, blank=True) license = models.CharField(max_length=200, null=True, blank=True) tags = TaggableManager() date_installed = models.DateTimeField('Date Installed', auto_now_add=True, null=True) installed_by = models.ForeignKey(geonode_settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.PROTECT) single_instance = models.BooleanField(default=False, null=False, blank=False) category = models.ManyToManyField(AppType, related_name='apps') status = models.CharField(max_length=100, blank=False, null=False, default='Alpha') owner_url = models.URLField(null=True, blank=True) help_url = models.URLField(null=True, blank=True) app_img_url = models.TextField(max_length=1000, blank=True, null=True) rating = models.IntegerField(default=0, null=True, blank=True) contact_name = models.CharField(max_length=200, null=True, blank=True) contact_email = models.EmailField(null=True, blank=True) version = models.CharField(max_length=10) store = models.ForeignKey(AppStore, null=True, on_delete=models.PROTECT) order = models.IntegerField(null=True, default=0) default_config = JSONField(default={}) class meta(object): ordering = ['order'] def __str__(self): return self.title @property def settings_url(self): try: return reverse("%s_settings" % self.name) except BaseException as e: logger.error(e) return None @property def urls(self): admin_urls = logged_in_urls = anonymous_urls = None try: app_module = __import__(self.name) if hasattr(app_module, 'urls_dict'): urls_dict = getattr(app_module, 'urls_dict') if 'admin' in list(urls_dict.keys()): admin_urls = urls_dict['admin'] else: admin_urls = None if 'logged_in' in list(urls_dict.keys()): logged_in_urls = urls_dict['logged_in'] else: logged_in_urls = None if 'anonymous' in list(urls_dict.keys()): anonymous_urls = urls_dict['anonymous'] else: anonymous_urls = None except ImportError as e: logger.error(e) return (admin_urls, logged_in_urls, anonymous_urls) @property def open_url(self): from django.urls import reverse open_url = reverse('app_manager_base_url') + self.name try: app_module = __import__(self.name) if hasattr(app_module, 'OPEN_URL_NAME'): open_url = reverse(getattr(app_module, 'OPEN_URL_NAME')) except ImportError as e: logger.error(e) return open_url @property def create_new_url(self): from django.urls import reverse create_new_url = reverse('{}.new'.format(self.name)) try: app_module = __import__(self.name) if hasattr(app_module, 'CREATE_NEW_URL_NAME'): create_new_url = reverse( getattr(app_module, 'CREATE_NEW_URL_NAME')) except ImportError as e: logger.error(e) return create_new_url @property def admin_urls(self): return self.urls[0] @property def logged_in_urls(self): return self.urls[1] @property def anonymous_urls(self): return self.urls[2] @property def new_url(self): try: return reverse("%s.new" % self.name) except BaseException as e: logger.error(e) return None def set_active(self, active=True): app = CartoviewApp.objects.get(self.name, None) if app: app.active = active app.commit() CartoviewApp.save() return app @property def config(self): return CartoviewApp.objects.get(self.name, None)
class Tag(models.Model): value = models.CharField(max_length=128)