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).
Related
Sample project with screenshots: https://github.com/nspo/slowformsets-django-example
Project with Authors, Books and Publishers.
There is a view to update an author where you can change all the books an Author has as well as add new books. The BookForms are created with an inlineformset_factory. Books also have a foreign key reference (publisher) than can be selected in the BookForm.
Rendering:
{% crispy form %}
{% crispy formset formset.form.helper %}
Problem:
For every BookForm, there seems to be a request for all Publishers.
I kind of understand that there is a request for publishers, because they can be selected in an implicit ModelChoiceField. But shouldn't I be able to speed that up with prefetch_related? I have a feeling that the instance of Author passed in lines 12 and 13 of view.py might be "copied" so that any prefetched data is forgotten?
If a direct solution is not possible b/c of ModelChoiceField limitations, it would also work in my case if the Publisher cannot be changed after adding a Book (but only displayed). Not sure how to do that though without lots of changes.
We can't see any code which makes this kind of a guessing game. You mention prefetch_related but it does not show up in the code you are linking to. In general I would do something like this
queryset=Book.objects.prefetch_related('publisher').filter(author=id_author)
BookInlineFormSet = inlineformset_factory(Author, Book, form=BookForm, extra=2, can_delete=False)
bookformset = BookInlineFormSet(instance=author, prefix="main", queryset=queryset)
Also I'm guessing that every book has exactly one publisher. So it would not be prefetch_related but select_related.
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.
I have a model with a number of foreign key fields, e.g. model Product with fields 'type', 'level', 'color', 'intensity' (just a generic example).
I then have a page to edit all products of a given type using a Type form with the products as an inline formset with the option to add additional products inline using extra=10.
The thing i find very strange is that each time when i output one of the foreign key choice fields on the template Django queries the database for the get the options (every time).
For example:
{% for form in formset %}
{{ form.level }}
{{ form.color }}
{{ form.intensity }}
{% endfor %}
With 20 products (and 10 empty extra forms) the above code issues 30 select * from ... from level, color and intensity totaling 90 queries (revealed using the Django Debug Toolbar), where 3 should be sufficient. The options are unlikely to change mid request, but even if they did I definitely wouldn't want some newly added options to appear in the last 5 forms only.
Is there any way to optimize my models/forms/views/templates so that the database doesn't get hammered like this unnecessarily?
-
Disclaimer: I'm relatively new to django and python and can't help thinking there must be a way to address this built in somehow.
field_queryset = Test.objects.all()
for form in formset:
form.fields['test_field'].queryset = field_queryset
Like this.
You can change the queryset used by the formset, then you could use select_related() to generate the FK joins rather than to execute a query at each forloop iteration.
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.
I've been implementing caching in my django application, and used per view caching via the cache API and template fragment caching.
On some of my pages I use a custom django template tag, this tag is provided via a third party developer, it takes some arguments in its template tags, and then make a request to a remote server, gets the response back over XML, and then renders the result in my page.
Great - I thought I could easily cache this using fragment caching, so I :
{% load cache %}
{% cache 500 request.user.username %}
{% load third party custom tags %}
{% expensive custom tag set that gets stuff from a third party server via xml %}
{{ some.stuff}}
{% endcache %}
Trouble is no matter what I do, the requests still get fired off to that remote server, it seems Django doesn't like to cache these custom template tags. I know memcached is working great, for other views and templates it all works just fine. Am I doing something that is incompatible with the fragment caching? Is there a way round it?
If the template fragment you're trying to cache can't be pickled, memcached won't be able to store it and will raise an exception. From what I can gather, exceptions generated when rendering Django templates are suppressed. Since your custom tag is doing HTTP requests, maybe socket objects (which can't be pickled) are getting stored to the template fragment somehow.
If this is the case, the only way around it I can think of would be to modify the custom tag to get rid of any leftover socket objects.
Have you tried to use a different name for the cache fragment? There could be a problem with using request.user.username for a couple of reasons:
If a user is not signed in,
request.user.username could be empty,
resulting in a non-named cache
fragment
If a user is signed in, this will
call the 3rd party template tag at
least once for each user every 3
mintues
Maybe it's worth trying to rename the cache fragment name to test:
{% cache 500 customxml %}
I'd also try loading of the 3rd party template tag outside the cache tag like so:
{% load cache third_party_custom_tags %}
{% cache 500 request.user.username %}
{% expensive custom tag set that gets stuff from a third party server via xml %}
{{ some.stuff}}
{% endcache %}
What I'm not sure of is if the cache framework caches the results of a template tag. If that doesn't work, I'd take a look at what the template tag is doing under the hood and re-implement the template tag using Django's low-level cache.
I think the problem is the custom tag, as you suggested.
I disagree that the request.user.username is a problem, as the documentation for the subject actually gives that as an example, and I have used it with internal caching (number of posts, for instance), in testing, and it worked fine.
The low level cache is potentially useful, but I would take a look at your custom tag to see what wouldn't be caching. Without the code it's hard to guess, but my guess would be something like the time, or some other variable, is being returned whic his causing it to force an update (if the XML pulls any data that changes Django may force an update, depending on other settings). I've had mixed results with Django's caching, so I would have a look at your XML feed(s) to see if it's causing anything to stop caching.
I don't think this has anything to do with the custom tag.
We endded up rewriting the Django caching tag because we needed more control than was possible with the one that was supplied. You might make a copy of it yourself and stick some debugging print statements into it. In particular, check the filename (assuming you are caching to files) and see what is being generated. It could be that it is changing when it shouldn't (for some unknown reason) and that would mean that it is always needing to re-render then enclosed block.
Look in django/templatetags/cache.py. It's only 63 lines of code.