Footer only on last data page in Reportlab - footer

I am working on an invoice and I would like to add a footer on the last page only (which can also be the first page).
Since the data of the table is dynamic, I am not able to calculate the number of pages.
Now I am working with 2 Page Templates, firstpage (with 2 frames and footer1) and nextpages (with 1 frame and footer2). This works when the data fills two pages, but when the table fills only 1 page or more then 2 pages, it no longer works.
I defined the footer in the following way:
footerFrame = Frame(x1=35*mm, y1=20*mm, width=175*mm, height=15*mm)
footerStory = [ Paragraph("Have a nice day.", styles["fancy"]) ]
def footer2(canvas,document):
canvas.saveState()
footerFrame.addFromList(footerStory, canvas)
canvas.restoreState()
Is there a more flexible way to define a footer, so it only shows up on the page at which the table ends?
Thanks in advance.

By overriding ReportLabs canvas Class, you CAN keep track of the pages (granted I've done it with other reports that don't involve flowables, but I believe you can still make it work!) .
Since you are using a flowable (Paragraph), you need to know how many pages it is going to be with each new PDF generation (the length is the dynamic part). I am not 100% positive, but I think ReportLab's flowable still invoke the "showPage()" method of the canvas. So you can do the following:
In pseudo-code/part-python, I'd recommend the following (untested):
class MyFooterCanvas(canvas.Canvas):
def __init__(self, *args, **kwargs):
## Subclass the ReportLab canvas class.
canvas.Canvas.__init__(self, *args, **kwargs)
## Create an empty list to store the saved pages so you can keep track of them.
self._savedPages = []
def showPage(self):
"""Override the showPage method"""
## We are writing our own showPage() method here, so we can keep track of
## what page we are on.
self._savedPages.append(self)
## Start a new page.
self._startPage()
def drawFooter(self):
"""Draws the footer to the page. You can have it do whatever you want here"""
self.drawString(50, 50, "This is my footer, yay me - footer freedom")
def save(self):
"""Saves the entire PDF in one go, a bit costly to do it this way,
but certainly one way to get a footer."""
numPages = len(self._savedPages)
for pages in self._savedPages:
## Finds the last page and when it 'hits', it will call the self.drawFooter() method.
if pages == self._savedPages[-1]:
self.drawFooter()
else:
## If it's not the last page, explicitly pass over it. Just being thorough here.
pass
## And... continue doing whatever canvas.Canvas() normally does when it saves.
canvas.Canvas.save(self)
AGAIN this is untested, but I think this will give you the behavior you want. Try it out, if you get stuck let me know, I can hash some of this out if need be, but I've done this same method for other non-flowables and it's worked for me in the past.

Related

Editable blocks on page (not related to model - related to SEO) in Ruby on Rails

My SEO-people do not write code. All they love is creating good texts. All they can do is pasting texts do database via some nice forms.
The problem is that sometimes they ask me: we need to put the text into page footer. Wee need to put some other text into page header.
And I just can not edit the code every time SEO-man asks me!
And sometimes the text are not related directly to model. I think you will understand me that it is a bad idea to create footer_block field inside a Car or Person model.
How nice it would if there was a gem that could:
Load text data from database by key (for example 'FOOTER_BLOCK'). To let me not to turn the models into a mess!
Give us forms where a SEO-person could paste the text
(Would be nice) Give us a WISIWIG editor.
PS: An example of such functionality (but not in Ruby): I used to code in python/Django. And we used django-flatblocks package - it did fit these 3 criterias.
I don't know any gem which will do this, but hopefully I can shed some light on how you might be able to achieve it
Code Blocks
You could create a table (and model) called code_blocks. The schema may look like this:
code_blocks
id | title | body | created_at | updated_at
This will allow you to create any number of records in this table that you want, and then call them from your app without the need for specific controller actions
Display
You could do this:
#app/helpers/application_helper.rb
def code_block(id)
block = CodeBlock.find(id)
return block.body
end
This may be inefficient, but it will allow you to include the code blocks whereever you want on the page, independent of the controller actions
So, for example, you have a footer block with id as 3, you could put:
<%= code_block(3) %>
Editing
This will mean that if you have a simple backend form, you can set it up so that you list the blocks by title, and allow the SEO guys to edit the HTML with a WYSIWYG editor (saving the HTML in the body column)

Proper way to remember multiple parameters across requests in Rails

My application feature a "main" page where most of the action happens: There are tags for filtering and a list of results in a (paginated) table, plus the possibility to select some or all results in a "shopping cart".
This page has to keep track of a whole lot of things: what tags are selected, what items are selected, and how the result table is sorted and what page it's on. Everything has to persist, so if I select a new tag, the page must partially reload but remember everything (sorting, what's selected).
Right now I'm handling everything with parameters, and for each action taken on the page, all links (select a tag/item, change page, sort table) are updated to include previous parameters + the relevant new addition. This works, obviously, but it feels kind of inefficient, as I have to reload more of the page than I want to. How is this situation normally handled? I can't find that much info on google at all, but it doesn't feel like a particularly uncommon case.
tl;dr: How to best make sure all links (to the same page) always include everything previously selected + the new action. There are a lot of links (one per tag to select/deselect, one per result item to select/deselect, one per sort option, one per page)
There are five ways to do that:
Method 1: By parameters
You mentioned this. I never think of this as it's too troublesome. Anyway it's still a solution for very simple case.
Method 2: By cookie
Save the settings to a cookie and read the cookie in controller to arrange layout settings.
Method 3: By LocalStorage
Similar to cookie but allows more space.
Method 4: By Session
If you are using ActiveRecord to save session, this could be the best solution for pure pages loading. Save the user preferences into session and load it in next layout.
Method 5: Use Ajax
This is the best solution IMO. Instead of whole page loading, use Ajax to refresh/retrieve changes you need. Using together with above method, a user can even continue his last preferences. This is the most powerful and should be applicable to your case which looks like a web app than a website.
Have you tried creating model for all those attributes? and just always load the 'latest' when on the page load, if you dont need them you can always have a flag for that session.

How to handle front-end content in order to display menu items based on the current user?

I am using Ruby on Rails 3.2.2 and I would like to "handle" / "generate" the proper front-end content so to follow a "common" way of managing menu items mostly based on the current user "equality". That is, I would like to display different menu items based on
the current browsed page;
the current user that is accessing that page (the page could be related to a user that is not the current user).
Where (for example, in controller, view or model files) and how (for example, stating checks related to the current user in controller, view or model files) I should "state" / "put" those "conditional statements"?
At this time I think (mostly for matters relating to the current browsed page) I could handle this matter directly in controllers by using helper methods...
I tend to put this into the View files with simple or static cases coded into the View file and more complex cases which would require more than just one line of coding into the helpers.
But in order not to bloat the view file, I suggest to use partials to offload blocks of code from the view file.
One of the reasons why I use the views is that I will do certain user based formatting anyways, e.g. if I list all the orders, then the normal user will see certain columns displayed, whereas if the admin logs in, he will see a couple of additional columns. This is typically done with something like
<%if #curreny_user_type == 'admin'%><td> ...... </td><%end%>
Thus before I now start splitting up some of the user based logic into the controller and others into the views, I'ld rather have them always at the same place.

Django admin/doc/views/ all blank or broken

I'm trying to use Django's built-in admin docs feature to make writing templates easier. Supposedly if you go to /admin/docs/views you should get documentation for every view in your application. I see a list, but none of the links work:
-) Any view listed that's related to my application just goes to a blank page with nothing but the name of the view as a header.
-) The views related to admin all give me Django 404 errors when I click on them, except those that are related to the docs itself. The docs-related links also give me blank pages. (i.e. clicking /admin/doc/filters gives a blank page with nothing but "django.contrib.admindocs.views.template_filter_index" as a title, but clicking /admin/auth/user gives me a Django 404 error
The 404 errors lead me to suspect my URLconf is wrong, but all I did was uncomment the built-in lines. The relevant sections read:
# Uncomment the admin/doc line below to enable admin documentation:
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)),
And I have no idea what to make of the blank pages. Do I need to provide some extra meta information somewhere, like I know you need to provide the get_absolute_url on models for some of the admin features to work right?
Even if no one knows the answer, any documentation on the admin docs feature would be useful -- I've been Google all over (and searching StackOverflow) and this feature seems very little-documented.
Thanks!
You need to add 'django.contrib.admindocs' to your INSTALLED_APPS in settings.py. It should already be there and commented out. Though it would be nice if the comment in urls.py mentioned it ... Source.
I've never looked at the views admin doc pages before -- I've never had a need to. B4ut you're right, they seem to be -- lacking in potential features.
If you give your views functions docstrings (documentation), that content will appear on your "blank pages".
Most -- no, all -- of the admin sites views are actually decorated member methods of admin.sites.AdminSite. I looked around, and a view of mine which uses a decorator also suffers from the 404.
The view responsible for view details starts:
def view_detail(request, view):
if not utils.docutils_is_available:
return missing_docutils_page(request)
mod, func = urlresolvers.get_mod_func(view)
try:
view_func = getattr(import_module(mod), func)
except (ImportError, AttributeError):
raise Http404
title, body, metadata = utils.parse_docstring(view_func.__doc__)
...
You can see it tries to import the view to get info from it; if the view is actually a decorator (which probably used an internal function to wrap the real view), it won't be able to import it. eg, if you do from django.contrib.admin.sites import index in a django shell, you'll get an ImportError, whereas django.contrib.admin.site.index (note the singular site) is a:
<bound method AdminSite.index of <django.contrib.admin.sites.AdminSite object at 0x...>>
Further, that last line in my snippet seems to indicate that there's a capability for finer control over what shows up on those pages, if you care to figure out the template that util.parse_docstring uses.

A new Rails idea in views and no more controller. maybe better maybe worse, i need help if this is too bad

Hy,
I was thinking that all my website will have use of cells, using the known plugin cell for rails, so this is my idea:
A table that contains 3 fields: id, view_name and layout. the layout will be a serialized hash.
When a request is made, the layout field is requested and then in the view, default layout, will be unserialized the layout var, that looks like this:
#layout[:sidecol][:gallery] = {... some params for it...};
#layout[:maincol][:comments] = {..params...};
In the <% #ruby code to render the cells in the #layout[:sidecol] %> will be some ruby code that will loop over the #layout[:sidecol] and render all cells in it. the same occurs in the maincol div.
What do you think?
Positive in my opinion:
More modular
controller is used only for post
easy change of structure
easier to implement some kind of traking to see diferences on what layout is better or not.
Negative:
not found yet
EDIT:
1) The request comes, is calculated the view name.
2) Load from the database the layout field that corresponds to the view name. (this will be cached, and will be updated only when changes are made. I intend to use this way, because I will need to test the layout. 33% layout1, 33% layout2 and 33% other layout. So will be used a random number to choose the view layout.)
3) The layout field contains: first subdivision is the name of the div to be created, then in each one will be more components, named cells in this case, that will be instanced in the application controller, because will be repeated for all get requests.
4) In the view will be created the divs and will be rendered in each one the cells defined.
5) The cell will make the request to the db and load the data.
6) The cell will then render the HTML and is ready to go!
So... in discussing MVC, you should understand that the controller layer is probably the most critical of any of the layers for actually accomplishing tasks. The controller layer is intended for actually getting any work done within your framework.
There are ways to abandon monolithic MVC as your primary pattern, for example, building a set of services which communicate with each other, but even there, that's mainly abandoning monoliths, since you can push the MVC pattern down into each component.
With regard to your specific proposal, storing layout data, which seldom changes between requests, in your DB is an unnecessary performance hit. Having to drag the layout from your DB out, unserialize it and run it will require you either to set up a caching framework, or to do crazy DB scaling.
Incidentally Rails3 and Merb (and i think even Rails2) are sufficiently modular in the controller layer, that they don't really care where your layout/templating/view stuff comes from. If you really want, you can just tell them to render a string.

Resources