├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── bcp ├── __init__.py ├── fonts │ ├── OCRA.ttf │ └── README ├── models.py ├── settings.py ├── static │ └── js │ │ └── pdfobject.min.js ├── templates │ ├── embed_example.html │ └── print.html ├── tests.py ├── urls.py └── views.py ├── docs └── example.png └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | *.pyc 4 | *.egg-info 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2014, Adlibre Pty Ltd. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of Adlibre Pty Ltd nor the names of its contributors may be used 15 | to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include README.md 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Barcode Printer for Django 2 | 3 | This is a reusable Django application which generates PDF barcodes in various formats with a human and machine (OCR-A) readable textual label. 4 | 5 | These barcodes are rendered as a PDF with embedded JavaScript which prompts the PDF to be immediately printed. 6 | 7 | Currently this is used by [Adlibre DMS](http://www.adlibre.com.au/adlibre-dms/) for document barcode generation, 8 | but this application is generic and can be reused in any Django app that requires barcode printing. 9 | 10 | [ReportLab](http://www.reportlab.com) is used for the barcode generation. And the following formats are supported: 11 | 12 | * Code39 (3 of 9), 13 | * Code128. 14 | 15 | However it would be trivial to add support for any format that ReportLab supports. 16 | 17 | ## Example 18 | 19 | Barcode automatically printing from URL: 20 | 21 |  22 | 23 | ## Installation 24 | 25 | If you use pip then the dependencies and requirements will be taken care of: 26 | 27 | Prod: 28 | 29 | pip install git+git://github.com/adlibre/django-bcp.git 30 | 31 | Dev: 32 | 33 | pip install -e git+git@github.com:adlibre/django-bcp.git#egg=bcp 34 | 35 | ## N.B. ReportLab Bug 36 | 37 | ReportLab 2.5/2.6 has a typo. "OpenActions" should be "OpenAction" as per ISO 32000-1:2008. 38 | 39 |
40 | diff -r broken/lib/python2.7/site-packages/reportlab/pdfbase/pdfdoc.py fixed/lib/python2.7/site-packages/reportlab/pdfbase/pdfdoc.py 41 | 1022c1022 42 | < Dests Outlines Pages Threads AcroForm Names OpenActions PageMode URI 43 | --- 44 | > Dests Outlines Pages Threads AcroForm Names OpenAction PageMode URI 45 |46 | 47 | You will need to manually patch this, otherwise the barcode will not automatically print: 48 | 49 | sed -i -e 's@OpenActions@OpenAction@g' lib/python*/site-packages/reportlab/pdfbase/pdfdoc.py 50 | -------------------------------------------------------------------------------- /bcp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adlibre/django-bcp/6ce7dd35cfc9c09961b363bddd1e89a35d6196ae/bcp/__init__.py -------------------------------------------------------------------------------- /bcp/fonts/OCRA.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adlibre/django-bcp/6ce7dd35cfc9c09961b363bddd1e89a35d6196ae/bcp/fonts/OCRA.ttf -------------------------------------------------------------------------------- /bcp/fonts/README: -------------------------------------------------------------------------------- 1 | OCR-A Font from http://sourceforge.net/projects/ocr-a-font/ 2 | 3 | Provided under Public Domain license. 4 | -------------------------------------------------------------------------------- /bcp/models.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adlibre/django-bcp/6ce7dd35cfc9c09961b363bddd1e89a35d6196ae/bcp/models.py -------------------------------------------------------------------------------- /bcp/settings.py: -------------------------------------------------------------------------------- 1 | # Settings for barcode printer 2 | 3 | import os 4 | 5 | # Barcode 6 | BAR_HEIGHT = 30 7 | BAR_WIDTH = 0.75 # default is 0.54 8 | BAR_QUIET = False # include l/r whitespace padding. 9 | BAR_CHECKSUM = True 10 | 11 | # Label Config 12 | FONT_SIZE = 10 13 | FONT_NAME = 'OCRA' 14 | FONT_PATH = os.path.join(os.path.split(__file__)[0], 'fonts', 'OCRA.ttf',) 15 | 16 | # NB It's a better idea to put your settings in a local_settings.py overrides file. 17 | try: 18 | from local_settings import * 19 | except ImportError: 20 | pass -------------------------------------------------------------------------------- /bcp/static/js/pdfobject.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | PDFObject v1.2.20111123 3 | https://github.com/pipwerks/PDFObject 4 | Copyright (c) Philip Hutchison 5 | MIT-style license: http://pipwerks.mit-license.org/ 6 | */ 7 | var PDFObject=function(h){if(!h||!h.url){return false}var e="1.2",c=h.id||false,d=h.width||"100%",p=h.height||"100%",g=h.pdfOpenParams,a,m,l,b,j,i,n,o,q,f,k;l=function(r){var s;try{s=new ActiveXObject(r)}catch(t){s=null}return s};b=function(){var r=null;if(window.ActiveXObject){r=l("AcroPDF.PDF");if(!r){r=l("PDF.PdfCtrl")}if(r!==null){return true}}return false};j=function(){var r,u=navigator.plugins,s=u.length,t=/Adobe Reader|Adobe PDF|Acrobat/gi;for(r=0;r
URL: {{ bcp_url }}
20 | 21 |[\w-]+)$', 'generate', name='bcp-generate'),
16 | url(r'^(?P(Standard39|Code128))/(?P[\w-]+)/print$', 'print_barcode', name='bcp-print'),
17 | url(r'^(?P(Standard39|Code128))/(?P[\w-]+)/test', 'print_barcode_embed_example', name='bcp-embed-example'),
18 |
19 | )
--------------------------------------------------------------------------------
/bcp/views.py:
--------------------------------------------------------------------------------
1 | """
2 | Module: Barcode Printer Views
3 | Project: Django BCP
4 | Copyright: Adlibre Pty Ltd 2012
5 | License: See LICENSE for license information
6 | """
7 |
8 | from django.http import HttpResponse
9 | from django.http import HttpResponseBadRequest
10 | from django.core.urlresolvers import reverse
11 | from django.shortcuts import render
12 |
13 | from django.conf import settings
14 |
15 | try:
16 | from cStringIO import StringIO
17 | except ImportError:
18 | from StringIO import StringIO
19 |
20 |
21 | def print_barcode_embed_example(request, code, barcode_type, template='embed_example.html'):
22 | """
23 | This is a test page showing how you can embed a request to print a barcode
24 | """
25 | bcp_url = reverse('bcp-print', kwargs = {'barcode_type': barcode_type, 'code': code,})
26 | context = { 'bcp_url': bcp_url, }
27 | return render(request, template, context)
28 |
29 |
30 | def print_barcode(request, code, barcode_type, template='print.html'):
31 | """
32 | This page causes the browser to request the barcode be printed
33 | """
34 | pdf_url = reverse('bcp-generate', kwargs = {'barcode_type': barcode_type, 'code': code,})
35 | context = { 'pdf_url': pdf_url, }
36 | return render(request, template, context)
37 |
38 |
39 | def generate(request, code, barcode_type='Standard39', auto_print=True):
40 | """
41 | Returns a PDF Barcode using ReportLab
42 | """
43 |
44 | from reportlab.graphics.shapes import String
45 | from reportlab.graphics import renderPDF
46 | from reportlab.graphics.barcode import createBarcodeDrawing
47 | from reportlab.pdfbase import pdfdoc
48 | from reportlab.pdfbase import pdfmetrics
49 | from reportlab.pdfbase.ttfonts import TTFont
50 |
51 | response = HttpResponse(mimetype='application/pdf')
52 | response['Content-Disposition'] = 'inline; filename=%s.pdf' % (code,)
53 |
54 | # Config
55 | import bcp.settings as bcp_settings
56 | font_size = bcp_settings.FONT_SIZE
57 | bar_height = bcp_settings.BAR_HEIGHT
58 | bar_width = bcp_settings.BAR_WIDTH
59 | font_name = bcp_settings.FONT_NAME
60 | font_path = bcp_settings.FONT_PATH
61 | try:
62 | # If this is extended to different barcode types, then these options will need to be specified differently, eg not all formats support checksum.
63 | bc = createBarcodeDrawing(barcode_type, barHeight=bar_height, barWidth=bar_width, value=str(code), isoScale=True, quiet=bcp_settings.BAR_QUIET, checksum=bcp_settings.BAR_CHECKSUM,)
64 | except KeyError, e:
65 | return HttpResponseBadRequest('Barcode Generation Failed: %s' % (e))
66 |
67 | # Register the font
68 | pdfmetrics.registerFont(TTFont(font_name, font_path))
69 |
70 | # Set JS to Autoprint document
71 | if auto_print:
72 | pdfdoc.PDFCatalog.OpenAction = '<>'
73 | pdfdoc.PDFInfo.title = code # nicety :)
74 |
75 | # Position for our text label
76 | x = bc.width / 2
77 | y = - font_size # or (bar_height + font_size) if placing on top
78 | # The textual barcode
79 | text = String(x, y, code, textAnchor='middle', fontName=font_name, fontSize=font_size)
80 | bc.add(text)
81 | bc = bc.resized() # resize barcode drawing object to accommodate text added
82 |
83 | buffer = StringIO() # buffer for the output
84 | renderPDF.drawToFile(bc, buffer, autoSize=1) # write PDF to buffer
85 |
86 | # Get the value of the StringIO buffer and write it to the response.
87 | pdf = buffer.getvalue()
88 | buffer.close()
89 | response.write(pdf)
90 |
91 | return response
--------------------------------------------------------------------------------
/docs/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adlibre/django-bcp/6ce7dd35cfc9c09961b363bddd1e89a35d6196ae/docs/example.png
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from setuptools import setup
4 |
5 | VERSION = '0.2.2'
6 |
7 | setup(name='django-bcp',
8 | version=VERSION,
9 | author="Andrew Cutler",
10 | author_email="andrew@adlibre.com.au",
11 | description="Barcode Printer for Django",
12 | license="BSD",
13 | long_description=open('README.md').read(),
14 | url='https://github.com/adlibre/django-bcp',
15 | packages=['bcp',],
16 | download_url='https://github.com/adlibre/python-bureaucrat/archive/v%s.tar.gz' % VERSION,
17 | classifiers=[
18 | "Development Status :: 5 - Production/Stable",
19 | "Environment :: Console",
20 | "Intended Audience :: Developers",
21 | "License :: OSI Approved :: BSD License",
22 | "Operating System :: Unix",
23 | "Programming Language :: Python",
24 | "Topic :: Utilities",
25 | ],
26 | install_requires=[
27 | 'django',
28 | 'reportlab>=2.6',
29 | ],
30 | package_data={'bcp': ['fonts/*', 'templates/*', ]},
31 | )
32 |
--------------------------------------------------------------------------------