How to render HTML Django page to PDF? - html

I have a task to render an HTML page with dynamic data and turn it into PDF, but, I have a problem achieving it.
def makepdf(request):
if request.POST:
chatvs = Competirors.objects.get(id = int(request.POST.get('competitor', '')))
jivo_staff = Manager.objects.get(id = int(request.POST.get('manager', '')))
business = Field.objects.get(id = int(request.POST.get('filed', '')))
business = business.link.all().order_by('?')[0:3]
context = {
"chatvs" : chatvs,
"jivo_staff" : jivo_staff,
"business" : business,
}
tmpl = get_template('marketing/jivopdf.html', )
html = tmpl.render(context)
# and i have a problem there with pdfkit
I was using Pdfcrowd API, but it cuts all CSS styles and does not look nice. As for vvwkhtmltopdf/pdfkit - I don't know how to make it a rendered HTML page, as it accesses only the url/file/string.
Is there a way to render ready HTML page?

Hard to say without knowing the error you get.
But what I can see from your code, if this is your real code. Looks like a spelling mistake in Competirors.objects.get, should probably be named Competitors.
And if you get the POST data from a form, you shouldn't use it directly.
Never trust user input...

I suggest you try weasyprint .

Related

Selenium not giving whats inside a class?

PATH = "D:\CDriver\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get('https://www.se.com/ww/en/about-us/careers/job-details/inside-sales-associate/006ZMV')
TITLE = driver.find_element_by_class_name('sdl-application-job-details__job-title')
print(TITLE)
driver.quit()
I have all the needed imports, I just wanted to leave them out.
When I run this the output SHOULD be: Inside Sales Associate
But instead it gives me this: <selenium.webdriver.remote.webelement.WebElement, the session and element code.
What do I need to do to make it print what it should print. I have tried by_tag_name('h1.sdl-application-job-details__job-title') but that gives the exact same.
There is a inbuilt title method available in Selenium. You can call that method on driver object not on web element.
Code :
driver.get('https://www.se.com/ww/en/about-us/careers/job-details/inside-sales-associate/006ZMV')
driver.title
print(driver.title)
or if you want to retrieve text inside any web element, you could probably do something like this :
class_value = driver.find_element(By.CSS_SELECTOR, "h1[class$='sdl-application-job-details__job-title']").text
print(class_value)
The find_element methods return web elements. Just pass print(TITLE.text)

Angular data binding sending strings?

I'm new to angular, and I would like to know if there's is a way to send a string to the Html file with a variable inside?
test.ts
test: string = "Display this {{testText}}";
testText: string = "Success";
test.html
<p>{{test}}</p>
What I want to achieve is that it displays this: Display this Success.
I'm just curious if this is possible, perhaps I can retrieve from an API chunks of HTML string and display them like that.
**
It is basic Javascript string operation. For this, there is nothing special with Angular at your TypeScript file.
Without handling updates on test
On Typescript file you have two options to merge strings:
First Way:
testText: string = "Success";
test: string = `Display this ${this.testText}`;
Second Way:
testText: string = "Success";
test: string = "Display this " + this.testText;
Of course you can see a problem with both of them. What will happen when you update your test? Based on these ways, the testText just initializing when the component instance is created, so if you want to fetch changes on your test variable you should use the way from one of following
**
First Way:
test.html
<p>Display is {{testText}}</p>
<p>{{'Display is ' + testText}}
Socond Way:
Specifically you can create a custom Pipe. You should check documentation about how are them work. For only this case you don't need to use this way. Pipes are generally for more generic or more complex operations.
Third way:
(more bad than others. Because change detector of Angular will not understand when your content should update the paragraph. You should use others.)
test.ts
getTestText() { return 'Display is ' + this.testText }
test.html
<p>{{ getTestText() }}</p>
**
Binding Dynamic Html Content
For binding any dynamic HTML template you need to use innerHTML attribute like
<div [innerHTML]="htmlVariable"></div>
but this is not a trusted way because there is nothing to check is the html is trusted or is it valid etc. Or if the html contains the selector of any component, it won 't render as expected. You should use more complex ways to do it.

How to scrape in Ruby when the page elements keep changing and shifting.

I'm writing a program to download the images from an imgur album: I had just begun to write the actual image-link-code:
#The imports.
require 'open-uri'
require 'nokogiri'
url = ARGV[0]
#The title.
open(url) do |f|
$doc = Nokogiri::HTML(f)
title = $doc.at_css('title').text.strip.clone
re = /\/[a]\/\w{5}/
s2 = url.match re
puts title
puts s2
end
href = $doc.xpath("//img")
puts href
When I ran into a major problem: the page I download isn't the page source.
For example: This album: http://imgur.com/a/tGRvr/layout/grid has the following code for it's images:
<span class="post-grid-image pointer" data-href="//i.imgur.com/zh6I7k2.png" data-title="" style="transform: translate(0px, 0px) scale(1); z-index: 0; background-image: url("//i.imgur.com/zh6I7k2b.jpg");"></span>
And yet when I look in the page source, or run the code for span elements, all the images are missing:
<div class="post-images is-owner">
<div class="post-action nodisplay"></div>
</div>
</div>
The HTML is active, and changes based on how my browser is. There aren't any images in the page source, and everything's loaded using some weird java system. How can I scrape active elements, when there aren't even any active elements to scrape?
And what's the difference between inspect and 'view-source'? That's what started this whole problem.
It's dynamic HTML. Mechanize and/or Nokogiri can't help you unless you can build the final version of the page then pass it to them.
Instead you have to use something that can interpret JavaScript and apply CSS, such as a browser. The WATIR project would be the first thing to investigate. "inspect" and "view-source" both reflect the page after the browser has processed the JavaScript and CSS in it, which often has little bearing on what the actual page looked like prior to that. Search SO for [ruby] [watir].
Use wget, curl or nokogiri to retrieve the page so you can see the raw HTML.
$doc.at_css('title') should be using the title method: doc.title.
Don't use a global like $doc. Learn about variable scoping then decide if a global is the right way to go.
Instead of open with a block:
open(url) do |f|
$doc = Nokogiri::HTML(f)
title = $doc.at_css('title').text.strip.clone
re = /\/[a]\/\w{5}/
s2 = url.match re
puts title
puts s2
end
Do this instead:
doc = Nokogiri::HTML(open(url))
title = doc.title
When working with URIs/URLs, use the built-in URI class since it's a well debugged tool:
require 'uri'
url = URI.parse('http://imgur.com/a/tGRvr/layout/grid')
url.path # => "/a/tGRvr/layout/grid"
.split('/') # => ["", "a", "tGRvr", "layout", "grid"]
Knowing that, you can do:
url.path.split('/')[2] # => "tGRvr"

Edit CSS Using Razor/Sitecore

We have a component that contains a background image. Our front-end guy needs it to be loaded through CSS (i.e. background: url(/*path here*/)...). The following is a possible solution we came up with:
#string src = // Get image path from Sitecore().Field("Picture");
<div style="background: url(#src) left top no-repeat;"> ... </div>
However, there are two problems with this approach:
It makes it very difficult for the content editor to swap out the image. They will have to manually change it through edit item.
It feels like a hack/workaround.
So the question is as follows: Is there a way to edit the CSS of an element through Razor/Sitecore? Specifically, the background: field.
I had a similar case and I used :
<footer class="layout_footer" style="background-color: #Model.BackgroundColor">
on view rendering (cshtml file)
And on the model we have :
public string BackgroundColor
{
get
{
Sitecore.Data.Fields.ImageField imgField =((Sitecore.Data.Fields.ImageField)item.Fields["BackgroundImage"]);
return Sitecore.Resources.Media.MediaManager.GetMediaUrl(imgField.MediaItem);
}
}
For editing this field in page editor you can use Sitecore Field Editor from a command : http://blog.istern.dk/2012/05/21/running-sitecore-field-editor-from-a-command/
Check for edit mode, and display in edit mode a editable field. Also create a Custom Experience Button from the Field Editor Button Type. You can also display. See User friendly developing with the Sitecore Experience Editor
#string src = // Get image path from Sitecore().Field("Picture");
<div style="background: url(#src) left top no-repeat;">
#if (IsInEditingMode)
{
<h3>Backgroiund Picture: #Editable(m => m.Picture)</h3>
}
</div>
There is no Sitecore extension method which will do this out of the box (i.e. #Html.Sitecore().Field("fieldName") will not work here as it would render the entire image tag (also a load of other non-image markup in page editor mode) as you probably know.
The method that #sitecore climber mentions is useful for controller renderings (or view renderings with a custom RenderingModel). If you want to stick with simple view renderings (i.e. not create a RenderingModel) then you could create a Html extension method which can be re-used on any view rendering. This could be something like the following:
public string ImageFieldSrc(this SitecoreHelper sitecoreHelper, string fieldName, Item item = null)
{
if (item == null) {
item = sitecoreHelper.CurrentItem;
}
var imageField = new ImageField(item.Fields[fieldName]);
var mediaItem = imageField.MediaItem;
var mediaUrl = MediaManager.GetMediaUrl(mediaItem);
mediaUrl = HashingUtils.ProtectAssetUrl(mediaUrl); //if you want to use media request protection (adding the hash onto the end of the URL, use this line
return mediaUrl;
}
It's worth noting that if you are using Sitecore 7.5 or above there is a feature to protect media URLs with a hash to prevent malicious DoS type attacks described in this blog post by Adam Najmanowicz.
In summary; if you are using Sitecore 7.5+ and you use media hashing then you will need to call HashingUtils.ProtectAssetUrl on the media URL if it is to respect size parameters.

Replace picture (from page header)

I have a base .docx for which I need to change the page header / footer image on a case by case basis. I read that python-docx does not yet handle headers/footers but it does handle Pictures.
What I cannot work around is how to replace them.
I found the Pictures in the documents ._package.parts objects as ImagePart, I could even try to identify the image by its partname attribute.
What I could not find in any way is how to replace the image. I tried replacing the ImagePart ._blob and ._image attributes but it makes no difference after saving.
So, what would be the "good" way to replace one Image blob with another one using python-docx? (it is the only change I need to do).
Current code is:
d = Document(docx='basefile.docx')
parts = d._package
for p in parts:
if isinstance(p, docx.parts.image.ImagePart) and p.partname.find('image1.png'):
img = p
break
img._blob = open('newfile.png', 'r').read()
d.save('newfile.docx')
Thanks,
marc
There is no requirement to use python-docx. I found another Python library for messing with docx files called "paradocx" altought it seems a bit abandoned it works for what I need.
python-docx would be preferable as the project seems more healthy so a solution based on it is still desired.
Anyway, here is the paradocx based solution:
from paradocx import Document
from paradocx.headerfooter import HeaderPart
template = 'template.docx'
newimg = open('new_file.png', 'r')
doc = Document.from_file(template)
header = doc.get_parts_by_class(HeaderPart).next()
img = header.related('http://schemas.openxmlformats.org/officeDocument/2006/relationships/image')[0]
img.data = newimg.read()
newimg.close()
doc.save('prueba.docx')