I need help in getting a list of fields in a Queryset.
I am using Django shell to test, but I haven't had any luck.
If I do .values like below
abc = PrescribedMedsSchedule.objects.filter(medication_date=scheduled_date_obj, medication_time__time=scheduled_time_obj) \
.select_related('prescribed_meds_id') \
.select_related('prescribed_meds_id__childno') \
.values(
'prescribed_meds_id',
'medication_date',
'medication_time',
'quantity',
'form',
'prescribed_meds_id__name_of_medication',
'prescribed_meds_id__childno__child_name',
'prescribed_meds_id__childno__group',
'prescribed_meds_id__childno__line_no'
).order_by('prescribed_meds_id__name_of_medication')
I get the exact column names that I can use in the template, when I type abc in shell.
QuerySet [{'prescribed_meds_id': 5731, 'medication_date': datetime.date(2020, 2, 4), ....
But if I use .only instead of .values, when I type abc, I get a
QuerySet [<PrescribedMedsSchedule: PrescribedMedsSchedule object (6117) ....
How can I retrieve/display the fields/columns in this queryset?
The reason I am asking is that the fields in the select_related tables no longer appears in the HTML template when I use .only.
Use QuerySet.values if you want the resulting queryset to contain dictionaries and QuerySet.only if you want the resulting queryset to contain model instances.
You can observe that the result query using values or orders are the same when you print it in terminal.
print(abc.query)
If you like to still use QuerySet.only and retrieve queryset results as an iterable of model instances, then you can access the related fields using the dot operator. For example, to output child name in the template:
{% for a in abc %}
{{ a.prescribed_meds_id.childno.child_name }}
{% endfor %}
Related
Like you see the codes below, I'm manually using an attribute status in Store model to show my stores in HTML Templates. The problem is the more codes I make, the more repeating codes happen.
I'm trying to find a way to avoid those inefficient repetitions. Is it possible to set up in models.py to show only active stores to be shown in HTML templates?
I'm asking this because I've already done a similar thing to this. I have a string type attribute, but I need it in a list format in my templates, so I made a function to call it only with a list format. But, I can't figure out how to hide inactive stores in the same way.
Can anyone give me some suggestins for this?
models.py
class Store(models.Model):
status = models.CharField(max_length=20,
choices=(
('active', 'Active'), # ('Stored value', 'Label shown on the UI')
('inactive', 'Inactive'),
),
default='inactive')
...
HTML Templates
{% if store.status == 'active' %}
... Show store
{% else %}
... Do not show store
{% endif %}
Usually, though, People need to select only a subset of the complete set of objects. To refine the initial QuerySet, Here are the two most common ways to proceed:
Use filter() or exclude() with your queryset before sending it to the template.
filter(kwargs**)
Returns a new QuerySet containing objects that match the given lookup parameters.
active_stores = Store.objects.filter(status='active')
# send active_stores to template
or
exclude(kwargs**)
Returns a new QuerySet containing objects that do not match the given lookup parameters.
active_stores = Store.objects.exclude(status='inactive')
# send active_stores to template
In your template, you can loop through without a problem of inactive stores
{% for store in active_stores %}
{{ store }}
{% empty %}
No stores
{% endfor %}
See further explanations in the Django Documentation
Do not filter in the template language, filter in Python. From within the view function and/or class, make sure to filter the queryset:
objs = stores_queryset.filter(status='active')
Then work with the filtered objs in the template, and just iterate over objs without a conditional. It's best to keep logic out of templates entirely, always passing in the correctly prepared context data.
I have 2 models Product an Categories. between them there is a many-to-many-relation.
I have the following code:
In view:
context['products']Product.objects.all().prefetch_related(Prefetch('categories', queryset=Category.objects.only('name')))
In template:
{% for product in products %}
{{ product.categories.all.0.name}}
In this case prefetch_related is ignore, and it exeutes anew query in categories for each product.
If I remove only, it executes just 2 queries
Why ?
You can't use a queryset with only the name field, as Django will at least need the product_id to match the Category object with the Product - since you have excluded it, Django will automatically make a separate query each time to fetch it. This happens at query time, even before the object it sent to the template.
Category.objects.only('name', 'product_id') would work.
I am trying to query a table where I have many records with the same name, on purpose. In my example, I'm using the make of the car, and unfortunately I've already ruled out using a foreignkey. Long story. Anyway, I've been able to determine that I can query the table using a ModelChoiceField and using the distinct command as I'm using Postgresql as shown below:
class Vehicle(forms.Form):
dropdown = forms.ModelChoiceField(queryset=Car.objects.none())
def __init__(self, *args, **kwargs):
super(Vehicle, self).__init__(*args, **kwargs)
self.fields['dropdown'].empty_label = ''
qs = Car.objects.distinct('vehicle_make')
The code above does what I need related to the dropdown, it limits the ModelChoiceField to just the unique values of the vehicle_make of the car.
The challenge is when I go to try to display all of the records with that vehicle_make in my template. I've tried to do a Detail View, but it is only showing me that individual record. That make sense since detail view is just for that record, but I'm trying to figure out how to query the table to show me all of the records with that vehicle_make. I've explored the ChoiceField as well, but can't seem to get this to work either. I've tried several variations of the code below in the template, but nothing seems to work.
{% for vehicle_make in car.queryset %}
{{ vehicle_make }}
{% endfor %}
My model is as follows:
Car(models.Model):
vehicle_make = models.Charfield(max_length=264,unique=False)
def __str__(self):
return self.vehicle_make
Thanks in advance for your input and suggestions.
You can query for all Car objects with a given value for vehicle_make with Car.objects.filter(vehicle_make = 'foo'). For example, this ListView would list all cars:
from django.views.generic.list import ListView
from .models import Car
class CarListView(ListView):
context_object_name = "car_list"
queryset = Car.objects.all()
Whereas this view would list all cars of make 'foo':
class FooCarListView(ListView):
context_object_name = "car_list"
queryset = Car.objects.filter(vehicle_make = 'foo')
One easy way to make this more "dynamic" would be to look for a search query in the url, either as a keyword argument or as a querystring. You could use your existing form to create a URL like this, then parse it in a view. For instance, this view would look for URLs appended with ?search=bar:
class SearchableCarListView(ListView):
context_object_name = "car_list"
def get_queryset(self):
search_term = self.request.GET.get('search', None)
if search_term is not None:
return Car.objects.filter(vehicle_make = search_term)
return Car.objects.all()
Your use case may be better served by using an icontains or iexact lookup, or even by making use of Django's full text search.
In the template for any of these views, you can access all of the Car objects in your queryset like so:
{% for car in car_list %}
{{car}}
{% endfor %}
I hope that I have understood and addressed your question. I am not 100% sure how you are using your form right now, so please let me know if I have overlooked anything there.
After our discussion in the comments, I think you are overcomplicating things with your form, and I think that your lookup might not be doing what you want.
We will get a ValuesQuerySet of all distinct vehicle_make values:
qs = Car.objects.values('vehicle_make').distinct()
(See: Select DISTINCT individual columns in django?)
This returns a ValuesQuerySet that looks like this:
<QuerySet [{'vehicle_make': 'vehicle_make_1'}, {'vehicle_make': 'vehicle_make_2'}...]
Where vehicle_make_1, vehicle_make_2 etc. are your distinct values.
We can give this queryset qs to our template and construct a select element. We could also simplify it first to a list of values to make it easier to work with in the template:
values_list = [ c['vehicle_make'] for c in qs.all() ]
Pass that value to our template and use it to make our select element:
<select name='search'>
{% for vehicle_make in values_list %}
<option value = {{vehicle_make}} > {{vehicle_make}} </option>
{% endfor %}
</select>
From here you have several options. In my opinion, the simplest thing would be using this select element in a form that uses the GET method to construct a search URL like we discussed earlier. Check out the first answer to this question for more info: <form method="link" > or <a>? What's the difference? There is a code snippet in the first answer to that question that can easily be adapted to create a GET-based search form with your newly-created select element.
Say I have a model:
class Entry(models.Model):
...
tags = TaggableManager()
When I iterate over Entry.objects.all() in a template, entry.tags.all produces one more query to the database. Is it possible to reduce queries number? Using something like select_related() (I know it won't work, since django-taggit uses manytomany relation, but I am sure there should be a way to select all entries with related tags in 1 hit)?
From Django 1.4 onward, you can use prefetch_related to retrieve one-to-many relations on a queryset in a single query. Unfortunately this doesn't work brilliantly with django-taggit, because the 'tags' property is a manager rather than a true relation, and so prefetch_related can't make sense of it. Instead, you need to follow the tagged_items relation:
entries = Entry.objects.prefetch_related('tagged_items__tag')
You then need to go through some similar contortions in the template code to access the prefetched tags, because entry.tags.all will run another query rather than making use of the prefetch:
{% for tagged_item in entry.tagged_items %}
<li>{{ tagged_item.tag.name }}</li>
{% endfor %}
Try using Select Reverse it's designed to grab the entirity of a many2many relationship with a single query.
Is it possible to combine a Django Haystack search with "built-in" QuerySet filter operations, specifically filtering with Q() instances and lookup types not supported by SearchQuerySet? In either order:
haystack-searched -> queryset-filtered
or
queryset-filtered -> haystack-searched
Browsing the Django Haystack documentation didn't give any directions how to do this.
You could filter your queryset based on the results of a Haystack search, using the objects' PKs:
def view(request):
if request.GET.get('q'):
from haystack import ModelSearchForm
form = ModelSearchForm(request.GET, searchqueryset=None, load_all=True)
searchqueryset = form.search()
results = [ r.pk for r in searchqueryset ]
docs = Document.objects.filter(pk__in=results)
# do something with your plain old regular queryset
return render_to_response('results.html', {'documents': docs});
Not sure how this scales, but for small resultsets (a few hundred, in my case), this works fine.
From the docs:
SearchQuerySet.load_all(self)
Efficiently populates the objects in the search results. Without using
this method, DB lookups are done on a per-object basis, resulting in
many individual trips to the database. If load_all is used, the
SearchQuerySet will group similar objects into a single query,
resulting in only as many queries as there are different object types
returned.
http://django-haystack.readthedocs.org/en/latest/searchqueryset_api.html#load-all
Therefore, after you have a filtered SQS, you can do a load_all() on it and just access the database objects via SearchResult.object. E.g.
sqs = SearchQuerySet()
# filter as needed, then load_all
sqs = sqs.load_all()
for result in sqs:
my_obj = result.object
# my_obj is a your model object
If you want to keep up with the pertinence, you have to access the object from the database through "object" :
example in your template:
{% for result in results %}
{{ result.object.title }}
{{ result.objects.author }}
{% endfor %}
But this is really bad since haystack will make an extra request like "SELECT * FROM blah WHERE id = 42" on each results.
Seems you're trying to get those object from your database because you didn't put some extra fields in your index ins't it ? If you add the title AND the author in your SearchIndex, then you can just use your results:
{% for result in results %}
{{ result.title }}
{{ result.author }}
{% endfor %}
and avoid some extra queries.