Django JSignature Templated Docs - django

I am utilizing Django 4.1.3, templated_docs, and Jsignature. I am hoping to be able to place the signature image generated by jsignature directly to the document.
I have attempted almost every combination of utilizing Draw_signature, templated_docs {% image %}, and even {{form.media}} {{form.field}} noted in Jsignature.
any insight here is helpful.
from templated_docs import fill_template
from templated_docs.http import FileResponse
from django.http import HttpResponseNotFound
from invoiceManager.models import Invoice
from jsignature.utils import draw_signature
def invoice_view(request, **kwargs):
pk = kwargs.get('pk', None)
if pk:
# try:
invoice = Invoice.objects.get(pk=pk)
information = {
'repairDate': invoice.repair_date,
'claim': invoice.claim_authorization_number,
'customerName': invoice.customer.name,
'customerAddress': invoice.customer.address,
'customerCityStateZip': f'{invoice.customer.city} {invoice.customer.state.abbreviation}, {invoice.customer.zip_code}',
'customerPhone': invoice.customer.phone_number,
'insuranceName': invoice.insurance.name,
'policyNumber': f'policy Number: {invoice.policy_number}',
'VIN': f'VIN: {invoice.vehicle_information.vin}',
'YMM': f'{invoice.vehicle_information.year} {invoice.vehicle_information.make} {invoice.vehicle_information.model}',
'customerSignature': draw_signature(invoice.signature),
'technician': invoice.technician.name,
'location': invoice.business_location.name,
'submissionDate': invoice.invoice_submission_date,
'amount':invoice.invoice_amount,
}
repairLocations = {f'RL{x}':"Repair Made" for x in invoice.location_of_repairs.all().values_list('id', flat=True).order_by().distinct()}
information.update(repairLocations)
filename = fill_template(
'docs/base_invoice.odt', information,
output_format=".pdf")
visible_filename = 'invoice{}'.format(".pdf")
return FileResponse(filename, visible_filename)

I rewrote the image tag to accept a path allowing the use of jsignature.draw_siganture(, as_file=True). Creating a temp file that can be referenced by PIL and then redrawn -- less than ideal, but allowed to maintain aspect ratio/size of the jsignature field.
from PIL import Image
from django.utils.html import escape
from django import template
register = template.Library()
PIXEL_TO_CM = 0.00846666
class ImageNode(template.Node):
def __init__(self, value):
self.value = template.Variable(value)
def render(self, context):
self.value = self.value.resolve(context)
images = context.dicts[0].setdefault('ootemplate_imgs', {})
id = len(images)
z_index = id + 3 # Magic
photo = Image.open(self.value)
width = photo.size[0] * PIXEL_TO_CM
height = photo.size[0] * PIXEL_TO_CM
return ('<draw:frame draw:style-name="gr%(z_index)s" '
'draw:name="Signature" '
'text:anchor-type="char" svg:width="%(width)fcm" '
'svg:height="%(height)fcm" draw:z-index="%(z_index)s">'
f'<draw:image xlink:href="{self.value}" '
'xlink:type="simple" xlink:show="embed" '
'xlink:actuate="onLoad"/></draw:frame>') % locals()
#register.tag
def template_image(parser, token):
_, path = token.split_contents()
return ImageNode(path)

Related

How to compare queryset size with another queryset?

I have three querysets and I want the maximum size among all.
from django.shortcuts import render
from .models import Resources, Journey_template, Topic_Table, Subtopic_Table
def Journey_view(request) :
if (Journey_template.objects.filter(subtopic_id=1).exists()):
# obj = Journey_template.objects.filter(subtopic_id=1)
completed_obj = Journey_template.objects.filter(subtopic_id=1, status='completed')
pending_obj = Journey_template.objects.filter(subtopic_id=1, status='pending')
skipped_obj = Journey_template.objects.filter(subtopic_id=1, status='skipped')
# print(completed_obj.count(), pending_obj.count(), skipped_obj.count())
# print(obj.count())
# return render(request,'journey-page.html',{'data': obj})
else:
obj = Resources.objects.filter(topic_id=1,subtopic_id=1)
# Id = Topic_Table.objects.get(id=topic_id)
for resource in obj:
print(resource.resource_id)
Journey_template(subtopic_id=resource.subtopic_id, resource_id=resource, topic_id=topic_id).save()
return render(request,'journey-page.html',{'completed' : completed_obj, 'pending' : pending_obj, 'skipped' : skipped_obj})
Is there any inbuilt function which returns maximum size.

How to convert Textinput text to a matrix

I am new to kivy/python. I wanted to test my programming skills, so I modified this code off a post. It take texts as numbers from the textinput and converts them into a matrix and performs an operation. It works perfectly for positive numbers, however I want to capture negative numbers as well. But that always gives an error.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
class Screen(GridLayout):
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
self.input = TextInput(multiline=False, size_hint = (None, None))
self.add_widget(self.input)
self.input.bind(on_text_validate=self.print_input)
def print_input(self, value):
"""function to convert Textinput text into a matrix"""
ans1 = [i for i in list(value.text) if i != ',']
new = []
for i in range(len(ans1)):
if ans1[i] == "-":
n = ans1[i] + ans1[i + 1] # concatenate "-" and the next item after it
ans1.remove(ans1[i]) # delete "-"
ans1.remove(ans1[i+1]) # delete the next element after "-"
new.append(n)
new.append(ans1[i])
# the list new can now be converted into a matrix of which dimension depends on the list
class MyApp(App):
def build(self):
return Screen()
if __name__ == '__main__':
MyApp().run()
This is the error I keep getting:
if ans1[i] == "-":
IndexError: list index out of range
Hurray! I have seen the magic. The secret was string.split()
This is the modified code. Works perfectly for both positive and
negative entries.
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from sympy import *
class Screen(GridLayout):
def __init__(self, **kwargs):
super(Screen, self).__init__(**kwargs)
self.input = TextInput(multiline=False, size_hint = (None, None))
self.add_widget(self.input)
self.input.bind(on_text_validate=self.print_input)
def print_input(self, value):
"""function to convert Textinput text into a matrix. works
for only square matrices"""
m = 3; n = 3 # rows and columns
list = [float(el) for el in value.text.split(',')] # entries must be separated with ','
mat = Matrix(list)
mat1 = mat.reshape(3, 3) # can be made general
pprint(mat1)
class MyApp(App):
def build(self):
return Screen()
if __name__ == '__main__':
MyApp().run()

How to call the next page in my parse - Scrapy

I've tried everything but I can't seem to figure it out how I can call the next page in the parse_category.
I've tried LinkExtractor as I do when I go directly to a catergory page but this didn't work.
import scrapy.selector
import urlparse
from scrapy.spiders import CrawlSpider, Rule
from scrapy.http import Request
from msh_final.items import CrawlerMshFinalItem
def complete_url(string):
return "http://www.mediamarkt.be" + string
def get_base_url(url):
if url != "":
u = urlparse.urlparse(url)
return "%s://%s" % (u.scheme, u.netloc)
else:
return ""
def encode(str):
return str.encode('utf8', 'ignore')
class msh_finalSpider(CrawlSpider):
name = 'msh_final'
start_urls = ['http://www.mediamarkt.be/mcs/productlist/_Telefoon-Navigatie,98952,509451.html?langId=-17']
def parse(self, response):
items = response.xpath('//ul[#class="infield cf"]//div[#class="infield-wrapper"]/h2/a/#href')
for item in items:
link = item.extract()
yield Request(complete_url(link), callback=self.parse_category)
def parse_category(self, response):
items = response.xpath("//ul[#class='products-list']/li/div")
for item in items:
msh = CrawlerMshFinalItem()
msh['item_price'] = encode(item.xpath('normalize-space(.//aside/div/div/div/text())').extract()[0])
msh['item_name'] = encode(item.xpath('normalize-space(.//div/h2/a/text())').extract()[0])
yield msh
You should inherite your spider from Spider instead of CrawlSpider and use following code:
class msh_finalSpider(Spider):
name = 'msh_final'
start_urls = ['http://www.mediamarkt.be/mcs/productlist/_Telefoon-Navigatie,98952,509451.html?langId=-17']
def parse(self, response):
items = response.xpath('//ul[#class="infield cf"]//div[#class="infield-wrapper"]/h2/a/#href')
for item in items:
link = item.extract()
yield Request(complete_url(link), callback=self.parse_category)
def parse_category(self, response):
items = response.xpath("//ul[#class='products-list']/li/div")
for item in items:
msh = CrawlerMshFinalItem()
msh['item_price'] = encode(item.xpath('normalize-space(.//aside/div/div/div/text())').extract()[0])
msh['item_name'] = encode(item.xpath('normalize-space(.//div/h2/a/text())').extract()[0])
yield msh
new_link = response.xpath('//li[#class="pagination-next"]/a/#href').extract()[0]
yield Request(
complete_url(new_link),
callback=self.parse_category
)

Can't save avatar field from Model method in Django

I'm following this tutorial for uploading (to S3 Amazon) and manipulating an image with Django.
I'm stuck somewhere, because I'm able to upload the file, but whenever the method that should create the thumb is called, I think something's missed.
This is the code:
def upload_avatar_to(instance, filename):
import os
from django.utils.timezone import now
filename_base, filename_ext = os.path.splitext(filename)
return 'media/images/avatars/%s%s' % (
now().strftime("%Y%m%d%H%M%S"),
filename_ext.lower(),
)
class CustomUser(AbstractBaseUser, PermissionsMixin):
avatar = models.ImageField('profile picture', upload_to=upload_avatar_to, null=True, blank=True)
def save(self, *args, **kwargs):
super(CustomUser, self).save(*args, **kwargs)
self.create_avatar_thumb()
def create_avatar_thumb(self):
import os
from django.core.files.storage import default_storage as storage
if not self.avatar:
return ""
file_path = self.avatar.name
filename_base, filename_ext = os.path.splitext(file_path)
thumb_file_path = "%s_thumb.jpg" % filename_base
if storage.exists(thumb_file_path):
return "exists"
try:
f = storage.open(file_path, 'r')
image = Image.open(f)
width, height = image.size
if width > height:
delta = width - height
left = int(delta/2)
upper = 0
right = height + left
lower = height
else:
delta = height - width
left = 0
upper = int(delta/2)
right = width
lower = width + upper
image = image.crop((left, upper, right, lower))
image = image.resize((250, 250), Image.ANTIALIAS)
f_thumb = storage.open(thumb_file_path, "w")
image.save(f_thumb, "JPEG")
f_thumb.close()
return "success"
except:
return "error"
def get_avatar_thumb_url(self):
import os
from django.core.files.storage import default_storage as storage
if not self.avatar:
return ""
file_path = self.avatar.name
filename_base, filename_ext = os.path.splitext(file_path)
thumb_file_path = "%s_thumb.jpg" % filename_base
if storage.exists(thumb_file_path):
return storage.url(thumb_file_path)
return ""
It seems that everything's ok, but there should be something wrong with the code.
I upload the image, no errors are caught, but:
The image doesn't get resized
No "avatar-name_thumb.jpg" is created and uploaded on the bucket
What could I do?

Django SelectDateWidget to show month and year only

Is there a different widget or argument that will allow django to only show/take the year and month input instead of year, month and day?
Currently using SelectDateWidget.
There's a snippet here, which sets the day to 1 (presuming you've got a DateField that this value will end up in, you'll need to get some kind of day).
The code is like this (just in case Django snippets disappears):
import datetime
import re
from django.forms.widgets import Widget, Select
from django.utils.dates import MONTHS
from django.utils.safestring import mark_safe
__all__ = ('MonthYearWidget',)
RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')
class MonthYearWidget(Widget):
"""
A Widget that splits date input into two <select> boxes for month and year,
with 'day' defaulting to the first of the month.
Based on SelectDateWidget, in
django/trunk/django/forms/extras/widgets.py
"""
none_value = (0, '---')
month_field = '%s_month'
year_field = '%s_year'
def __init__(self, attrs=None, years=None, required=True):
# years is an optional list/tuple of years to use in the "year" select box.
self.attrs = attrs or {}
self.required = required
if years:
self.years = years
else:
this_year = datetime.date.today().year
self.years = range(this_year, this_year+10)
def render(self, name, value, attrs=None):
try:
year_val, month_val = value.year, value.month
except AttributeError:
year_val = month_val = None
if isinstance(value, basestring):
match = RE_DATE.match(value)
if match:
year_val, month_val, day_val = [int(v) for v in match.groups()]
output = []
if 'id' in self.attrs:
id_ = self.attrs['id']
else:
id_ = 'id_%s' % name
month_choices = MONTHS.items()
if not (self.required and value):
month_choices.append(self.none_value)
month_choices.sort()
local_attrs = self.build_attrs(id=self.month_field % id_)
s = Select(choices=month_choices)
select_html = s.render(self.month_field % name, month_val, local_attrs)
output.append(select_html)
year_choices = [(i, i) for i in self.years]
if not (self.required and value):
year_choices.insert(0, self.none_value)
local_attrs['id'] = self.year_field % id_
s = Select(choices=year_choices)
select_html = s.render(self.year_field % name, year_val, local_attrs)
output.append(select_html)
return mark_safe(u'\n'.join(output))
def id_for_label(self, id_):
return '%s_month' % id_
id_for_label = classmethod(id_for_label)
def value_from_datadict(self, data, files, name):
y = data.get(self.year_field % name)
m = data.get(self.month_field % name)
if y == m == "0":
return None
if y and m:
return '%s-%s-%s' % (y, m, 1)
return data.get(name, None)
A Python 3 widget sample here https://djangosnippets.org/snippets/10522/.
Example usage :
class myForm(forms.Form):
# ...
date = forms.DateField(
required=False,
widget=MonthYearWidget(years=xrange(2004,2010))
)
I came across the same problem today and solved it by removing the day field via a css property and setting 1 as value for the day on clean up.
#id_my_date_field_day-button {
display: none;
}
I used a ModelForm with an UpdateView and therefore had initial data in my fields which made life a bit simpler because I always had a valid value for the day of my_date_field.
I've written a simpler version (https://djangosnippets.org/snippets/10943/) inheriting from django built-in SelectDateWidget.
In widgets.py:
import calendar
import datetime
from django.forms.widgets import HiddenInput, SelectDateWidget
from django.utils import datetime_safe
from django.utils.formats import get_format
class MonthYearWidget(SelectDateWidget):
def __init__(self, last_day=False, *args, **kwargs):
self.last_day = last_day
return super().__init__(*args, **kwargs)
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
day_name = self.day_field % name
day_subwidget = HiddenInput().get_context(
name=day_name,
value=1,
attrs={**context["widget"]["attrs"], "id": "id_%s" % day_name},
)
context["widget"]["subwidgets"][0] = day_subwidget["widget"]
return context
def value_from_datadict(self, data, files, name):
value = super().value_from_datadict(data, files, name)
if self.last_day is True:
y = data.get(self.year_field % name)
m = data.get(self.month_field % name)
if y is not None and m is not None:
input_format = get_format("DATE_INPUT_FORMATS")[0]
monthrange = calendar.monthrange(int(y), int(m))
date_value = datetime.date(int(y), int(m), monthrange[1])
date_value = datetime_safe.new_date(date_value)
return date_value.strftime(input_format)
return value
kwargs:
last_day : if set to True, returns the last day of the month in the generated date, otherwise returns a date starting from the 1st day of the month
Usage example:
# models.py
from django.db import models
from django.utils.translation import gettext_lazy as _
class MyModel(models.Model):
start = models.DateField(
_("Start date"),
)
end = models.DateField(
_("End date"),
)
class Meta:
verbose_name = _("My model")
# forms.py
from django import forms
from .models import MyModel
from .widgets import MonthYearWidget
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
exclude = []
widgets = {
"start": MonthYearWidget(),
"end": MonthYearWidget(last_day=True),
}