Flex 4 + Django: Testing and Release Options - django

I am creating a django-based site that will serve flash apps that occasionally access data via pyamf. I need to be able to easily test the flash in the context of the django framework, i.e. with all the login cookies and everything available, so that when I make a pyamf call, it has all the user context there. And I need to be able to test and release both the swf's and the wrapper html's in a sane way. However:
The html templates in flex are already templates, so if I put template code in there for django, it gets scraped out before the flashapp.html is created.
The html's and swf's automatically get released to the same directory, but I want them to go to different directories because the swf's shouldn't be served by django and the html's should be in an area in control of django.
This leads me to believe, at first glance, that I need:
A way of having the html and swf files be released to different locations. (I don't know how to do this.)
A way of releasing the html's as stubs (no html/body tag) so that I can include them from another location in django. (I guess just strip what I don't want from the index.template.html?)
Then I can point flex to go to the django site that in turn includes the generated flashapp.html that in turn references the swf, and it should all work. (By feeding that alternate html to the run/debug settings, I assume.)
So my question comes down to:
Is the above the best way of doing this, or is this even the right direction?
If so, how do I release the html and swf to different directories? (For debug and release mode, if there are two different methods.)
If not, what is proper?
And if there are any other general bits of advice for me on this topic, please feel free to share. :-)

Finally figured this out myself. A combination of this and django get-parameters works. The general take-away:
You can put {% tags %} and {{ variables }} in index.template.html without worry, as there is no way to customize the currently-existing macros there like ${title}
If you make a foo.template.html and foo-debug.template.html in the html-template directory of your project, then the former will override index.template.html for release builds, and the latter for debug builds (note that the result will be foo-debug.html instead of foo.html though.)
You can pass the name of the SWF in a parameter to django, and have it fill in the directory for you
foo-debug.template.html
<object ...
<param name="movie" value="{{ bin_debug_url }}/${swf}.swf" ...
djangoflash.html
{% block content %}
{% include flash_template %}
{% endblock %}
views.py
def djangoflashview( request, **kwargs ):
if not kwargs.has_key('extra_context'):
kwargs['extra_context'] = {}
if request.GET.has_key('name'):
debug = "-debug" if request.GET.has_key('debug') else ""
bin_debug_dir = '/dir-to-bin-debug/'
bin_debug_url = 'url-to-bin-debug'
name = bin_debug_dir + request.GET['name'] + debug + '.html'
kwargs['extra_context']['flash_template'] = name
kwargs['extra_context']['bin_debug_url' ] = bin_debug_url
return direct_to_template( request, **kwargs )
urls.py
url( r'^djangoflash/', 'views.djangoflashview',
{ 'template': 'djangoflash.html' }
foo.mxml's run-debug target:
/url-to-django/djangoflash/?name=foo
When you debug foo.mxml, flex:
Adds &debug=true to the url
Brings up a browser to /url-to-djangoflash/djangoflash/?name=foo&debug=true
Which picks djangoflash/ in urls.py
Which passes the request to djangoflashview and {'name':'foo','debug':'true'} to request.GET in views.py
Which figures out the name and location of the foo-debug.html location, passing it to the flash_template context variable
And the url of the swf to the bin_debug_url context variable
And loads up the direct template djangoflash.html
Which, in djangoflash.html, includes the foo-debug.html wrapper for flash using the flash_template context variable
Which, in turn fills in the bin_debug_url context variable to point the foo.swf reference correctly to the thing you just compiled
Whew. :-P

Related

Passing HTML code as string variable to template for PDF generation

I'm working on a Django app which parses xlsx input, processes series of REST API queries and returns the result of the queries as a table in one of my django templates. The HTML code containing the results table is generated with Pandas.to_html() functionality. The HTML code is stored in a variable ("table") and passed to the html template, where it is displayed as {{ table | safe }}. This mechanism works just fine. However, I'm now struggling to add a button which would generate a pdf file to be downloaded by the user.
NOTE: I'm aware it would probably make more sense to use JS to render the PDF on the client side, but at the moment the point is to avoid doing so.
Upon some research, I decided to go with the django-easy-pdf library. I based my solution on the example included in the documentation, but so far to no avail.
In urls.py:
urlpatterns = [
[...]
path('result.pdf', views.PDFView.as_view(), name='PDFview'),
]
In views.py:
class PDFView(PDFTemplateView):
template_name = 'whitelist/listresult.html'
table = None
def get_context_data(self, **kwargs):
return super(PDFView, self).get_context_data(pagesize='A4', title='Hi there!', table=self.table, date=date.today)
Please note that the template "listresult.html" is the one expecting the {{ table }} variable.
Last but not least, in the very listresult.html (where I want to place the button to render the PDF file), I added a simple button object:
<a class="btn btn-secondary btn-lg" href="{% url 'PDFview' table %}">Download PDF</a>
My expectation was that since I'm sending the "table" variable along with the request for PDF url, the view would process it nicely and prompt the user with a download pop-up for the PDF file looking exactly (or almost exactly) as the page which presented the result in the first place. However, I'm cought in a vicious circle where if I add "table" to the url reference on the site I get an error during template rendering for the very website displaying results (NoReverseMatch for ..., Reverse for 'PDFview' with arguments '['table' contents go here] not found). On the other hand, if I remove the "table" argument from the url reference, the results website renders OK with the "Download PDF" button, but upon clicking it I'm left with a Runtime Error (since context is missing).
I'm 97% confident my mistake is ostentatiously stupid, but after x hours of struggle I'm ready for StackOverflow's judgement.

Django views/templates: list filtering based on a current a site category

In my app user can create and manage organizations -> projects -> resources and so on. A project instance has a FK to organization, resource has a FK to project.
In example, when user selects an active organization, i want projects view to display only projects that belong to this organization. I see these ways:
Optional argument in all specific urls:
url(r'^(?:organization/(?P<organization_id>\d+)/)?projects/$', 'app.views.projects', name='projects'),
url(r'^(?:organization/(?P<organization_id>\d+)/)?(?:project/(?P<project_id>\d+)/)?resources/$', 'app.views.resources', name='resources'),
Also, this method forces to rewrite all {% url %} tags in templates:
`{% url 'projects' org.id %}`
`{% url 'resources' org.id prj.id %}`
but that's all does not look pretty, especially urls.py.
UPDATE 1
This method forces to pass organization_id in templates everytime. Even if I write middleware to avoid annoying passing it in context,
class FetchFiltersMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
request.project_id = view_kwargs.get('project_id', 0)
request.organization_id = view_kwargs.get('organization_id', 0)
anyway, ALL site urls must be rewritten to contain organization_id, otherwise filtering will be broken. Even if it's not necessary, i.e. in user profile view all sidebar links to projects will be broken.
Storing a current filter in cookie or GET argument
like {% url 'myurl' %}&project={{ project_id }}. bad. ugly.
Storing a last selected organization/project id in cache or session
Easy to use. But not userside-explicit. Also it will generate problems when site opened in multiple tabs with different organizations selected on each tab.
At this moment i see first way looks better, but a lot of rewrite work is required. Is there a better way to do category/section based filtering?
UPDATE 2
If it's not clean yet. The selection of the project, or organization - it's actually switching the current display context. In the context of the selected organization all links should lead to projects in this organization, and so on.
I personally prefer the first way. If you have a relatively simple structure, you can simplify your template by using get_absolute_url. For example, {{ org.get_absolute_url }} could lead to the projects view, {{ prj.get_absolute_url }} to resources etc.
In an older project, I used the session-way, and still regret it, exactly because of the problems with multiple tabs/windows. Using a cookie has the same problems. I think the "ugliness" of the URL configuration in the first way is worth the gain in usability.

Attaching a .png file to an email sent by satchmo

In a Satchmo Store, I need to attach a small .png (a barcode) to an email that django sends on completion of the order. The email is formatted in HTML using send_order_confirmation() which calls send_store_mail() (both part of satchmo.) Neither of these functions offer the ability to attach a file (I think) so should I just re-write them? I was wondering if it is possible/better to do this using signals. Maybe rendering_store_mail() ?
By the way, the barcode would be dynamically generated, so there's no way of having a link to a file on a server somewhere.
Many thanks,
Thomas
well I too had to add extra infos to the confirmation emails, only text though. So this would be the very easy way to add extra-stuff to emails using signals, which IMHO, is the best approach to do it. Always use signals if you can avoid overriding the satchmo-core ;-)
define your listener to add some context for the rendering. In this case I'm adding the contents of an extra notes field, and the barcode for this order, supposing there is a function named get_barcode_img(<order>), to the context. I'm supposing here too, that the get_barcode_img function would return not just a png, but something like a MIMEImage (like from email.MIMEImage import MIMEImage) to be able to just include it inline. Also, there might be more infos needed, like a MIME-header for the img.
# localsite/payment/listeners.py
def add_extra_context_to_store_mail(sender,
send_mail_args={}, context={}, **kwargs):
if not 'order' in context:
return
context['barcode_header'] = get_barcode_header(context['order'])
context['barcode_img'] = get_barcode_img(context['order'])
context['notes'] = context['order'].notes
connect the listener to the signal somewhere where the code will be "discovered" for sure, like models.py:
# localsite/payment/models.py
from satchmo_store.shop.signals import rendering_store_mail, order_notice_sender
rendering_store_mail.connect(payment_listeners.add_extra_context_to_store_mail, sender=order_notice_sender)
override the templates locally (e.g. order_placed_notice.html) to add the new context. Be aware where you put your templates, as the path is essential for django to take your new template instead of the satchmo's one. In this case, starting from your project's root-path, there could be a templates-folder and inside it, there must be exactly the same path as in the satchmo-folder. E.g. /templates/shop/email/order_placed_notice.html ... this can be applied for any "valid" templates-folder inside an app. It's up to you to decide, where/how the templates should be organized.
<!-- templates/shop/email/order_placed_notice.html -->
<!DOCTYPE ...><html>
<head>
<!-- include the image-header here somewhere??? -->
<title></title>
</head>
<body>
...
Your comments:
{{ notes }}
Barcode:
{{ barcode_img }}"

Django app to "switch on" other apps for specyfic user

I am new to django and I really like its modular construction so I decided to take advantage of it and put all the separated functionalities each in different app.
Now I need a way to switch on and off this apps by both user and admin.
The user options panel would look like this:
[ ] blog
---------------------
[ ] tagging [BUY]
After checking "blog" option user would get the blog in his profile and after buying and checking "tagging" he would get tagging for the blog.
The admin panel would have an ability to show or hide an app from user panel.
I wonder if:
there is an app which would help me switch on and off an app for specyfic user
and if not -
what would be a proper "architecture" for such django app?
Can it be done dynamically in middleware or should it be done during login (check available apps from database, switch them on, redirect to user home page)?
Any advices for such a task?
Thanks,
Robert
I haven't heard of any such app… But I don't expect it would be too hard to build.
If I were doing it, I would put a permissions check in the entry points to each app. For example:
check_app_permission = lambda request: permissions.check_app_permission("blog", request)
def view_blog(request, …):
check_app_permission(request)
…
(it might even be possible to do some magic and inject this check at the urls.py level…)
Additionally, I would create a has_app_permission template tag:
<div id="sidebar">
{% if has_app_permission "blog" %}
{% include "blog/sidebar_recent_posts.html" %}
{% endif %}
</div>
Or similar.
Finally, there are approximately a million ways you could implement the permission system… And without more information I wouldn't be able to comment. The simplest, though, would be something like this:
class App(Model):
name = CharField(…)
class AppPermission(object):
app = ForeignKey(App)
user = ForiegnKey(User)
def user_has_permission(user, app_name):
return AppPermission.objects.filter(app__name=app_name, user=user).exists()
I would avoid trying to do this with middleware, because if I understand the problem correctly, I expect you will (or, at least, I expect I would) end up spending a bunch of time building a generic framework which, in the end, would just have checks similar to those above.
Does that help? Is there something I can clarify?

Django - Pre render signal?

I have a 'live settings' app which I use to store certain global site settings. Certain pages of my site reference these settings, although generally they only use 2-3 at a time. I access these settings using a custom template tag like so:
{% settings site_name %}
Each time I use this tag, the model will retrieve the setting from the database, so if I had something like:
{% settings site_name %} {% settings num_articles %}
the database would get queried twice.
What I'd like to do is not hit the database more than once per page for the settings values, if I could get all the settings used on a page and then hit the database to retrieve them all, that would be much better.
I had a look through the documentation and it seems Django has no pre render signal which I could use to update any references to the settings, so does anyone have any suggestions how I could optimise this system? And yes obviously caching is the obvious answer but I'd still like to improve on this for when the page isn't cached.
Agreeing with Daniel that process_template_response is the hook you're looking for. I don't know how many settings you have, but it could also make sense to retrieve all settings once, and store them in some dictionary like structure, so you can access them anytime without hitting the database. You could retrieve them once either per request, or - even if your settings do barely change - when django initializes. You could additionally use django's signals to update your cached settings on delete or update.
If you have a look at django-dbsettings you will see it does a similar thing!
Django 1.3 includes the new TemplateResponse class, which allows you to modify the response later in the rendering process - eg in middleware. This looks like it might do what you want.
If you wish to stick to a scheme similar to what you already have, I'd implement a filter that takes in a list of keys and returns a dict with all the relevant values.
Example filter:
def get_settings(key_list):
# take values from conf.settings. In practice, can be from any source
return dict((k, getattr(settings, k, None)) for k in key_list.split(","))
register.filter("get_settings", get_settings)
Usage:
{# load multiple values with a single call #}
{% with "KEY1,KEY2"|get_settings as settings %}
setting values {{ settings.KEY1 }} and {{ settings.KEY2 }}
{% endwith %}
Note that I used a filter instead of a tag because the with builtin expects a single value before as.