class GentityGenericDataForm(ModelForm): station_objects = Station.objects.all() if len(settings.ENHYDRIS_SITE_STATION_FILTER) > 0: station_objects = station_objects.filter( **settings.ENHYDRIS_SITE_STATION_FILTER) gentity = forms.ModelChoiceField(station_objects, label='Station', empty_label=None) data_type = forms.ModelChoiceField( GentityGenericDataType.objects, label='Data type', widget=SelectWithPop(model_name='gentitygenericdatatype')) class Meta: model = GentityGenericData exclude = [] def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) gentity_id = kwargs.pop('gentity_id', None) super(GentityGenericDataForm, self).__init__(*args, **kwargs) if user and not user.is_superuser: perms = user.get_rows_with_permission(Station(), 'edit') ids = [p.object_id for p in perms] self.fields["gentity"].queryset = Station.objects.filter( id__in=ids) if gentity_id: self.fields["gentity"].queryset = Station.objects.filter( id=gentity_id)
class StationForm(GpointForm, GentityForm): """ In this form, we overide the default fields with our own to allow inline creation of models that a Station has foreign keys to. To achieve this we use a custom widget which adds in each select box a 'Add New' button which takes care of the object creation and also updating the original select box with the new entries. The only caveat is that we need to pass manually to the widget the name of the foreign object as it is depicted in our database in cases where the field name is not the same. """ class Meta: model = Station exclude = ('overseers', 'creator', 'point') if not settings.ENHYDRIS_USERS_CAN_ADD_CONTENT: exclude = exclude + ('maintainers', ) political_division = forms.ModelChoiceField( PoliticalDivision.objects, widget=SelectWithPop(model_name='politicaldivision'), required=False) water_basin = forms.ModelChoiceField( WaterBasin.objects, widget=SelectWithPop(model_name='waterbasin'), required=False) water_division = forms.ModelChoiceField( WaterDivision.objects, widget=SelectWithPop(model_name='waterdivision'), required=False) # owner should be modified to allow either Person or Organization add owner = forms.ModelChoiceField(Lentity.objects, widget=SelectWithPop(model_name='lentity')) if settings.ENHYDRIS_USERS_CAN_ADD_CONTENT: maintainers = AutoCompleteSelectMultipleField('maintainers', required=False) def clean_altitude(self): value = self.cleaned_data['altitude'] if not value is None and (value > 8850 or value < -422): raise forms.ValidationError( _("%f is not a valid altitude") % (value, )) return self.cleaned_data['altitude']
class TimeseriesForm(ModelForm): """ This form extends the basic Timeseries model with a file field through which a user may upload additional data. """ gentity = forms.ModelChoiceField(Gentity.objects.all(), empty_label=None, label='Station') instrument = forms.ModelChoiceField(Instrument.objects.all(), required=False, label='Instrument') variable = forms.ModelChoiceField( Variable.objects, widget=SelectWithPop(model_name='variable')) unit_of_measurement = forms.ModelChoiceField( UnitOfMeasurement.objects, widget=SelectWithPop(model_name='unitofmeasurement')) time_zone = forms.ModelChoiceField( TimeZone.objects, widget=SelectWithPop(model_name='timezone')) time_step = forms.ModelChoiceField( TimeStep.objects, widget=SelectWithPop(model_name='timestep'), required=False) interval_type = forms.ModelChoiceField(IntervalType.objects, required=False) class Meta: model = Timeseries exclude = [] def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) gentity_id = kwargs.pop('gentity_id', None) instrument_id = kwargs.pop('instrument_id', None) super(TimeseriesForm, self).__init__(*args, **kwargs) if user and not user.is_superuser: perms = user.get_rows_with_permission(Station(), 'edit') ids = [p.object_id for p in perms] self.fields["gentity"].queryset = Station.objects.filter( id__in=ids) perms = user.get_rows_with_permission(Instrument(), 'edit') ids = [p.object_id for p in perms] self.fields["instrument"].queryset = Instrument.objects.filter( id__in=ids) if gentity_id: self.fields["gentity"].queryset = Station.objects.filter( id=gentity_id) self.fields["instrument"].queryset = Instrument.objects.filter( station__id=gentity_id) if instrument_id: self.fields["instrument"].queryset = Instrument.objects.filter( id=instrument_id) self.fields["instrument"].empty_label = None def clean_data(self): # Check if file contains valid timeseries data. if ('data' not in self.cleaned_data) or not self.cleaned_data['data']: return None self.cleaned_data['data'].seek(0) ts = timeseries.Timeseries() data = self.cleaned_data['data'] try: ts.read_file(self.cleaned_data['data']) except Exception as e: raise forms.ValidationError(str(e)) return self.cleaned_data['data'] def clean(self): """ This function checks the timestep and offset values and reports inconsistencies. """ time_step = self.cleaned_data.get('time_step', None) nominal_offset_minutes = self.cleaned_data.get( 'nominal_offset_minutes', None) nominal_offset_months = self.cleaned_data.get('nominal_offset_months', None) actual_offset_minutes = self.cleaned_data.get('actual_offset_minutes', None) actual_offset_months = self.cleaned_data.get('actual_offset_months', None) if not time_step: if nominal_offset_minutes or nominal_offset_months or \ actual_offset_minutes or actual_offset_months: raise forms.ValidationError( _("Invalid Timestep: If time step is" " null, the offsets must also be null!")) else: if actual_offset_minutes is None or actual_offset_months is None: raise forms.ValidationError( _("Invalid offset: If time step is" " not null, actual offset values must be provided!")) if (nominal_offset_minutes is None and nominal_offset_months is not None) \ or (nominal_offset_minutes is not None and nominal_offset_months is None): raise forms.ValidationError( _("Invalid offsets: Nominal" " offsets must be both null or both not null!")) #add a validation test for instrument in station: instr = self.cleaned_data.get('instrument', None) if instr: stat = self.cleaned_data.get('gentity', None) assert (stat) if Instrument.objects.filter(id=instr.id, station__id=stat.id).count() < 1: raise forms.ValidationError( _("Selected instrument " "not in selected station")) # XXX: This is not a good idea but it's the only way to handle append # errors. We save the data in the clean function instead of the save # and if an error occurs we show the error in the form. Another way # would be to write a try_append() function in pthelma.timeseries but # this is specific to enhydris and should not be part of the pthelma # module. if 'data' in self.cleaned_data and self.cleaned_data['data']: data = self.cleaned_data['data'] ts = timeseries.Timeseries(int(self.instance.id)) data.seek(0) ts.read_file(data) if self.cleaned_data['data_policy'] == 'A': try: ts.append_to_db(db.connection, commit=False) except Exception, e: raise forms.ValidationError(_(e.message)) return self.cleaned_data