Django vs MySQL uuid - python

Django noob here
I have created a model using
customer_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
After migrating the model to MySQL, I tried to add data into mysql using
insert into customer_customer (customer_id, ...) values (uuid(), ...)
The data gets inserted properly in MySQL with a unique code, however, when I try to display this via Django admin tool (this table feeds into a property for users), it throws a badly formatted uuid error.
File "/usr/lib/python2.7/uuid.py", line 134, in __init__
raise ValueError('badly formed hexadecimal UUID string')
ValueError: badly formed hexadecimal UUID string
Please discuss if there is another way of creating seed data directly in MySQL.

A field for storing universally unique identifiers. Uses Python’s UUID
class. When used on PostgreSQL, this stores in a uuid datatype,
otherwise in a char(32).
So with MySQL django handles the uuid, and manages the field as Char32. You can't use native MySQL uuid.
If you have to create uuid from the MySQL side, use a CharField in django model, and populate it:
class MyModel(models.Model):
fld = models.CharField(max_length=36)
Then when saving:
import uuid
MyModel.fld = str(uuid.uuid4())
As a default:
fld = models.CharField(max_length=36, default=uuid.uuid4)

Try this:
insert into customer_customer (customer_id, ...) values (Replace(uuid(),'-',''), ...)
then it will work.

Documentation states that if you use a MySQL database, Django will store a string (char32):
UUIDField.
A field for storing universally unique identifiers. Uses Python’s UUID class. When used on PostgreSQL, this stores in a uuid datatype, otherwise in a char(32).
Python's uuid module gives you the following options to generate UUIDs:
>>> import uuid
>>> uuid.uuid4()
UUID('bd65600d-8669-4903-8a14-af88203add38')
>>> str(uuid.uuid4())
'f50ec0b7-f960-400d-91f0-c42a6d44e3d0'
>>> uuid.uuid4().hex
'9fe2c4e93f654fdbb24c02b15259716c'
In your case (using uuid4 as default in the Django module), you will need to use the "UUID.uuid4().hex" option in order to save the UUID as a string, just like Django would save it in your MySql database.

Related

Why does a SQLite database created in Python have the VARCHAR data type?

When I create an SQLite database from a python data model, any column defined as a String in Python is displayed as VARCHAR in SQLite (viewing with DB Browser for SQLite). Here is an example of the data model in Python:
class Users(db.Model):
id = db.Column(db.Integer, primary_key=True)
role = db.Column(db.String(10))
name_first = db.Column(db.String(50), nullable=False)
name_last = db.Column(db.String(50), nullable=False)
This may not be relevant, but I should clarify that I'm doing this as part of a website hosted with Flask. The database is initially created by dropping to a python prompt and:
from app import db
db.create_all()
I have a basic understanding of MS SQL and SQLite datatypes (NULL,INTEGER,REAL,TEXT,BLOB), but I don't understand why I'm seeing the columns defined as Strings in Python classified as VARCHAR in DB Browser for SQLite. If I attempt to modify the table, I see all of the expected datatypes for SQLite and also VARCHAR as an option. If I create a new database/table, then VARCHAR doesn't exist as an option for datatypes. Why wouldn't these columns be displayed as TEXT datatypes?
Strings in Python classified as VARCHAR in DB Browser for SQLite.
In Flask you are actually using SQLAlchemy ORM which will convert your class models directly into SQLite statements to create the relational database tables corresponding to it.
String data type in Python class model will be as VARCHAR data type in SQLite using Object Relational Mapper.
In SQLite, Text is the parent of VARCHAR and in the default installation is no different, so VARCHAR is actually same as TEXT.
Also If you check 3.1. Determination Of Column Affinity in the documentation you notice in the second point that:
If the declared type of the column contains any of the strings "CHAR",
"CLOB", or "TEXT" then that column has TEXT affinity. Notice that the
type VARCHAR contains the string "CHAR" and is thus assigned TEXT
affinity.
For more info check : http://www.sqlite.org/datatype3.html

Can't find django auth user with PostgreSQL

from django.contrib.auth.models import User as DjangoUser
class Ward(models.Model):
user = models.ForeignKey(DjangoUser, related_name='wards')
group = models.ForeignKey(Group, related_name='wards')
This is my django model and I use this filter.
Group.objects.filter(wards__user=_user).all()
I used this code in sqlite3, it works well.
But, it doesn't work in PostgreSQL.
operator does not exist: character varying = integer
LINE 1: ...rchive_ward"."group_id" ) WHERE "archive_ward"."user_id" = 1
I think it is caused by user_id field in archive_ward tables.
I found this field's data type is character.varying(20).
What can I do for this code?
Try removing the user table in the database and adding it again.
create a new one from scratch. Syncing database again will work..
or else You can do like this Way raw_query
You cannot compare an integer with a varchar. PostgreSQL is strict and does not do any magic typecasting for you. I'm guessing SQLServer does typecasting automagically (which is a bad thing).
If you want to compare these two different beasts, you will have to cast one to the other using the casting syntax ::
The Postgres error means you're comparing an integer to a string:
operator does not exist: character varying = integer
You could change the database model so user_id is of an integer type. Or you could cast the integer to string in Python:
Group.objects.filter(wards__user=str(_user)).all()

Can't syncdb with UUID field

I'm trying to generate a new database with uuid using django and postgresql
I have a model with UUID field like this :
class BaseUser(AbstractBaseUser):
id = models.UUIDField(_('id'), primary_key=True, default=uuid.uuid4, editable=False)
When i try to syncdb i got the following error :
django.db.utils.ProgrammingError: column "id" cannot be cast automatically to type uuid
HINT: Specify a USING expression to perform the conversion.
I already try to modify the type by hand doing:
CREATE EXTENSION "uuid-ossp";
ALTER TABLE baseuser ALTER COLUMN id SET DATA TYPE UUID USING (uuid_generate_v4());
end up with this error:
ERROR: default for column "Id" cannot be cast automatically to type uuid
I also tried sqlite without success
I just want to generate a new db with uuid, I don't care about existing data.

Auto_increment custom Primary Key in Peewee model

I want a primary key id field to be Bigint
class Tweets(Model):
id = BigIntegerField(primary_key=True)
...
But it needs to be auto_incremented and I can't find a way in the Peewee docs.
Please suggest if it's possible.
Update: I'm using MySql db.
Peewee automatically generates an integer id column serving as primary key, having the auto_increment property. This is true for any table you create with Peewee.
It is very likely that IntegerField is enough for your needs; BigIntegerField is very rarely useful. Will you really need numbers bigger than 2147483647? Will you insert more than two billion rows?
See: http://dev.mysql.com/doc/refman/5.5/en/integer-types.html
Peewee, as of 3.1, includes a BigAutoField which is an auto-incrementing integer field using 64-bit integer storage. Should do the trick:
http://docs.peewee-orm.com/en/latest/peewee/api.html#BigAutoField
I think the most convenience answer is by using SQL constraints:
import peewee
class MyModel(peewee.Model):
id = peewee.BigIntegerField(primary_key=True, unique=True,
constraints=[peewee.SQL('AUTO_INCREMENT')])
Looks like this should help.
After creating table, do:
db.register_fields({'primary_key': 'BIGINT AUTOINCREMENT'})
After that when you say
class Tweets(Model):
id = PrimaryKey()
...
class Meta():
db = db
Then in mysql that field will appear as BigInt with auto increment

Postgre/SQLAlchemy UUID inserts but failed to compare

I am accessing Postgre database using SQLAlchemy models. In one of models I have Column with UUID type.
id = Column(UUID(as_uuid=True), default=uuid.uuid4(), nullable=False, unique=True)
and it works when I try to insert new row (generates new id).
Problem is when I try to fetch Person by id I try like
person = session.query(Person).filter(Person.id.like(some_id)).first()
some_id is string received from client
but then I get error LIKE (Programming Error) operator does not exist: uuid ~~ unknown.
How to fetch/compare UUID column in database through SQLAlchemy ?
don't use like, use =, not == (in ISO-standard SQL, = means equality).
Keep in mind that UUID's are stored in PostgreSQL as binary types, not as text strings, so LIKE makes no sense. You could probably do uuid::text LIKE ? but it would perform very poorly over large sets because you are effectively ensuring that indexes can't be used.
But = works, and is far preferable:
mydb=>select 'd796d940-687f-11e3-bbb6-88ae1de492b9'::uuid = 'd796d940-687f-11e3-bbb6-88ae1de492b9';
?column?
----------
t
(1 row)

Categories

Resources