Django Generate Barcode With Reportlab

Fundor333 | | Reading time 3 minutes | Word count 605

#####


After Django With Barcode and Qrcode and Django Return Pdf With Reportlab I need something new in my Django server. I need a barcode generator for labeling stuffs.

The problem

Every code is a solution to a pratical problem. In this case I need to make the barcode labels with text for keep an inventory. The basic solution is generate a pdf/img file to print into sticker’s paper and cut it after.

Barcode Example

So, I need the data to convert into lable (the string on top to the barcode) and the barcode (or the qrcode) as in the screenshot, so I wrote this code for do it for pages and ready to print and stick it all around the world!

Code

The view

This code is the view for generating download link for the pdf with all the barcode.

from django.views.generic import View

class ExampleBarcodePdf(View):
    bar_height = None
    position_text_y = None
    filename = "ExampleBarCode.pdf"

    def get(self, request, *args, **kwargs):
      super().get(request, *args, **kwargs)
      response = HttpResponse(content_type="application/pdf")
      response["Content-Disposition"] = (
          'attachment; filename="' + self.filename + '"'
      )
      a4p = A4PrinterBarcode()
      pdf = a4p.get_pdf(
          buffer=BytesIO(),
          datas=[{barcode:"0000000000000", "label"}, {"999999999999", "other label"}],
          bar_height=self.bar_height,
          position_text_y=self.position_text_y,
      )
      response.write(pdf)
      return response

The pdf generator

This is the “printer” the code for generate pdf. After the import you find the constant with define the pdf.ß

from reportlab.graphics.barcode.eanbc import Ean13BarcodeWidget
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.shapes import String
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas

PAGESIZE = A4
NUM_LABELS_X = 3
NUM_LABELS_Y = 8
BAR_WIDTH = 1.5
BAR_HEIGHT = 51.0
TEXT_Y = 80
BARCODE_Y = 17
FONT_SIZE = 8

LABEL_WIDTH = PAGESIZE[0] / NUM_LABELS_X
LABEL_HEIGHT = PAGESIZE[1] / NUM_LABELS_Y
SHEET_TOP = PAGESIZE[1]


class A4PrinterBarcode:

    def generate_label(
        self,
        ean13: str,
        description: str,
        label_w: float = 0.0,
        label_h: float = 0.0,
        bar_with: float = BAR_WIDTH,
        bar_height: float = BAR_HEIGHT,
        postion_text_y: float = TEXT_Y,
        font_size: int = FONT_SIZE,
    ) -> Drawing:
        """
        Generate a drawing with EAN-13 barcode and descriptive text.
        :param ean13: The EAN-13 Code.
        :type ean13: str
        :param description: Short product description.
        :type description: str
        :return: Drawing with barcode and description
        :rtype: Drawing
        """
        if label_w == 0.0:
            label_w = A4[0] / NUM_LABELS_X
        if label_h == 0.0:
            label_h = A4[1] / NUM_LABELS_Y
        text = String(
            0,
            postion_text_y,
            description,
            fontName="Helvetica",
            fontSize=font_size,
            textAnchor="middle",
        )
        text.x = label_w / 2

        barcode = Ean13BarcodeWidget(ean13)
        barcode.barWidth = bar_with
        barcode.barHeight = bar_height
        _, _, bw, _ = barcode.getBounds()
        barcode.x = (label_w - bw) / 2  # center barcode
        barcode.y = 18  # spacing from label bottom (pt)

        label_drawing = Drawing(label_w, label_h)
        label_drawing.add(text)
        label_drawing.add(barcode)
        return label_drawing

    def get_pdf(
        self,
        buffer,
        datas: list,
        bar_height: float = None,
        position_text_y: float = None,
    ) -> bytes:
        if bar_height is None or bar_height < 0:
            bar_height = BAR_HEIGHT
        if position_text_y is None or position_text_y < 0:
            position_text_y = TEXT_Y
        p = canvas.Canvas(buffer)
        j = 0
        for _ in range(len(datas) // (NUM_LABELS_X * NUM_LABELS_Y) + 1):
            for u in range(0, NUM_LABELS_Y):
                for i in range(0, NUM_LABELS_X):
                    if j < len(datas):
                        data = datas[j]
                        cb = data.barcode
                        desc = data.label
                        try:
                            label = self.generate_label(
                                ean13=cb,
                                description=desc,
                                bar_height=bar_height,
                                postion_text_y=position_text_y,
                            )
                            x = i * LABEL_WIDTH
                            y = SHEET_TOP - LABEL_HEIGHT - u * LABEL_HEIGHT
                            label.drawOn(p, x, y)
                        except AttributeError:
                            pass
                        j += 1
            p.showPage()
        p.save()
        pdf = buffer.getvalue()
        buffer.close()
        return pdf

So how do A4PrinterBarcode work ?

The main concept of this class is to generate the “labels” (barcode and text) and put them into a grid pattern. So we have two function:

  • generate_label generate the single “label”, one of the time
  • get_pdf generate the pdf putting the “labels” in a grid pattern

If you need, this class can be used without Django, in something like a tool for terminal

This post is part of the Printing With ReportLab series
  1. Letterhead With ReportLab
  2. Django Return Pdf With Reportlab
  3. Django Generate Barcode With Reportlab
This post is part of the Django Tricks series
  1. Django Rest Framework: Multiple post
  2. Make a Excel Django combo
  3. Django With Barcode and Qrcode
  4. Django Return Pdf With Reportlab
  5. Django List View With Show More
  6. Message and Allert With Django and Boostrap
  7. Csv From Django
  8. Django Generate Barcode With Reportlab



Comments

To reply to this post, you can send a Webmention or you can toot me at [email protected]

With an account on the Fediverse or Mastodon, you can respond to this post. Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one. Known non-private replies are displayed below.


You mentioned this post on your site? Send a Webmention


See Also