Can web2py list contains() be negated? - list

I am trying to select a table where a certain value is not present in a reference field. Is it possible to negate the contains() method?
grid = SQLFORM.smartgrid(db.redaktion.projekt.contains(projektid)

The negation operator in pyDAL queries is ~. Also, the first argument of smartgrid must be a Table rather than a Query. To apply a query to a given table, use the constraints argument. So, it would be:
grid = SQLFORM.smartgrid(db.redaktion,
constraints={'redaktion': ~db.redaktion.projekt.contains(projektid)})
See http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#Logical-operators.

Related

Django Filter on Distinct with orderby created at

How can I filter with distinct and order by
IncomingCallRecording.objects.filter().order_by("lead_id","-created_at").distinct("lead_id")
Problem:
Order by is not working with created at
Is there an alternative solution that might help
You can just use created_at in order_by.
IncomingCallRecording.objects.order_by("-created_at").distinct("lead_id")
Multiple columns sorting is done in sequence. If you define two columns in order_by, it sorts by first column and then second column (first by lead_id, and then within each lead_id sort by created_at).
Update
The solution would be subjected to database. For MYSQL, DISTINCT ON isn't allowed. For POSTGRES, DISTINCT ON expression must match ORDER BY.
In case of POSTGRES, you will need to use Subquery, if you would like to use different DISTINCT ON and ORDER BY expressions.
IncomingCallRecording.objects.filter(
pk__in=Subquery(
IncomingCallRecording.objects.distinct('lead_id').values('pk')
)
).order_by('-created_at')

Django Model.objects.get(...) case-insensitivity

I am developing a dictionary application and I have an Expression model defined as follows:
class Expression(models.Model):
expression = models.CharField()
In one of my views, I am using Expression.objects.get_or_create(expression=expression).
Importantly, I want the comparison between "expression" and all existing Expression objects in my database to be case-insensitive.
In other words, even though this is not valid syntax, I would like the logic of my search to be: Expression.objects.get_or_create(expression.lower()=expression.lower())
How can I achieve that?
You can do case-insensitive filter as below:
Expression.objects.get_or_create(expression__iexact=expression.lower())
Look at documentation for other field lookups.
Note: get_or_create method can create duplicate items in database because of race condition. Be sure that you pass unique field or fields that are unique together to this method for avoiding possible duplicates.

Django Array contains a field

I am using Django, with mongoengine. I have a model Classes with an inscriptions list, And I want to get the docs that have an id in that list.
classes = Classes.objects.filter(inscriptions__contains=request.data['inscription'])
Here's a general explanation of querying ArrayField membership:
Per the Django ArrayField docs, the __contains operator checks if a provided array is a subset of the values in the ArrayField.
So, to filter on whether an ArrayField contains the value "foo", you pass in a length 1 array containing the value you're looking for, like this:
# matches rows where myarrayfield is something like ['foo','bar']
Customer.objects.filter(myarrayfield__contains=['foo'])
The Django ORM produces the #> postgres operator, as you can see by printing the query:
print Customer.objects.filter(myarrayfield__contains=['foo']).only('pk').query
>>> SELECT "website_customer"."id" FROM "website_customer" WHERE "website_customer"."myarrayfield_" #> ['foo']::varchar(100)[]
If you provide something other than an array, you'll get a cryptic error like DataError: malformed array literal: "foo" DETAIL: Array value must start with "{" or dimension information.
Perhaps I'm missing something...but it seems that you should be using .filter():
classes = Classes.objects.filter(inscriptions__contains=request.data['inscription'])
This answer is in reference to your comment for rnevius answer
In Django ORM whenever you make a Database call using ORM, it will generally return either a QuerySet or an object of the model if using get() / number if you are using count() ect., depending on the functions that you are using which return other than a queryset.
The result from a Queryset function can be used to implement further more refinement, like if you like to perform a order() or collecting only distinct() etc. Queryset are lazy which means it only hits the database when they are actually used not when they are assigned. You can find more information about them here.
Where as the functions that doesn't return queryset cannot implement such things.
Take time and go through the Queryset Documentation more in depth explanation with examples are provided. It is useful to understand the behavior to make your application more efficient.

In Django, is there a way to set field values with a query expression on objects returned from a queryset?

I have a proxy model which has to have some calculated (with query expressions) read-only fields. Annotating won't do, because I will later need to have field metadata to do filtering in my views.
So, is there a way to call a SQL function to get the value?
I am looking for something like a QuerySet.annotate for fields, a Transform or a custom field that would do this.
I found a way to do this by using the Col Expression and a custom field.

Django Nested Filter Values

This line works and returns the value that I'm looking for:
logs = Log.objects.filter(filterURI=aFilter.uri).values()[0]['yk']
However, when I try to add another filter and do the same I get errors:
logs = Log.objects.filter(filterURI=aFilter.uri).filter(k=k-1).values()[0]['yk']
My understanding is that a object.filter returns a queryset but so does a 'filter of a filter'. So I should be able to do the 'values' call in the same way regardless of whether I have one filter or 1000.
What am I doing wrong here.
Thanks in advance.
I don't think the error is in the fact that you have two filters - it's in the actual second filter. k=k-1 will only work if you have both a model field and a local variable called k - the first is on the left of the expression, the second on the right.
If you want to refer to the model field on the right of the expression, use F:
.filter(k=(F('k')-1)