How can I use regex in django's Replace function - python

I'm trying to update all urls in my query by using django's update and Replace function using regex.
Here's what I've tried so far but it seems like django's Value expression did not recognize my regex.
from django.db.models import Value
from django.db.models.functions import Replace
Foo.objects.filter(
some_url__iregex=r'^\/some-link\/\d+\/').update(
some_url=Replace(
'some_url', Value(r'^\/some-link\/\d+\/'),
Value('/some-link/')))
My goal is to remove all numbers after /some-link/ (e.g. /some-link/55/test to just /some-link/test)

I wasn't able to get the Replace function from Django working, but I was able to use the Function for REGEXP_REPLACE detailed in this answer: https://stackoverflow.com/a/68402017/3056056

Related

Python parsing update statements using regex

I'm trying to find a regex expression in python that will be able to handle most of the UPDATE queries that I throw at if from my DB. I can't use sqlparse or any other libraries that may be useful with for this, I can only use python's built-in modules or cx_Oracle, in case it has a method I'm not aware of that could do something like this.
Most update queries look like this:
UPDATE TABLE_NAME SET COLUMN_NAME=2, OTHER_COLUMN=to_date('31-DEC-202023:59:59','DD-MON-YYYYHH24:MI:SS'), COLUMN_STRING='Hello, thanks for your help', UPDATED_BY=-100 WHERE CODE=9999;
Most update queries I use have a version of these types of updates. The output has to be a list including each separate SQL keyword (UPDATE, SET, WHERE), each separate update statement(i.e COLUMN_NAME=2) and the final identifier (CODE=9999).
Ideally, the result would look something like this:
list = ['UPDATE', 'TABLE_NAME', 'SET', 'COLUMN_NAME=2', 'OTHER_COLUMN=("31-DEC-2020 23:59:59","DD-MON-YYYY HH24:MI:SS")', COLUMN_STRING='Hello, thanks for your help', 'UPDATED_BY=-100', 'WHERE', 'CODE=9999']
Initially I tried doing this using a string.split() splitting on the spaces, but when dealing with one of my slightly more complex queries like the one above, the split method doesn't deal well with string updates such as the one I'm trying to make in COLUMN_STRING or those in OTHER_COLUMN due to the blank spaces in those updates.
Let's use the shlex module :
import shlex
test="UPDATE TABLE_NAME SET COLUMN_NAME=2, OTHER_COLUMN=to_date('31-DEC-202023:59:59','DD-MON-YYYYHH24:MI:SS'), COLUMN_STRING='Hello, thanks for your help', UPDATED_BY=-100 WHERE CODE=9999;"
t=shlex.split(test)
Up to here, we won't get rid of comma delimiters and the last semi one, so maybe we can do this :
for i in t:
if i[-1] in [',',';']:
i=i[:-1]
If we print every element of that list we'll get :
UPDATE
TABLE_NAME
SET
COLUMN_NAME=2
OTHER_COLUMN=to_date(31-DEC-202023:59:59,DD-MON-YYYYHH24:MI:SS)
COLUMN_STRING=Hello, thanks for your help
UPDATED_BY=-100
WHERE
CODE=9999
Not a proper generic answer, but serves the purpose i hope.

Django SearchVector using icontains

I am trying to search for a list of values in multiple columns in postgres (via django). I was able to use SearchQuery and SearchVector and this works great if one of the search values matches a full word. I was hoping to use icontains so that partial strings could also be used in the search. Is this possible and if so could someone point me in the right direction. Here is an example of my approach below.
Example Data:
Superhero.objects.create(
superhero='Batman',
publisher='DC Comics',
alter_ego='Bruce Wayne',
)
Superhero.objects.create(
superhero='Hulk',
publisher='Marvel Comics',
alter_ego='Bruce Banner',
)
Django filter:
from django.contrib.postgres.search import SearchQuery, SearchVector
query = SearchQuery('man') | SearchQuery('Bruce')
vector = SearchVector('superhero', 'alter_ego', 'publisher')
queryset = queryset.annotate(search=vector).filter(search=query)
This would return the Hulk record but I am hoping I can somehow use like 'icontains' so that when searching for 'man' the Batman record would also be returned. Any help is appreciated!
You can apply icontains to the filter like:
queryset = queryset.annotate(search=vector).filter(search__icontains=query)
So SearchQuery and SearchVector are a part of Django's Full Text searching functionality and it doesnt look like you can achieve what I was wanting to do with these functions. I have taken a different approach thanks to Julian Phalip's approach here.. https://www.julienphalip.com/blog/adding-search-to-a-django-site-in-a-snap/

MongoAlchemy regex return nothing

I'm testing MongoAlchemy for a project and I've to search user by name.
I'm trying to make a regex but query result is always empty.
I tried two methods :
import re
users = User.query.filter({"name":re.compile("/a/", re.IGNORECASE)}).all()
And :
users = User.query.filter(User.name.regex('/a/', ignore_case=True)).all()
Even if I use a very general regex like /.*/, the result is always empty.
Thank you.
In python regular expressions are not defined using /regexp/, this is javascript syntax.
The proper way to initialize regular expressions would be:
re.compile(r".*", re.IGNORECASE)
So you should use:
users = User.query.filter({"name": re.compile(r".*", re.IGNORECASE)}).all()

Django queryset exclude regex

I have a command that filter through requests, and I need to extract some of them following two rules.
It should
include '^https?:\/\/[^.]*\.?site\.co([^?]*[?]).*utm_.*$'
or
exclude '^https?:\/\/[^.]*\.?site\.([^\/]+\/)*'
So, working out a possible SQL representation, I came up with:
exclude (
matching '^https?:\/\/[^.]*\.?site\.([^\/]+\/)*'
and
not matching '^https?:\/\/[^.]*\.?site\.co([^?]*[?]).*utm_.*$'
)
Which translate in django to:
.exclude(
Q(referer__iregex=r'^https?:\/\/[^.]*\.?site\.co([^?]*[?]).*utm_.*$') &
Q(referer__not_iregex=r'^https?://[^.]*\.?site\.[^/]+/?[\?]*$'))
But unfortunately, the __not_iregex lookup doesn't exists. What could be a workaround this?
You could in fact use filter for the part which you don't want to exclude:
queryset
.filter(referer__iregex=r'^https?://[^.]*\.?site\.[^/]+/?[\?]*$')
.exclude(referer__iregex=r'^https?:\/\/[^.]*\.?site\.([^\/]+\/)*')
So here your matching goes into exclude and not matching goes into filter.
Or you could use the ~Q if you really want to imitate what you have in the SQL representation:
.exclude(
Q(referer__iregex=r'^https?:\/\/[^.]*\.?site\.([^\/]+\/)*') &
~Q(referer__iregex=r'^https?://[^.]*\.?site\.[^/]+/?[\?]*$'))
# notice use of ~ here

mysql 'LIKE' in Django python

I am little new to Django,
My Question is How do i do %LIKE% of MYSQL in Django Filter
Want something like this
myModel.objects.filter(myField__**like**="xyz")
as we can do
myModel.objects.filter(myField__startswith="xyz")
for strings that starts with 'xyz' but i want to match anywhere in the myField content.
What i know
it can be done by REGEX and .extra() but i want something very straight forward.
Thanks in advance.
You can do it like this:
myModel.objects.filter(myField__contains = "xyz")
Note: __contains is case sensitive. You can use __icontains if you don't care about the case of the text.
Use the contains operator my_model.objects.filter(my_field__contains='xyz') and icontains if you want case insensitivity

Categories