Sql query in django. How to translate? - python

I have this SQL query:
"INSERT INTO $TABLENAME (address, count) VALUES(%s, %s) \
ON DUPLICATE KEY UPDATE count = VALUES(count) + count"
How to translate it into django ?

I think you're looking for get_or_create https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create
Fore example lets assume $TABLENAME is represented by a django model called MyModel:
models.py:
class MyModel(models.Model):
address = models.CharField(max_length=300, unique=True)
count = models.IntegerField(default=0)
views.py:
new_model, created = MyModel.objects.get_or_create(address="123 1st st")
new_model.count += 1
new_model.save()
get_or_create will either create a new object with the given properties or if it already exists it will return the existing object which you can then update.

Related

how can we update one to one relationship models db data from django?

i am new to django and i created onetoOneField relationship model with inbuilt User model of django but i cant figure out how can i update that model class table value.
My model
class category(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
TYPES = [
("BASIC","BASIC"),
("PLUS","PLUS"),
("PRO","PRO")
]
User_Type = models.CharField(max_length=40,choices=TYPES,default="BASIC")
Product_Limit = models.IntegerField(default=0)
Amount_Paid = models.IntegerField(default=0)
Tried these 2 cases but getting some error
#key = category.objects.update_or_create(id=request.user.id,User_Type= request.user.category.User_Type,Product_Limit=2,Amount_Paid=request.user.category.Amount_Paid)
user = request.user.category.update_or_create(Product_Limit=10)
Try this:
category = Category.objects.filter(user=request.user).update_or_create(
user=user, Product_Limit=10
)
This will make two SQL queries:
First, Django will make a SELECT ... FROM category WHERE user_id = .... As category and user has a one to one relationship, this should return 0 or 1 row.
If the first query has no record, Django will make an INSERT INTO category query with user_id=request.user.id and Product_Limit=10, the other fields following the default values.
If the first query has a record, Django will make a UPDATE category SET user_id = ..., Product_Limit = ... WHERE user_id = ... query to update the Product_Limit field.

How to use temp table count values into into the where query in Django Raw Sql?

I need to use raw sql in my django project. I'm using count command and then I associated it with as command like "the_count" but i got an error. The error like this, the_count does not exist.
And my my code here,
# First Model
class AModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_lenth=100)
# Second Model
class BModel(models.Model):
a_model = models.ForeignKey(AModel, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
query = 'SELECT "app_AModel"."id",
(SELECT COUNT(*) FROM "app_BModel" INNER JOIN ON ("app_BModel"."user_id" = "app_AModel"."user_id") WHERE ("app_BModel"."a_model_id" = "app_AModel"."id")) AS "the_count"
FROM "app_AModel"
WHERE ("the_count" = 0)'
BModel.objects.raw(query)
Thank you for yours helps...
From postgreSQL documentation
An output column's name can be used to refer to the column's value in
ORDER BY and GROUP BY clauses, but not in the WHERE or HAVING clauses;
there you must write out the expression instead.
Also you probably want to use GROUP BY and HAVING on my_app table instead so something in a line of following:
SELECT a_model_id, COUNT(*) from app_BModel GROUP BY a_model_id HAVING count(*) > 0

Peewee query with join doesn't work as expected

I'm new to peewee and currently trying to migrate from normal Python SQlite3 library.
While my code generate a valid SQL query that return result as expected using a SQlite DB browser, trying to get the value of a field return AttributeError: x object has no attribute y.
Model:
class TableShows(BaseModel):
sonarr_series_id = IntegerField(column_name='sonarrSeriesId', unique=True)
title = TextField()
class Meta:
table_name = 'table_shows'
class TableHistory(BaseModel):
sonarr_series_id = ForeignKeyField(TableShows, field='sonarr_series_id', column_name='sonarrSeriesId')
class Meta:
table_name = 'table_history'
Peewee Query:
data = TableHistory.select(
TableShows.title,
TableHistory.sonarr_series_id
).join(
TableShows
).order_by(
TableShows.title.asc()
)
Resulting SQL query:
SELECT "t1"."title", "t2"."sonarrSeriesId"
FROM "table_history" AS "t2"
INNER JOIN "table_shows" AS "t1" ON ("t2"."sonarrSeriesId" = "t1"."sonarrSeriesId")
ORDER BY "t1"."title" ASC
Resulting dicts():
{'title': u'Test title', 'sonarr_series_id': 1}
Why does running this:
for item in data:
print item.title
Return this:
AttributeError: 'TableHistory' object has no attribute 'title'
http://docs.peewee-orm.com/en/latest/peewee/relationships.html#selecting-from-multiple-sources
You access the data via item.sonarr_series_id.title
You might consider naming your fields something a bit more pythonic.

Django db raw MySQL execute

I have a model and custom manager
model
class VideoDescription(models.Model):
title_eng = models.CharField(max_length=120, unique=True)
title_ru = models.CharField(max_length=120, unique=True)
slug = models.SlugField(max_length=200, unique=True, blank=True)
rating = models.IntegerField(default=0)
pub_date_start = models.DateField()
poster = models.ImageField(upload_to=get_poster_path)
genre = models.CharField(validators=[validate_comma_separated_integer_list], max_length=10, default=0)
description = models.TextField(blank=True)
objects = VideoDescriptionManager()
class VideoDescriptionManager(models.Manager):
def get_video_by_genre(self, genre):
from django.db import connection
with connection.cursor() as cursor:
cursor.execute('''select m.id, m.title_eng, m.title_ru, m.slug, m.rating, m.pub_date_start,
m.poster, m.genre, m.description, COUNT(*) from main_app_videodescription m
where genre like "%%%s%%";''', [genre])
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], title_eng=row[1], title_ru=row[2], slug=row[3], rating=row[4],
pub_date_start=row[5], poster=row[6], genre=row[7], description=row[8])
p.num_responses = row[9]
result_list.append(p)
return result_list
And i've got a error:
django.db.utils.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 1 supplied.
Google talking me change [genre] to (genre,) in a raw sql query but it doesn't help.
What can i do to fix it?
sqlite does not use %s for parameters, it uses ?.
But either with sqlite or another db, you can't use the parameter substitution to insert a param in the middle of a string. You need to build up the string separately, and then insert it using the parameters. So:
param = "%{}%".format(genre)
cursor.execute('''select m.id, m.title_eng, m.title_ru, m.slug, m.rating, m.pub_date_start,
m.poster, m.genre, m.description, COUNT(*) from main_app_videodescription m
where genre like ?;''', [param])
Note that using .format removes the need to double-escape the percents.

MySQL INSERT ... ON DUPLICATE KEY UPDATE with django 1.4 for bulk insert

I am having issues figuring out MySQL INSERT ... ON DUPLICATE KEY UPDATE with django 1.4.
The table that I am trying to insert records has a 2 column(composite) unique key. Records that I am receiving is from a 3rd party source and values will change over time except for those fields that makes the unique key set. I am receiving 1 ~ 5k records at a time, and would need to
Currently I am using Model.objects.bulk_create to bulk insert, performance is really amazing as it issues generally one query no matter how big the record set is. However, as my records can change over time on the 3rd party end, I need to perform the MySQL INSERT ... ON DUPLICATE KEY UPDATE query on the recordset.
I am planning to write raw SQL statements and execute using something like here:
sql = "MySQL INSERT ... ON DUPLICATE KEY UPDATE"
raw_insert(sql)
def raw_insert(sql):
from django.db import connection, transaction
cursor = connection.cursor()
# Data modifying operation - commit required
cursor.execute(sql)
transaction.commit_unless_managed()
return 1
Wondering if there is a better solution to my problem. Also how would I sanitize the field values for raw insert?
So I created a custom manager. Here is the manager:
class BulkInsertManager(models.Manager):
def _bulk_insert_or_update(self, create_fields, update_fields, values):
from django.db import connection, transaction
cursor = connection.cursor()
db_table = self.model._meta.db_table
values_sql = []
values_data =[]
for value_lists in values:
values_sql.append( "(%s)" % (','.join([ "%s" for i in range(len(value_lists))]),) )
values_data.extend(value_lists)
base_sql = "INSERT INTO %s (%s) VALUES " % (db_table, ",".join(create_fields))
on_duplicates = []
for field in update_fields:
on_duplicates.append(field + "=VALUES(" + field +")")
sql = "%s %s ON DUPLICATE KEY UPDATE %s" % (base_sql, ", ".join(values_sql), ",".join(on_duplicates))
cursor.executemany(sql, [values_data])
transaction.commit_unless_managed()
And a sample model:
class User_Friend(models.Model):
objects = BulkInsertManager() # assign a custom manager to handle bulk insert
id = models.CharField(max_length=255)
user = models.ForeignKey(User, null=False, blank=False)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
city = models.CharField(max_length=50, null=True, blank=True)
province = models.CharField(max_length=50, null=True, blank=True)
country = models.CharField(max_length=30, null=True, blank=True)
And sample implementation:
def save_user_friends(user, friends):
user_friends = []
for friend in friends:
create_fields = ['id', 'user_id', 'first_name', 'last_name', 'city', 'province', 'country']
update_fields = ['first_name', 'last_name', 'city', 'province', 'country']
user_friends.append(
[
str(user.id),
str(friend['id']),
friend['first_name'],
friend['last_name'],
friend['city'],
friend['province'],
friend['country'],
]
)
User_Friend.objects._bulk_insert_or_update(create_fields, update_fields, user_friends)
Here is the gist.
You could sanitize with a ModelForm:
from django.forms.models import modelform_factory
form_class = modelform_factory(MyModel)
for obj in my_data:
form = form_class(obj)
if not form.is_valid():
raise Hell()
As to the raw SQL, I say go for it. It doesn't appear that Django's ORM supports ON DUPLICATE KEY UPDATE, so don't let it get in your way. The Django docs talk about doing it without any reservation.
It may be worth using Manager.raw, though.

Categories