0

I am trying to figure out the best way to pass data between Flask requests when using redirect. Here is some of my code first,

models

class Customer(db.Model):
__tablename__ = 'customers'

id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(80))
last_name = db.Column(db.String(80))
email = db.Column(db.String(120), unique=True)
phone_number = db.Column(db.String(10), unique=True)
address = db.Column(db.Text)
last_order = db.Column(db.Text)
send_email = db.Column(db.Boolean)

def __init__(self, first_name, last_name, email, phone_number, address,
             last_order, send_email):
    self.first_name = first_name
    self.last_name = last_name
    self.email = email
    self.phone_number = phone_number
    self.address = address
    self.last_order = last_order
    self.send_email = send_email

def __repr__(self):
    return '<Customer {} {}>'.format(self.first_name, self.last_name)

views

blueprint = Blueprint('customer', __name__, url_prefix='/customer')


@blueprint.route('/', methods=('GET', 'POST'))
@login_required
def home():
    """Logged-in user homepage"""
    error = None
    form = CustomerSearchForm()
    if form.validate_on_submit():
        phone_number = form.phone_number.data
        customer = Customer.query.filter_by(phone_number=phone_number).first()
        if customer:
            return redirect(url_for('customer.customer', customer_id=customer.id))
        else:
            error = 'Customer with phone number {} not found'.format(phone_number)
    form.phone_number.data = ''
    return render_template('customer/index.html', form=form, error=error)


@blueprint.route('/<int:customer_id>', methods=('GET', 'POST'))
@login_required
def customer(customer_id):
    """Get customer by id"""
    customer = Customer.query.get(customer_id)
    return render_template('customer/customer.html', customer=customer, form=form)

So, write now, when I add a customer and I pass the id to the view customer with redirect(url_for('customer.customer')), I have to search for the customer again in the database and then render my template. I wanted help in determining if this is a correct/good approach? I know I cannot use g because doing redirect means a new request and hence g will not persist.

I can use session but then I found out that I have to do something like

session['customer'] = customer

where customer is an instance of Customer model, I will have a write a custom JsonEncoder where I will define how to encode the customer instance (Fixing the class to enable object storing in Flask session).

So, is it better to retrieve customer from database again using provided customer id or store customer object in session (using the custom JsonEncoder) or is there another better approach?

Community
  • 1
  • 1
ueg1990
  • 1,003
  • 2
  • 19
  • 39

2 Answers2

0

Yes, this is the correct approach. Querying twice isn't so expensive.

You can also try Message Flashing for showing something like error with redirect.

Tatsuyuki Ishi
  • 3,883
  • 3
  • 29
  • 41
0

Whether you should pass the objects across requests or do a new query depends on your integrity requirements.

If your business logic can't affort stale data, then do a query, caz database is the single state of truth, and the transaction can save you lots of troubles.

Otherwise, you can pass around data. And there are several ways:

1. A session object server side, which store inside memcached or something.
2. Cookies, which is not used that much I guess.
3. JWT, which I believe is the right approach.

jwt

Shuo
  • 8,447
  • 4
  • 30
  • 36
  • How would I use a JWT token? I want to pass data from one view to another view (via redirect) – ueg1990 Mar 11 '17 at 09:40
  • ok, does that i mean i still have to write a custom JsonEncoder to define how to encode my customer instance? – ueg1990 Mar 11 '17 at 10:01
  • https://github.com/jpadilla/pyjwt Check out the document, You can pass a dict object to it. – Shuo Mar 11 '17 at 10:04