Django raw sql query - mysql

I have a this model:
class Document(models.Model):
data = models.TextField()
users = models.ManyToManyField(User)
How would you convert the following query for the model above to raw sql?
Document.objects.annotate(num_users=Count(users))
I need to switch this to raw sql because there is a bug in django when using MySql that makes annotate very slow.
But I'm not sure how to handle the many to many field in raw sql..
Document.objects.raw('SELECT ...')

The easiest way to translate your Django query to SQL is to simply look at the SQL that Django generates: How can I see the raw SQL queries Django is running?

you can get corresponding query the way mentioned below:
queryset = Document.objects.annotate(num_users=Count(users))
sql_query = queryset.query
print(sql_query)

Related

get distinct "title" in mysql in django

I have used django to develop a web app.
I want to get the distinct "title" form the queryset get by filter.
But I use mysql so could not pass "title" to distict.
How could I filter the queryset with the distinct "title"?
query_set = CourseInfo.objects.filter(discipline_id=id).distinct('title')
return render(request, 'main.html',
context={'query_set':query_set})
I get error for this in mysql as it may only used in postgresql
`
It will give you distinct titles:
titles = CourseInfo.objects.filter(
discipline_id=id
).order_by('title').values('title').distinct()
Note:
there is no such thing called SELECT DISTINCT ON in MySQL.
You can only use it in Postgresql but maybe GROUP BY helps you for converting SELECT DISTINCT ON query to MySQL query.
Check out this link then you kinda can convert this query to MySQL query.

Writing to MySQL with Python without using SQL strings

I am importing data into my Python3 environment and then writing it to a MySQL database. However, there is a lot of different data tables, and so writing out each INSERT statement isn't really pragmatic, plus some have 50+ columns.
Is there a good way to create a table in MySQL directly from a dataframe, and then send insert commands to that same table using a dataframe of the same format, without having to actually type out all the col names? I started trying to call column names and format it and concat everything as a string, but it is extremely messy.
Ideally there is a function out there to directly handle this. For example:
apiconn.request("GET", url, headers=datheaders)
#pull in some JSON data from an API
eventres = apiconn.getresponse()
eventjson = json.loads(eventres.read().decode("utf-8"))
#create a dataframe from the data
eventtable = json_normalize(eventjson)
dbconn = pymysql.connect(host='hostval',
user='userval',
passwd='passval',
db='dbval')
cursor = dbconn.cursor()
sql = sqltranslate(table = 'eventtable', fun = 'append')
#where sqlwrite() is some magic function that takes a dataframe and
#creates SQL commands that pymysql can execute.
cursor.execute(sql)
What you want is a way to abstract the generation of the SQL statements.
A library like SQLAlchemy will do a good job, including a powerful way to construct DDL, DML, and DQL statements without needing to directly write any SQL.

Does Knex.js prevent sql injection?

I'm using a MySql database and was trying to find a MySQL alternative to tedious.js (a SQL server parameterised query builder).I'm using Node.js for my backend.
I read that the .raw() command from knex.js is susceptible to sql injection, if not used with bindings.
But are the other commands and knex.js as a whole safe to use to prevent sql injection? Or am I barking up the wrong tree?
Read carefully from knex documentation how to pass values to knex raw (http://knexjs.org/#Raw).
If you are passing values as parameter binding to raw like:
knex.raw('select * from foo where id = ?', [1])
In that case parameters and query string are passed separately to database driver protecting query from SQL injection.
Other query builder methods always uses binding format internally so they are safe too.
To see how certain query is passed to database driver one can do:
knex('foo').where('id', 1).toSQL().toNative()
Which will output SQL string and bindings that are given to driver for running the query (https://runkit.com/embed/2yhqebv6pte6).
Biggest mistake that one can do with knex raw queries is to use javascript template string and interpolate variables directly to SQL string format like:
knex.raw(`select * from foo where id = ${id}`) // NEVER DO THIS
One thing to note is that knex table/identifier names cannot be passed as bindings to driver, so with those one should be extra careful to not read table / column names from user and use them without properly validating them first.
Edit:
By saying that identifier names cannot be passed as bindings I mean that when one is using ?? knex -binding for identifier name, that will be rendered as part of SQL string when passed to the database driver.

Getting the raw SQL query string from the ORM

How do I get the raw SQL string sent to the server from the ORM? How do I intercept it in order to do custom work?
I want to forward the query to a custom driver. My target is MS SQL Server via NodeJS - from a Linux environment.
But I don't want to reinvent the wheel. I want to reuse the existing SqlServer query builder.
As long as your query is not executed by toArray() or something similar, you can use $q->sql() to retrieve the raw sql query that cakePHP will execute:
$q = $this->Model->find('all');
$this->log($q->sql()); // log raw sql query
$query = $this->find();
debug($query);
$query is a query object from where you can get the raw SQL expression.

Using raw sql in django

What would be the equivalent raw sql for the following:
def index:
Emails.objects.create(email=request.POST['invite_email'])
I have this so far, but I can't quite get the quotations working --
cursor = connection.cursor()
cursor.execute("insert into splash_emails (id, email) values ('0','request.POST[invite_email]')")
transaction.commit_unless_managed()
What would be correct way to write this, and is this the simplest way to perform raw sql?
If you ever want to see the queries django is using you can do:
emails = Emails.objects.create(email=request.POST['invite_email'])
print emails.query
It's a bit verbose, but you'll get the gist.
I think after reading the Django cookbook chapter on Security, you'll have a good idea on how to execute raw sql AND execute it safely.