Django: empty date string should return all - mysql

So, I have a date from input field, and date to input field. When I pass in the date range from and to it works fine. But when I try to leave one or both blank, to get all the items, or partial items, it gives ValueError: Cannot use None as a query value or format error when I try to make the default empty string.
def report(self, request):
date_from = query['date_from'] if query['date_from'] else None
date_to = query['date_to'] if query['date_to'] else None
queryset = Client.objects.filter(
client_code__in=clients,
account__note__creation_time__gte=date_from,
account__note__creation_time__lte=date_to,
)
To give a better context, if I leave both field empty i should get all items from beginning to now, if I fill in date from field but leave date to field empty, I should get all item from date from till now. If I have date to field buy empty date from field, I should get items from beginning till date to.
Got lazy and found a solution that works but not very happy with it. If someone finds something better feel free to share.
query = Q()
if clients:
clients = clients.split(',')
query &= Q(client_code__in=clients)
if date_from:
query &= Q(account__note__creation_time__gte=date_from)
if date_to:
query &= Q(account__note__creation_time__lte=date_to)
Client.objects.filter(query)

If you put a filter on the queryset you have to supply valid values for that filter.. Django can't guess that you actually don't want the filter after all...
But there are ways to make it a little nicer looking, eg:
qs = Client.objects.all()
if date_from:
qs = qs.filter(account__note__creation_time__gte=date_from)
if date_to:
qs = qs.filter(account__note__creation_time__lte=date_to)
# etc etc for all your AND queries.
# but for OR type queries you need to use Q objects.
When you create a queryset, as I did using Client.objects.all, it doesn't actually go to the database and get the objects right away. So you can then modify that queryset by adding additional filters onto it to limit your results. You can use all the different queryset methods.. eg order_by(), fetch_related() etc.. until the queryset is how you want it. It won't actually execute any SQL until you try to read the objects by iterating over the queryset, eg:
# now it will go to the database and get the objects based on your filters.
for instance in qs:
print instance
So you see, in this case, where all your filters are narrowing the search (they are all AND'ed together), there's no need to use Q() and that makes for less typing and clearer code. But if you are doing a query where you are using OR logic or where you are perhaps applying the same query to multiple querysets, then you do need to use the Q class to form that query.

Related

Remove query string pairs until a result is returned

Lets say I have a search form on my site which generates a query string to filter results, eg. mysite/search?field1=value1&field2=value2&field3=value3
The user enters the following into the search fields:
Field 1 = Cat
Field 2 = Black
Field 3 = Stray
Given the nature of a query string, all three field values would have to be present in an item being searched, in order for it to be recognised as a match.. right?
Is there a way to either make the '&' an 'OR', so that any matching field will return a result.
Or
Is there a way to match the nearest result? Ie. Remove string pairs until a match is found, or in some way, find the next closest result.
For example. If the user enters 'Cat', 'Black' and 'Stray' and there is an item that includes all three values, it returns that result (standard response). If there isn't an item that includes all three values, let's say there's only an item that has 'Cat' and 'Stray', it recognizes there are no items containing all three values, so it looks for two field value matches instead?
Happy to consider any ideas to prevent "no items found" and at least render something rather than nothing.
It depends on what you're using for filtering but general idea is that after you filter the data you check if it is empty and if it is you remove one filter do the filtering again. Something like this for example:
result = filter(data,filters);
while(!result || filters.length > 0){
filters.pop();
result = filter(data, filters);
}
Not working code, just general idea.

query to filter on specific data or no filter if blank

I have a query which filters records based on dates (start date and end date)selected in a previous form. I want the query to filter the specific date range, or output all records if the fields are left blank.
I am unfamiliar with SQL. is there a way to add an if-then statement?
I can use vba if necessary, but would like to use the Access GUI if it is possible.
If you have a parameter, used in WHERE clause (Criteria in query builder) and you want to show all records if parameter is empty, just add this parameter as new column and OR condition where indicate Is Null or, better add a column with expression Nz([MyParam],"") and in Condition area inORrow add""`. Unfortunately in query builder this construction may be quite complicated if you have few parameters, in SQL it looks much simpler, for instance in your case it will be something like this:
WHERE (MyDate >= [paramDateStart] and MyDate <= [paramDateEnd])
OR (Nz([paramDateStart],"")="" AND Nz([paramDateEnd],"") = "")
Sometimes simpler edit SQL and then switch to Design view
You can use these criteria for StartDate and EndDate respectively to compare them to themselves in case one (or both) of the search fields on the form is empty (Null):
>=Nz([Forms]![YourForm]![FromDate], [StartDate])
<=Nz([Forms]![YourForm]![ToDate], [EndDate])

Django distinct group by query on two fields

I have a model which have 2 fields.
class MyModel:
tcode = Charfield
created_on = Date field
#some more fields
now this model can have multiple rows with same tcode, and each row can have different day or same.
e.g.
tcode1, 1/2/2001
tcode2, 1/2/2001
tcode2, 2/2/2001
....etc.
I want to filter query on this model such that tcode and date field combination should be unique. how can I get all those objects.
i was trying to do this
MyModel.objects.all().order_by('tcode').distinct('tcode', 'created_on')
Now you may ask that in case if there are two rows with same data in two fields which one row I want! it doesn't matter to me, any row would work fine.
I don't think there's one single query that could do this, because there's no mechanism from database to pick random one from duplicates. However, if you only care about those two fields, you could do:
MyModel.objects.order_by('tcode').values('tcode', 'created_on').distinct()
This won't give you complete MyModel objects, but a list of dictionaries that contain all the existing combinations of tcode and created_on.
Today I faced the same problem. In Django admin in get_queryset method I needed to make the distinct operation in multiple fields. I solved this problem this way:
from django.db.models import TextField
from django.db.models.functions import Concat
Mymodel.objects.filter(...).annotate(distinct_name=Concat('tcode', 'created_on', output_field=TextField())).order_by('distinct_name').distinct('distinct_name')
This decision helps to return QuerySet with ID of the record

SSRS Report - Dataset Filters

I've written a report for SSRS and Im using dataset filters with expressions to filter the report info. I seem to either have this expression wrong or the filter is not working correctly:
=IIf(Parameters!DoctorID.Value = "All" Or Parameters!DoctorID.Value = "", "*", Parameters!DoctorID.Value)
What I want to accomplish with the above code is if DoctorID = ALL or "" (blank) then I want to omit it from the filters so I return information for all doctors. However, whenever the value of DoctorID = ALL, I'm returning no rows what so ever. It should be the case that i'm getting ALL rows since DoctorID is not a specific number.
Does the "*" (star) not denote an omitting of that filter? Am I doing something wrong here?
Thanks!
The filter formula you provide is only half the equation: what is the operator and what are you comparing this to? And yes, I haven't seen SSRS use asterisk as a wildcard.
Consider putting your filter into the query for the dataset. The SQL WHERE clause can get pretty powerful. I would write your filter into the query as
...
WHERE
#DoctorID = 'All' OR #DoctorID = ''
OR #DoctorID = myTable.DoctorID
This will also let you move to a multiple value parameter pretty easily.

Calculating average age in Django

I need to find out average age of items (groupped by various criteria, but it does not seem to be the issue). However I fail to find how to effectively create aggregation over DateTimeField using Django (on top of MySQL).
Pure Item.objects.all.aggregate(Avg('created')) seems to produce absolutely bogus values (eg. 20081988007238.133) and using Item.objects.all.extra(...) I have not found a way how to aggregate.
Of course I can manually create SQL query (something like SELECT AVG(UNIX_TIMESTAMP(created)) FROM items_item), but I'd prefer to avoid using MySQL specific code in the application.
Just for the reference, sample model I use for testing:
class Item(models.Model):
name = models.CharField(max_length = 255)
created = models.DateTimeField()
I think there is no other way as using the extra method. It should look like this then (not tested):
Item.objects.extra('avg': 'AVG(UNIX_TIMESTAMP(created))'.values('avg')
The problem is, that you have to convert the date to a UNIX timestamp before. Otherwise you cannot calculate the average. An average of string will indeed produce garbage.