QR Code link to open up a form with database row

Happy New Year all!

Has anyone got some suggestions as how to structure an app to achieve the following:

  1. Generate a QR code relating to a specific database row
  2. Use a smart phone camera to scan the qr code and link to the app (straight from the camera not with in the Anvil app)
  3. The link directs to a specific form and loads the database row as the item.

Would Hash Routing be the way to go with this or have I overlooked something here? HTTP endpoint? I know less than zero about HTTP so would rather avoid investing time learning if this is not the best path but this does look promising:

Hi @rickhurlbatt, HTTP API is likely your best bet if you just need data without UI. It is very easy to make with anvil. Just follow the code in the docs and it will work without any issue.

Since you nees to open a form, Hash Routing is more suitable

1 Like

for the generating a qrcode i’d probably give each row a unique id which you can reference as part of a url with a hash or as an api endpoint

something like this should work on the server to generate qr codes.

import uuid
import pyqrcode

@anvil.server.callable
def add_row(data):
  uid = str(uuid.uuid4())
  qrcode = get_qr_code(f"{anvil.server.get_app_origin()}/#{uid}", uid)
  # generate a url to later use with anvil.get_url_hash() (or HashRouting)
  # or use an api endpoint instead
  app_tables.my_table.add_row(**data, uid=uid, qrcode=qrcode)
  
def get_qr_code(url, uid):
  # from pyqrcode docs
  code = pyqrcode.create(url, error='L', version=27, mode='binary')
  file = f'/tmp/{uid}.png'
  code.png(file, scale=6, module_color=[0, 0, 0, 128], background=[0xff, 0xff, 0xcc])
  with open(file, 'rb') as f:
    media = anvil.BlobMedia('image/png', f.read(), uid)
  return media

as for opening the qrcode - I think most modern smart phone cameras that recognise a qrcode url will display a popup that asks if you want to open the url.

3 Likes

Thanks @Tony.Nguyen

@stucork I presume the UID is to account for any changes in Row IDs?

I guess this will have to wait until after I have added a custom domain so I don’t regenerate QR codes.

Thanks again

yes - the uid was just something unique to the data row that wasn’t relying on the row ids (row ids are not guaranteed to be the same for all time so shouldn’t be relied upon here).

You could always generate a script to update all your QR codes in the future.
It could even be a small separate app that shares the table so that it doesn’t clutter your main app.
(it might need to be a background task depending on the number of rows)

Ok thanks, I think I have a handle on it now, will report back when I make the time to build this.

Thanks @stucork, hopefully that information will be added into docs soon

@stucork qr code and uid is working well thank you but I am struggling to understand how to use the hashed url to open up the form. I have got this working but it seems too simple so I wonder if I have done it in a short-cutty way.

Method

  1. Create uid and qr code as described above and save to the data table row
  2. in the main form (which is the start up form) open the deisred form if the app was accessed by qr code scanning:
class SupplierMain(SupplierMainTemplate):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)
    if get_url_hash():
      # Search and return the row
      requested_item = anvil.server.call('get_item_by_uid', get_url_hash()) 

      # Open the form with the returned row as the item
      open_form(ViewItem(item = requested_item))

    # then the rest of the code out side the if statement

This works well and only opens the ViewItem form when accessed by scanning the qr code.
But like I said, seems too easy. Any feedback would be appreciated.

It’s generally not best practice to do open_form inside of an init method. Because the main form hasn’t loaded yet before you open a new one.

I would move this logic to a startup module which decides whether to open the ViewItem form based on the QR code, or open the main Supplier form.

Otherwise this is exactly what I’d do.

An example of a startup module

2 Likes