Optimized solution for selecting one item from array in Python - python

I am using Google App Engine free tier with Python and Jinja2 template engine.
My task is to run vote "yes" or "no" on all 5000 items. For that I am using following query on the index page.
{% extends "base.html" %}
{% block content %}
{% for item in items if not item.voted %}
//HTML goes here to display the item
{% break %}
{% endfor %}
{% endblock %}
I am breaking the loop as I want to show just one item anytime on the index page. The item can be randomly chosen, but it must not be voted. That is a very unoptimised/lazy solution which was working just fine locally but on app engine server it's an expensive operation. After voting some items, I get following error:
OverQuotaError: The API call datastore_v3.RunQuery() required more quota than is available.
Can someone suggest any better solution? I have very limited knowledge in using jinja2 template engine so I am unable to find an inexpensive solution.

There are multiple ways to do it.
Add a "random" property you you entity and then do query 1 item (using limit=1) where "RandomProp > randomValue". This is not related to Jinja2 (as Jinja is just a template engine) and should be done in your Python code and consist of 3 parts: modify model to add new prop, when saving entities assign a random value to the new prop, when want to display data do a query with filter on the new property with property greater then some (another) random value.
Keep somewhere list of IDs of the entities and randomly select one and get from DB by key.

Related

How to delete a specific Django cache by the name of the cache fragment?

Let's assume I don't want to clear the whole cache, but only a specific fragment. I have this in my template:
{% cache 500 sidebar page_num %}
.. sidebar ..
{% endcache %}
I can use cache.delete(key) to remove a specific cache, but how can I find all the keys based on the cache fragment name "sidebar"? I'm using FileBasedCache cache.
When I used Redis Cache, there was keys() method which allowed to find the key based on a name pattern, but it doesn't work with FileBasedCache.

Render returned string in django template

I have been working a lot with Django's template language lately, and it works well in most cases, but recently I've come across a small problem it hasn't been able to solve.
I'm iterating over a bunch of database objects, and building a button in the template from each of them. Something like this:
{% for item in items %}
<button id="{{ item.action.id }}">
{{ item.action.text }}
</button>
{% endfor %}
This works fine, but my Action class is inheritable, and may have a different button structure. Say I wanted to sometimes have a javascript function attached as well. My first though was well, let's just create a render method in my class, and then call that in my template.
class ScriptAction(Action):
def render(self):
return '''
<button id="{}" onclick={}>
{}
</button>'''.format(self.id, self.func, self.text)
Because no the template is much more elegant, and doesn't rely on a fixed button structure:
{% for item in items %}
{{ item.action.render|safe }}
{% endfor %}
And now for my actual problem: what if this rendered string needs further processing by django?
Maybe render method returns a string like
<button id="action-button-id" onclick="console.log('clicked')">
{{ item.name }}
</button>
Currently, {{ item.name }} will not be rendered in the template loop. Is there a way of getting around this?
Perhaps I making this more complicated than it should be, but I've looked through the Django built-in tags and filters, even looked at writing you own parser. But at this point something inside me told me that I was being obsessive. This is actually just a small problem, and would require a fair amount of time, so -
is this more effort than it is worth?
is writing complex parsers like this secure?
is the Django template language even able to do something like this?
If you could hone in on some of these points, I would really appreciate it. This problem is really bugging me.
Thanks in advance!
I'd look into the simple_tag option for building a custom template tag, and have the tag:
Take the model instance as its argument (plus context!)
Ask the model instance for a snippet of template code to use in rendering it
Use the raw template API to render that template snippet
Return the result, optionally marked safe if you know it is safe.

Cannot use filter inside Django template html

I have an issue on my Django project. I have a situation as follows:
{% for subObject in mainObject.subObjects.all %}
This works nice, every subObject gets iterated nicely. What I want now is that I print a subset of the objects, something like:
{% for subObject in mainObject.subobjects.filter(someField=someValue) %}
So far I have searched solutions about the error I get:
Could not parse the remainder: '(someField=someValue)'
but did not find a solution about how the line should be different when a filter is used. I want to tweak just the template.html file, thus I don't want to make the change on views.py file (where everything supposedly would work nicely).
How to achieve this?
Following #Yuji'Tomira'Tomita's comment..
Don't put too much logic into the template, quote from django docs:
Philosophy
If you have a background in programming, or if you’re used to
languages which mix programming code directly into HTML, you’ll want
to bear in mind that the Django template system is not simply Python
embedded into HTML. This is by design: the template system is meant to
express presentation, not program logic.
Better define the queryset in the view and pass to the template:
view:
def my_view(request):
...
my_objects = mainObject.subobjects.filter(someField=someValue)
return render(request, 'mytemplate.html', {'my_objects': my_objects})
template:
{% for subObject in my_objects %}
...
{% endfor %}
Hope that helps.

How to generate lots of redundant ajax elements like checkboxes and pulldowns in Django?

I've been getting lots of answers from stackoverflow now that I'm in Django just by searching. Now I hope my question will also create some value for everybody.
In choosing Django, I was hoping there was some similar mechanism to the way you can do partials in ROR. This was going to help me in two ways. One was in generating repeating indexed forms or form elements, and also in rendering only a piece of the page on the round trip.
I've done a little bit of that by using taconite with a simple URL click but now I'm trying to get more advanced. This will focus on the form issue which boils down to how to iterate over a secondary object.
If I have a list of photo instances, each of which has a couple of parameters, let's say a size and a quantity. I want to generate form elements for each photo instance separately. But then I have two lists I want to iterate on at the same time.
Context:
photos : Photo.objects.all()
and
forms = {}
for photo in photos:
forms[photo.id] = PhotoForm()
In other words we've got a list of photo objects and a dict of forms based on the photo.id.
Here's an abstraction of the template:
{% for photo in photos %}
{% include "photoview.html" %}
{% comment %}
So here I want to use the photo.id as an index to get the correct form. So that each photo has its own form. I would want to have a different action and each form field would be unique. Is that possible? How can I iterate on that? Thanks!
Would it be a with? In Python of course it's form = forms[photo.id] but here?
{% endcomment %}
Quantity: {{ oi.quantity }} {{ form.quantity }}
Dimensions: {{ oi.size }} {{ form.size }}
{% endfor %}
What can I do about this simple case. And how can I make it where every control is automatically updating the server instead of using a form at all?
Thanks!
James
I'm not sure I understand your question, but here's what I think you want, expressed in pseudo-code:
for photo in photos:
form = forms[photo.id]
generate_some_html(photo, form)
Probably the best way to achieve this is with inclusion tags: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags . Basically, it's a custom tag that relies on another template, similar to an RoR partial. The details can be found in the link I provided, but what you basically need to do is
create a package names "templatetags" in one of your app directories
create a module in that package. Let's take foo_tags.py for example.
Add the following boilerplate to foo_tags.py:
from django import template
register = template.Library()
Write your custom tag, which implements generate_some_html. Make it take the caller's context:
#register.inclusion_tag('relative/path/to/some/template.html', takes_context=True)
def foo_tag(context):
photo = context['photo'] # loop variable in parent template
form = context['forms'][photo.id]
# further computation that you need in order to setup the
# context for relative/path/to/some/template.html can be
# done here...
return locals()
Use the context returned by foo_tag in relative/path/to/some/template.html.
Add {% load foo_tags %} to the parent template. You should probably put this near the top, the same way you put imports near the top of a .py file.
Use your new custom tag in the parent template:
{% for photo in photos %}
{% foo_tag %}
{% endfor %}
Django doesn't comme with backed AJAX like RAIL, but it let you choose any lib you want to use from the start.
You can do what you want by creating custom widgets and using form media.

What does pk__in mean in Django?

Model.objects.filter(pk__in=[list of ids])
and
Model.objects.filter(pk__in=[1,2,3])
How do I show this data in a template?
def xx(request):
return HttpResponse(Model.objects.filter(pk__in=[1,2,3]))
It means, give me all objects of model Model that either have 1,2 or 3 as their primary key.
See Field lookups - in.
You get a list of objects back you can show them in the template like every other list, using the for template tag:
{% for object in objects %}
Some value: {{ object.value }}
{% endfor %}
To learn how to create a Django application you should read the tutorial or the Django book.
A tricky way to batch select (a best practice when dealing with a lot of data).
it would be faster than calling get/get_or_create in a loop due to the fact that only one SQL query is sent.
Try to time this :
Model.objects.filter(pk__in=[list of ids])
and this :
[Model.objects.get(pk=i) for i in ids]
Also note that running on your laptop there is minimal latency when django communicates with the database (production might be different).

Categories