Define Filter on django-datatable-view - django

I am using django-datatable-view to show my data. I have a scenario that I need to retrieve records from a model, that satisfy certain conditions.
For example, the request could be described as:
"SELECT * FROM model WHERE column_1='value_1' AND column_2='value_2'
How could I implement this? Actually, I saw the examples, but I don't have an efficient idea to do this.
Would you please help me in View definition or refer to proper sample?

It seems that we should implement a get_queryset(self) method to apply on targeted filters:
def get_queryset(self):
return Entity.objects.filter('item_1'='value_1')
While this could results in proper table values, but, the performance of loading decreases significantly.
Maybe other solutions could save the performance, or we should use other techniques like caching.

I think that the correct answer is pointed out in official documentation
You can filter QuerySet as it's shown in the example:
Entry.objects.filter(pub_date__year=2006)
For your case it could be:
Entry.objects.filter(column_1='value_1').filter(column_2='value_2')
Also it is possible duplicate of this topic

Related

Return QuerySet from a RawQuerySet

I am trying to create a queryset from a rawqueryset, but the changelist is always saying Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user.
This is my attempt (is a simple query, but it will became more complex and I need a raw SQL query):
class MyModelAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = MyModel.objects.raw('SELECT field1, field2 FROM MyTable)
return qs
Is there any way to show this raw query in my changelist view applying admin.site.register(MyModel, MyModelAdmin) in admin.py?
It's been a while, and versions seem to have changed a lot since then, however you used to be able to simple convert the qs itself to a string or the query attribute contained within the qs, and it would spell out the sql for you.
e.g. sql = str(qs) or sql = str(qs.query)
That being said, django modifies the table names. It's probably not MyTable you're looking for, but appname_my_table. Browse the django core to find out exactly what the naming specification is, or perhaps get it from model_instance._meta.db_name or similar property.
update: ok it seems I misunderstood the question, you don't want to 'print' the queryset to inspect the sql it generates at all, you need the ModelAdmin to pass a RawQuerySet instead of a regular QuerySet to its ChangeView.
Short answer: No, its not going to work that way. They are two very distinct classes.
It looks like they behave the same, because you can iterate them and when you do it turns out to contain proper model instances. However its missing a plethora of other functionality that the ModelAdmin's changeview has come to rely upon over time. I'm not even sure if it actually has a Manager.
The only option that comes to mind, is using either:
Use Model.objects.extra(...) instead of Model.objects.raw(...), so that it returns a proper QuerySet.
Create a view using your database software, Postgres or MySQL, what have you. And map that to a simple django Model.
You can try and recreate all the missing functionality by wrapping the RawQuerySet in a little proxy class that passes everything on to the RawQuerySet and implement the missing methods yourself. I do not recall which those were, probably you need to override __and__ and __or__, provide it with a custom manager, at the very least. I've done this before and its very possible but I guarantee a lot of work, especially if you expect ALL of the usual admin magic to work, think filterspecs, search, inline relationships. Expect to hurt your brain, or learn to live without most of the admins benefits you've come to love.
The thing is, using raw(...) basicly results in being entirely seperated from django's ORM, even though at first glance it fools you into thinking that this is not the case (primarily because its iterator returns proper Model instances). Ofcourse your ModelAdmin's ChangeView has not got the slightest clue of what to do with it.
Kind regards,
You can subclass models.Manager and create a method that executes raw SQL as a subquery in the where clause.
https://gist.github.com/carymrobbins/8477219

Accessing related models with django-tables2

Can anyone provide a clear example of how to create a table object using django-tables2 that selects and presents data from multiple related models (ie a relational join)? The documentation implies this is possible, but does not say how.
In normal django the select_related() function works nicely, but I cannot work out how to implement this in django-tables2. I note there are other unanswered questions on similar topics.
First, select_related() is not required to access related data, it is there for performance reasons. For django-tables2, you need to define an accessor. An example is here: https://github.com/bradleyayers/django-tables2/issues/106

django design pattern/best practice: filtering a queryset

I have a page where I'm displaying the results of a queryset to the user.
What i'd like to do is allow the user to click on a link in order to apply a filter.
Currently what I do is have the links pass "get" parameters to the page in order to apply filters. The filters can be references to other models or custom filters (e.g. an unassigned filter)
In order to provide a decent user experience the implementation needs to do a few things
in the view:
check that the filter parameter passed is valid
check what type of filter it is (based on other models or a custom filter) in order to apply the correct condition to the queryset
(optional) a way to make the filters cumulative (i.e. you can keep adding filters)
in the Template:
display the correct resultset based on the filter choosen
when displaying the filters, recognize which filter we have applied so that the current applied filter is displayed as text not a hyperlink.
I'm thinking this must be common enough that someone must have like a design pattern or best practice figured out for this other than the obvious whack of if/else statements in the view and the template.
is there?
I find the way the Django admin handles this kind of functionality a great pattern. If you're not familiar, check out the list_filter option in the admin. It's similar to what you're describing, but yours is a bit more generic. Perhaps this will help you ponder some ideas?
First, for the actual querystring chunk, you're simply passing the Django-ORM lookup key and value pair. e.g., ?sites__id__exact=1, tags__in=words, etc. Since you want to allow for cross-model lookups, you'd need to provide another parts in the string to include the model name, not too tough.
For checking if the filter is valid, you can simply ensure that the model/field lookup is valid. By splitting the parts of each QS chunk, you can identify the model, the fieldname, the lookup, and the value. Then, use Django's built-in functionality to validate that fieldname exists on model. You can do this with ForeignKey's too. Here's how Django does it
You can keep adding filters pretty easily to this. You'll be providing your view and the form that's displaying these filters with some context, so it'll persist and re-populate for the user. Also, you could just as easily persist the query string. Basically, you'd have the same read / parsing functionality here at all times, nothing really different.
I think the keys are automating and keeping it as DRY as possible. Don't succumb to a bunch of if statements. It's really easy to pass these lookups into the ORM, safely too, and it's really easy to catch bad lookups and provide the user with a meaningful error message.
I hope that helps you on your path! :)

Django passing querysets between pages

I have a view which does a pretty heavy query on three separate databases and outputs the count of each query into a template. From the the user can go to one of the three results and get the detailed results. I don't want to repeat myself in my views and I want to maximize performance, so my question is what is the best way to achieve this result?
Can I pass a queryset to another page (get or post)?
Should I save the queryset in a session (I am not currently using session for this project as it is fully public)
Or is there a better way?
I know this is not a highly specific question, but I would appreciate any advice on this (I'm guessing - not uncommon) situation.
From my experience, I think saving your result on session is a good and simple solution.
Save the result of the querysets to the session. When I say to save the results, what I mean is to run list() on it to execute them, and then store the resulting list in request.session.
sounds like you want to have a look at caching

about annotate django

I'd like to create the top five best seller of the products in each month.
I've heard that the annotations must be used for this case but I don't know how to use it.
Will anybody be kind enough to help me ??
You need to provide much more information before anyone can provide you with a useful answer. Describe what you know, what you've tried, elaborate on what you hope to accomplish.
In the mean time, you can learn about django's annotate() function, and see a few examples by reading the aggregation documentation for django.
annotate is not the only way to do it. You could also use an extra aggregation, though it might not be very efficient, and this will rely on sql specific to your database. This approach will not work in App Engine, but should in a SQL compliant database.
For example, say you had a Product model and a SalesOrder model, where the SalesOrder model has a line item for each product_id and order_date in it.
top_products = Product.objects.extra(
select={'num_orders':'select count(product_id) from app_product where app_salesorder.order_date > thirty_days_ago and app_product.id = app_salesorder.product_id'})
.order_by('-num_orders')[:5]