django pdf export - django

I want to generate a PDF which will show the output of my queryset in table format, for example:
query = ModelA.objects.filter(p_id=100)
class ModelA(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
p_id = models.IntegerField()
description = models.TextField()
I need to show the values for name, description and pid in the generated PDF.

As mentioned by other people the best way to do this is to generate a template then convert the result, using one of the many libraries around, into a PDF. This method provides you with the usual amount of control over your templates, for example using tags.
I've used the previously mentioned ReportLab/Pisa setup but found it to be quite limiting, most layouts have to be built using tables and many parts of the CSS2 spec aren't implemented yet.
An easier to use library is wkhtmltopdf which is a headless distribution of WebKit. This has the benefit of rendering your templates like any webkit browser would and thus letting you use webkit specific extras, such as parts of the CSS3 spec that exist in WebKit.
Using the wrapper library django-wkhtmltopdf you can render_to_pdf in your view instead of the usual Django render_to_response.
Disclaimer: I am a contributor to this library.
Update
This library has been converted to CBVs and most of the information below (which I'll leave to help add some context) is now implemented in the library itself for convenience.
See the quickstart docs for an example of how to implement the below code block. If you need to use more advanced usage you can subclass PDFTemplateView and add various options like filename and the margins.
An example view:
from django.shortcuts import render_to_response
from wkhtmltopdf import render_to_pdf
def pdf(request):
context.update({'objects': ModelA.objects.filter(p_id=100)})
kwargs = {}
if request.GET and request.GET.get('as', '') == 'html':
render_to = render_to_response
else:
render_to = render_to_pdf
kwargs.update(dict(
filename='model-a.pdf',
margin_top=0,
margin_right=0,
margin_bottom=0,
margin_left=0))
return render_to('pdf.html', context, **kwargs)
The conditional statement here lets you pass ?as=html to the view so you can develop in the browser. It's a bit of an ugly way to do it currently but there are plans to fix this in a release soon.
Using this view you could loop the contents of objects in your view as you would normally and even extend your base template. I've normally used a different stylesheet specifically for the PDFs for maintainability and readability of the styles as you need to do a few things differently for PDFs, such as setting a min-height if you want to keep your footer block in the same place.
On this note, you can create header and footer templates that will be used on each page of your PDF by passing them into render_to_pdf as part of kwargs.

Just generate the HTML the way you would want it and ask xhtml2pdf to convert it into pdf.
Like one of the comment mentions, there is ReportLab, but that would need you to give specification in PDF's required format. It provides you more control, but if it is easier for you to generate HTML, the standard way which you need to generate anyway, you can use pisa to make it pdf.

Try wkhtmltopdf with python-pdfkit
This seems to be the best solution.Supports javascript and css

Related

drf-yasg Customize SwaggerUIRenderer

I'd like to customize the style (font, colors, logo, etc) of drf_yasg generated docs.
I see that I can extend drf_yasg/swagger-ui.html with the blocks extra_head, extra_styles, extra_body, extra_scripts, and can even overwrite the other blocks if I need to.
What I am not clear on is how I point to my template that extends swagger-ui.html.
I started with
class MyCustomSwaggerUIRenderer(SwaggerUIRenderer):
template = 'api/custom-swagger-ui.html'
I want to replace SwaggerUIRenderer with MyCustomSwaggerUIRenderer in get_schema_view but do not understand how/where to do it without explicitly trying to enumerate all the other Renderers required too in some subclass of rest_framework.views.APIView and that seems convoluted.
Pointers to docs or examples are appreciated. I've already read https://drf-yasg.readthedocs.io/ without success.
You don't have to create a custom class for this. You just need to create a directory with the name drf-yasg under new or existing app and then place a file with the name swagger-ui.html underneath it with your custom template. For example, if you already have an app with the name api, you can just put it under api/templates/drf-yasg/swagger-ui.html. Make sure the app api is specified before drf-yasg in INSTALLED_APPS.
Reference: https://github.com/axnsan12/drf-yasg/issues/294#issuecomment-464461773

In the Wagtail admin how to disable summary items of Images and Documents?

I know that I can get rid of the Pages summary by using the hook, in fact a code sample below should have removed all the items, however Images and Documents still remain.
#hooks.register("construct_homepage_summary_items")
def hide_images_and_documents_from_partners(request, summary_items):
if request.user.groups.filter(name="Partners").exists():
summary_items.clear()
Wagtail too internally uses the construct_homepage_summary_items hook, therefore to make this work correctly one must pass order argument to the hooks.register() to make this hook run after every hook in the wagtail core.
To hide Images and Documents summary items one could use the following code:
from wagtail.admin.site_summary import PagesSummaryItem
#hooks.register("construct_homepage_summary_items", order=1)
def hide_everything_except_pages_summary_for_partners(request, summary_items):
if request.user.groups.filter(name="Partners").exists():
summary_items[:] = [i for i in summary_items if isinstance(i, PagesSummaryItem)]

How to store a dynamic site-wide variable

I have an html file which is the base,where other html documents extends.Its a static page but i want to have variable in the menu.I don't think it's wise to create a view for it,since i don't intend to let users visit the base alone.So where in my project can I store site-wide dynamic variables that can be called on any page without explicitly stating them in their views.
Thank you in advance.
For user specific variables, use session.
For global constants (not variables!), use settings.py.
For global variables, consider to store it in database so it can be multithreading & multiprocess safe.
I looked around and saw different approaches,but one that doesn't compromise the DRY philosophy the most for me is registering a tag in your project then input it in the base template.Its neater See here https://stackoverflow.com/a/21062774/6629594 for an example
Storage can take any number of places, I put mine in a stats model in the db so you get all the goodness of that (and make it easy to access in views).
I then have a context processor written as so:
#context_processors.py:
def my_custom_context_processor(request):
return {'custom_context_variable1':'foo','custom_context_variable2':'bar'}
Add this to your context processors in settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
...
"my_app.context_processors.ny_custom_context_processor",
)
Provided you use render() to render your templates you can then you can just use:
{{ custom_context_variable1 }}
to return 'foo' in your template. Obviously returning strings is for example only, you can use anything you like so long as your context processor returns a dict.
you can also try using php pages.
Then acces the variable on each page with an include 'file containing the var.php' on every page.
None of this will be visible in the source html as it is only processed on the server side.
If you you would like to try this, mail me and I will send you some sample code.

Flask/Python calling def in approute

This might be a stupid question, but I am new to coding with Python.
Using flask and calling #app.route(), i need to create several HTML files.
Rather then coding everything inside of #app.route(), can i call different def inside the app.route before returning the render_template?
Edit:
So i am creating HTML files. Rather then opening 3-4 different documents inside the app.route and printing lines to them, can I create 3-4 functions in the main code to handle each document.
so rather then:
#app.route('/')
Print all html files
have:
def html1():
write html files
#app.route('/')
html1()
render_template
Yes, you can do whatever processing you need to inside a route before finally returning the response to the client. Be aware of load times, however - people don't like waiting long for a page to load.
That being said, you should really take a look at the template tutorial of the official docs. Your approach sounds like a perfect place to make use of templates as Jinja is doing what you describe, but in real-time: taking the HTML file, replacing certain places with your data, and presenting that to the user.

Django: Model-dependent Apps to Choose From Based on User

I have a Django app where multiple teams upload content that will be parsed. The app keeps track of certain common information in the parsed content. The issue here is that each team has content that needs to be parsed by a different parser because the content is in a different format (e.g. some teams have XML content, some have text, some have JSON, etc...). Each of the teams has provided a parser (a python module) that grabs the necessary info that is placed into corresponding Django models after parsing.
My question is: what is the best way to architect this in Django where each team can have their own parser setup correctly? It can be purely backend, no need for a user form or anything like that. My first thought was that I would create a Parser model with ForeignKey to each team like so:
class Parser(models.Model):
team = models.ForeignKey('Team')
module_path = models.CharField(max_length=..., blank=False)
and that module_path would be something like "parsers.teamA.XMLparser" which would reside in my app code in that path like so:
parsers/
teamA/
__init__.py
XMLparser.py
teamB/
Then when my app is coming to parse the uploaded content, I would have this:
team = Team.objects.get(id=team_id)
parser = Parser.objects.get(team=team)
theParser = __import__(parser.module_path)
theParser.parse(theStuffToBeParsed)
What problems does anyone see with this? The only other option that I can think of is to create separate Django apps for each parser, but how would I reference which team uses which app in the database (same as done here?)?
The approach you're taking seems valid to me. Keep in mind that you are effectively running arbitrary python code so I would never be using something like this on a public facing site and ensure you trust the teams writing their parsers.
You might make this a bit nicer by writing a custom Field to represent the module path that will remove the need to handle the import everytime and will instead handle the import for you and return the parse method (or maybe even better a Parser object where you could tell the teams to implement an interface)
The best example might be to look at the source for django's ImageField or even CharField. Instead of having having your model have a CharField, you'd have a "ModuleField": parser = ModuleField(). The database stored value would indeed be the path to the module (so simply make it a subclass of CharField), but override the to_python method. In your new to_python method handle importing the module and return a python object.
That python object could be anything you want it to be, from your example you could return theParser.parse. This would result in if you have a Parser instance foo you could the_parser_method = foo.parser