Combining RFID, NFC and QRCodes with django-oscar online shop

You can write a lot of tutorials about making web apps. So to make something different lets talk about using some hardware and combine it with a shop. I'll show how to use RFID, NFC and QRCodes with a django-oscar based shop.

RFID is close range radio communication. It can be used in many places like in logistics to track packages, or for identification cards. You need a RFID reader and a RFID tag with the radio device. The tag may be a sticker, a clip or something else (a lot of shape and sizes). The the tag is put close to the reader the electromagnetic field induces current in the tag that powers the radio devices. It sends back data to the reader. In most simple RFID standards it will be just unique identification number. In writable tags it may be an URL pointing to the product on the website.

In a real shop RFID tags may replace price stickers. Salesman may present a luxury product by placing it on a plate which will have RFID reader built in. The reader will read the tag sticked the product and display details, price, pictures on a screen nearby. In bigger shops RFID reader may replace plain price checkers that scan product bar codes (or the bar code scanner may do more than just show price).

NFC is radio communication used in some smartphones or tablets. It's compatible with one of RFID standards - Mifare. It works like plain RFID I described before, but it allows writing data to the tag. Instead of RFID reader you use the smartphone to read it. NFC standard allow writing URL, email, address bookmark or text. A NFC tag just like a QRCode may contain a link to a product page on your online shop. As NFC is available in some devices (not all) it's not very widespread yet and it's often combined with QRCodes. Compared to QRCode you don't have to point phone camera on it, you just have to put the phone above it.

One of interesting NFC/QRCode usages is virtual poster shops - you place a poster in subways, train stations and other places where a lot of people pass it every day. The poster has pictures of products you may buy. To pick a product you scan its QRCode or its NFC tag. Both contain a link which adds the product to the basket. Scanning multiple products gives multiple products in basket. Then quick online payments and you are done. The products may be delivered at given address, or after work to your home or you favorite pickup stand.

In more advanced poster-shops there is also dedicated mobile application that shortens the add-to-cart path. You have to make the app, and users must download it but you get the scanner (QRCoder/NFC) and basket on one view. Without such app users scans the tag, opens the website and then he closes it to scan again (for QRCode he needs to open the scanning app).

RFID reader and showing product details

Simplest RFID is Unique working at 125 kHz. Tags following this standard just give you their unique ID and you can't write any data. USB readers work like additional keyboards and they don't require any additional drivers or software. When the reader reads a tag it will print the number and "press" Enter (new line character). If at such moment you will have your browser open and you will focus on an input field in a form the reader will put the ID in the field and the "Enter" will submit the form.

I will use a basic shop based on django-oscar. Download link for the whole app is at the end of this article.

To find a product by a RFID tag ID you need to bind it to the product first. For a simple example we can use a CharField in a product model, but if you have multiple real-world shops with the same product you will have multiple tags for one product. On larger scale you would rather want to use Mifare/NFC to just write product URL to multiple tags.

Here is a basic example model with a CharField:

class Product(abstract_models.AbstractProduct):
    token = models.CharField("RFID Token", blank=True, max_length=10)
We also need a view:
class RFIDProductRedirectView(generic.TemplateView):
    template_name = 'rfid.html'

    def post(self, request, **kwargs):
            product = self._get_product(request.POST.get('rfid_token', None))
        except Product.DoesNotExist:
            url = self._get_fail_url()
            url = self._get_success_url(product)
        return HttpResponseRedirect(url)

    def _get_product(self, rfid_token):
        return Product.objects.get(token=rfid_token)

    def _get_success_url(self, product):
        return reverse('catalogue:detail',
                       kwargs={'product_slug': product.slug, 'pk':})

    def _get_fail_url(self):
        return reverse('rfid')

rfid_view = RFIDProductRedirectView.as_view()
It's quite basic view that handles a form (it should be FormView by the way). If it can find a product by the RFID token ID it will redirect to the product detail page. The template is also simple:
{% extends "layout.html" %}

{% block content %}
    <form method="post" action="./">
    {% csrf_token %}
        <input type="text" name="rfid_token" class="rfid-input">
{% endblock %}

{% block extrascripts %}
    {{ block.super }}
    $(function() {

        function prepareRFIDForm() {
            var input = $('.rfid-input');
{% endblock %}

The template sets focus on the form field after loading the page. For a real application this template must be much better. It has to work without fixing/doing something with a mouse or keyboard (you won't have those usually in such display systems). If the network connection is done it shouldn't redirect to an broken not loaded URL... and it shouldn't redirect at all as it must be ready to scan a new tag at any time. You could use Angular.js or Ember.js for such interface.

It works like so:

NFC/QRCode and shopping from a poster

You can easily get a lot of NFC tag stickers and write URL to them using one of mobile applications like Tagstand Writer (on Android). QRCodes may be easily generated by one of Python libraries.

NFC sticker

The tag or QRCode must open a link that will add a product to the basket. The basket must survive between closing and opening the browser when scanning multiple products (this part is covered by django-oscar).

The view looks like so:

class AddToBasketFromLink(generic.View):
    def get(self, request, **kwargs):
        pk = self.kwargs.get('product', None)
        url = self._get_basket_url()
        return HttpResponseRedirect(url)

    def _add_product_to_basket(self, pk):
            product = self._get_product(pk)
        except Product.DoesNotExist:
            messages.add_message(self.request, messages.ERROR, 'No such product')
            messages.add_message(self.request, messages.SUCCESS, 'Product added to basket')

    def _get_product(self, pk):
        return Product.objects.get(pk=pk)

    def _add_to_basket(self, product):

    def _get_basket_url(self):
        return reverse('basket:summary')

add_to_basket_from_link = AddToBasketFromLink.as_view()

The view tries to fetch a product by its PK given in the URL. If the product exists it will be added to the basket. In the end the view redirects to the basket summary page.

It works something like this (except asking which browser to use as I have few for testing):

Post shop needs Internet access so it would be nice to provide a free WiFi (like for example with a 3G router). You will also provide clear instructions how to buy using such poster.

You can download the whole Django project and play with it (the code is in rfidshop/apps/catalogue).

RFID and NFC security

New technology has new security problems. For NFC or other writable tags there are few issues like unauthorized modification of data (if they aren't protected from new writes) or tag switching to one pointing to a malicious website. If you plan to use RFID or NFC you have to take such security issues into account.


Django web framework tutorials, 5 August 2013

Comment article
Comment article RkBlog main page Search RSS Contact