Getting error when trying to insert JSON field in Postgres - json

I have the following schema in django.
class function(models.Model):
func_id = models.IntegerField(primary_key=True)
func_name = models.CharField(max_length=30)
func_args = JSONField()
func_version = models.CharField(max_length=20)
func_desc = models.CharField(max_length=500)
user = models.ForeignKey(user_data,on_delete=models.CASCADE)
container_path = models.CharField(max_length=200)
class Meta:
db_table = 'function'
When I am trying to run the following query in postgres shell
INSERT INTO
function(func_id,func_name,func_args,func_version,func_desc,user_id,container_path)
VALUES (101,'Sum',{"input1":"a","input2":"b"},'1.7','blahblah',105,'/path');
I am getting below error:
ERROR: syntax error at or near "{"
LINE 1: ...nc_desc,user_id,container_path) VALUES (101,'Sum',{"input1":...
Any clue where I am going wrong?

Try enclosing your JSON in single quotes '{...}'. Even though JSONField supposedly works with python dictionaries, when doing raw SQL, postgresql won't understand that syntax.

Related

What's the right definition of peewee model while mapping from json file?

Hi stack overflow community! This is my first question here, but I tried to find an answer beforehand. Right now I am working on loading data from json file like so (I actually have a json file named persons.json, not API) with the use of peewee to SQLite DB. As you can see, the json file has multiple nested dicts. My peewee model is as follows:
import json
import sqlite3
from peewee import *
db = SqliteDatabase('persons.sqlite3')
class Person(Model):
gender = CharField()
name = CharField()
location = CharField()
email = CharField()
login = CharField()
dob = CharField()
registered = CharField()
phone = CharField()
cell = CharField()
id_ = CharField()
picture = CharField()
nat = CharField()
count_dob = IntegerField()
And this is how I load all the data from json file to SQLite DB:
db.connect()
db.create_tables([Person])
with open('persons.json', encoding='utf8') as persons:
persons_data = json.load(persons)
for person in persons_data['results']:
p = Person(gender=person['gender'], name=person['name'], location=person['location'], email=person['email'],
login=person['login'], dob=person['dob'], registered=person['registered'], phone=person['phone'],
cell=person['cell'], id_=person['id'], picture=person['picture'], nat=person['nat'])
My question is, do you think the variables in my model are correctly defined (basically every single one of them as a CharField) ? The thing is, later whenever I query the DB and I need to access some of these nested dictionaries, they are actually a string, which I can convert with the use of ast.literal_eval back to dict, but I don't think it looks nice. I thought of a solution - for all the 'dictionary type' variables in my model ('location', 'dob' etc), instead of using CharField() I could probably use JSONField() - not sure how to do that though. Could you please advise on that one?
Relational databases do not support "nesting". It's foundational. Anything that is nested should probably be in a separate table or in its own column as a flat/scalar value.
https://en.wikipedia.org/wiki/Database_normalization

How to annotate JSON fields in Django?

I have a model like this:
class MyModel(models.Model):
details = models.JSONField()
# other fields
I want to annotate some fields from this model like this:
qs = MyModel.objects.filter(id__in=given_list).annotate(
first_name=F('details__first_name'),
last_name=F('details__last_name')
)
However the F() expression is not considering the json keys, its just returning the details field only.
I am using MySQL, so cannot use KeyTextTransform.
I tried using RawSQL like this:
qs = MyModel.objects.filter(id__in=given_list).annotate(
first_name=RawSQL("(details->%s)", ('first_name',)),
last_name=RawSQL("(details->%s)", ('last_name',))
)
But it was giving this error:
MySQLdb._exceptions.OperationalError: (3143, 'Invalid JSON path expression. The error is around character position 1.')
So what can I do to make everything work as expected?
You can use JSONExtract, it will be easier to write and understand:
from django_mysql.models.functions import JSONExtract
qs = MyModel.objects.filter(id__in=given_list).annotate(
first_name=JSONExtract('details', '$.first_name'),
last_name=JSONExtract('details', '$.last_name')
)
MySQL json extractions have a special syntax using jsonfield->"$.key". Try with this:
qs = MyModel.objects.filter(id__in=given_list).annotate(
first_name=RawSQL("(details->%s)", ('$.first_name',)),
last_name=RawSQL("(details->%s)", ('$.last_name',))
)
You can just add properties to your MyModel and have them return the corresponding information
class MyModel(models.Model):
details = models.JSONField()
#property
def first_name(self):
return self.details['first_name']
#property
def last_name(self):
return self.details['last_name']

Django equivalent for MySQL bit datatype

I am facing issues with "makeflag" field which is bit(1) type in my database(MySQL). I have tried using booleanField and bit1booleanfield with below syntax. But i am getting error with both. when i try POST request with json data on this model,
I get error as
"Data too long for column" on passing 1 or 0 as value.
And when i give true or false as value, then i get 400 Bad Request.
Can someone please help me understand how can i post data using django and json for bit field (of mysql).
makeflag=models.BooleanField(db_column='MakeFlag', default=1)
makeflag=Bit1BooleanField()
My model is the next:
class Product(models.Model):
productid = models.AutoField(db_column='ProductID', primary_key=True)
name = models.CharField(db_column='Name', max_length=50)
productnumber = models.CharField(db_column='ProductNumber', max_length=25)
makeflag = models.TextField(db_column='MakeFlag', max_length=1)
color = models.CharField(db_column='Color', max_length=15, blank=True)
safetystocklevel = models.SmallIntegerField(db_column='SafetyStockLevel')
reorderpoint = models.SmallIntegerField(db_column='ReorderPoint')
standardcost = models.FloatField(db_column='StandardCost')
You probably need to use django-mysql for mysql specific functionality. Have a look docs for bit here

linq to sql error when trying to insert

Im trying to do an simple insert but am stuck with an error...
Error 10 The type arguments for method 'System.Data.Linq.Table<RequestSystem.User>.InsertAllOnSubmit<TSubEntity>(System.Collections.Generic.IEnumerable<TSubEntity>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
My code is
`UserModel User = new UserModel();
User.MudID = a[1];
User.Name = Session["username"].ToString();
User.Email = Session["email"].ToString();`
DataClasses1DataContext dt = new DataClasses1DataContext();
dt.Users.InsertAllOnSubmit(User);
dt.SubmitChanges();
Use the following instead:
dt.Users.InsertOnSubmit(User);
That will insert a single instance of your object. Using InsertAllOnSubmit expects a collection of objects

proper Django ORM syntax to make this code work in MySQL

I have the following django code working on an sqlite database but for some unknown reason I get a syntax error if I change the backend to MySQL...does django's ORM treat filtering differently in MySQL?
def wsjson(request,imei):
wstations = WS.objects.annotate(latest_wslog_date=Max('wslog__date'),latest_wslog_time=Max('wslog__time'))
logs = WSLog.objects.filter(date__in=[b.latest_wslog_date for b in wstations],time__in=[b.latest_wslog_time for b in wstations],imei__exact=imei)
data = serializers.serialize('json',logs)
return HttpResponse(data,'application/javascript')
The code basically gets the latest logs from WSlog corresponding to each record in WS and serializes it to json.
Models are defined as:
class WS(models.Model):
name = models.CharField(max_length=20)
imei = models.CharField(max_length=15)
description = models.TextField()
def __unicode__(self):
return self.name
class WSLog(models.Model):
imei = models.CharField(max_length=15)
date = models.DateField()
time = models.TimeField()
data1 = models.DecimalField(max_digits=8,decimal_places=3)
data2 = models.DecimalField(max_digits=8,decimal_places=3)
WS = models.ForeignKey(WS)
def __unicode__(self):
return self.imei
Ok finally managed to fix it with code below
def wsjson(request,imei):
wstations = WS.objects.annotate(latest_wslog_date=Max('wslog__date'),latest_wslog_time=Max('wslog__time'))logs = WSLog.objects.filter(date__in=[a.latest_wslog_date for a in wstations],time__in=[b.latest_wslog_time for b in wstations],imei__exact=imei)
data = serializers.serialize('json',logs)
return HttpResponse(data,'application/javascript')
the weird part was the original code worked as expected in an ubuntu machine running MySql but failed in a windows machine (also running MySql)