Skip to content
Advertisement

How to call a variable outside a validate() function which is inside the FlaskForm class

I have two def validate(self) functions within the RegistrationForm(FlaskForm). First function validates the user input if the car range is over 400km. The other function validates if the user lives far or close to work by calculating the distance between the user’s address and work address by means of geopy module. I’ve been told that def validate_field(self, field): function takes only one attribute which must be the same as the field name. In that function I have an extra variable total_travel_km that stores distance between work and user’s home. If user is validated than I need to store total_travel_km variable in DB.

Now the server brings me this message: ‘RegistrationForm’ object has no attribute ‘total_travel_km’

How can I call that total_travel_km variable correctly and write it inside DB

Here is the cut out from my code:

class RegistrationForm(FlaskForm):
    car_range = IntegerField('Car Range, km')
    home_address = StringField('Home Address')
    submit = SubmitField('Register User/Car')
    
    def validate_car_range(self, car_range):
        if car_range.data > 400:
            raise ValidationError('Your car range does not meet our requirements')

    def validate_home_address(self, home_address):
        user_loc = locator.geocode(home_address.data)
        user_coords = (user_loc.latitude, user_loc.longitude)
        one_way = geopy.distance.geodesic(tco_coords, user_coords).km
        total_travel_km = one_way*4
        if total_travel_km < self.car_range.data:
            raise ValidationError('You live too close to work')
        return total_travel_km

@app.route("/register", methods=['POST', 'GET'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User(car_range=form.car_range.data, home_address=form.home_address.data,
                    car_travel_km=form.total_travel_km)
        db.session.add(user)
        db.session.commit()

EDIT: I figured out. I had to pass form. instead of self. in validation method. Below is the correct code:

def validate_home_address(form, home_address):
            user_loc = locator.geocode(home_address.data)
            user_coords = (user_loc.latitude, user_loc.longitude)
            one_way = geopy.distance.geodesic(tco_coords, user_coords).km
            form.total_travel_km = one_way*4
            if form.total_travel_km < self.car_range.data:
                raise ValidationError('You live too close to work')
            return form.total_travel_km

Advertisement

Answer

Set a form instance variable in the validation method:

class RegistrationForm(FlaskForm):

    def __init__(self, *args, **kwargs):
        super(RegistrationForm, self).__init__(*args, **kwargs)
        self.total_travel_km = None

    def validate_home_address(self, home_address):
        user_loc = locator.geocode(home_address.data)
        user_coords = (user_loc.latitude, user_loc.longitude)
        one_way = geopy.distance.geodesic(tco_coords, user_coords).km
        total_travel_km = one_way * 4
        if total_travel_km < self.car_range.data:
            raise ValidationError('You live too close to work')
        # all good save the total travel in the form
        self.total_travel_km = total_travel_km

Also, you might not want to hard code the car range limit, you can pass a value when you instance the form:

class RegistrationForm(FlaskForm):

    def __init__(self, *args, **kwargs):
        super(RegistrationForm, self).__init__(*args, **kwargs)
        self.total_travel_km = None
        self.required_car_range = kwargs.get('required_car_range', 400)

    def validate_car_range(self, car_range):
        if car_range.data > self.required_car_range:
            raise ValidationError('Your car range does not meet our requirements')

and use as follows:

@app.route("/register", methods=['POST', 'GET'])
def register():
    form = RegistrationForm(required_car_range=600)
    if form.validate_on_submit():
        user = User(car_range=form.car_range.data, home_address=form.home_address.data,
                    car_travel_km=form.total_travel_km)
        db.session.add(user)
        db.session.commit()
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement