So, here's my model:
class MyModel(models.Model):
timestamp = models.DateTimeField(primary_key=True)
fielda = models.TextField()
When I call syncdb, django doesn't add a constraint to postgresql for timestamp to be unique, even though it gives it the primary key constraint.
If I change timestamp to just unique=True, django creates the unique constraint. However, if I combine unique=True and primary_key=True, django doesn't create the unique constraint.
My info:
django-south v1.8
django 1.4
python 2.7
postgresql 9.1
Edit:
If I save a model with the same exact timestamp twice in two different runs (not the same process), it doesn't raise and IntegrityError like it should. But when it creates the unique constraint and no primary key, it does with the same code.
Edit 2:
This is the code that runs when I have CONSTRAINT "MyModel_pkey" PRIMARY KEY ("timestamp") in postgresql from just having timestamp = models.DateTimeField(primary_key=True)
timestamp = datetime.datetime(2013, 7, 31, 0, 0, 0).replace(tzinfo=utc)
print timestamp # prints 2013-07-31 00:00:00+00:00
row = MyModel(timestamp=timestamp, fielda='test')
row.save()
When run twice in a row, it doesn't raise an IntegrityError. However, with the unique=True and not primary_key=True, it does raise an IntegrityError.
Maybe the example from the docs can bring some light into your question
Technically, a primary key constraint is simply a combination of a
unique constraint and a not-null constraint. So, the following two
table definitions accept the same data:
CREATE TABLE products (
product_no integer UNIQUE NOT NULL,
name text,
price numeric );
CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric );
[...] A primary key indicates that a column or group of columns can be
used as a unique identifier for rows in the table [...] Adding a
primary key will automatically create a unique btree index on the
column or group of columns used in the primary key. [...]
Ricola3D linked me to the same question (that's answered) that explains my problem.
Answered Question
Related
I am trying to build a composite primary key for my tabels. They should also have a self incremented id. My problem is that when I use a composite primary key the ID becomes NULL (as seen in the pictures)
here it works as it should but no composite key
here the id is NULL no matter what.
I tried different synatxes and also key words like NOT NULL and AUTOINCREMENT but nothing seems to work.
Here is the code without composite key
mystr = "CREATE TABLE IF NOT EXISTS KM%s(id INTEGER PRIMARY KEY, date TEXT, client INTEGER)"%(month.replace('-',"))
print(mystr)
c.execute(mystr) #create a table
conn.commit()'''
Here is the code with COMPOSITE KEY
mystr = "CREATE TABLE IF NOT EXISTS KM%s(id INTEGER, date TEXT, client INTEGER, primary key (id, client)"%(month.replace('-',"))
print(mystr)
c.execute(mystr) #create a table
conn.commit()
I was sure that I'd used autoincremented integer columns in the past which were not primary keys, but it certainly doesn't work today with SQLite.
I must echo what #forpas has already said in the comment that you just can't do that.
The solution would be to add the UNIQUE constraint to id and generate your ID programmatically as you go. You do not need to track your current maximum ID because you can simply ask SQLite what the max is:
SELECT MAX(id) FROM KM<month>;
Increment that value by 1 and include it in your INSERT INTO statement.
I'd like to offer a couple of tips:
Using two integers as your composite key is a bad idea. Take composite key 1315 for example. Is that client 315 with an ID of 1, client 15 with an ID of 13, or client 5 with an ID of 131? It's true that primary keys are just for searching and do not have to be unique in many cases, but using integers generally does not work well.
The second tip is not to create a new database table for each month. A very good rule is that identically-structured tables should be combined into a single table. In this case you would add a column called month (actually, it would be 'date' then you would search by month) and keep everything in one table, not one table per month.
I want to save data from the Django model to PostgreSQL database with:
mymodel.objects.create(title='test')
this model only has title and id but it raises this error:
django.db.utils.IntegrityError: null value in column "id" violates not-null constraint
how can I fix it? why id is not set automatically as always?
If you somehow had your ID field altered on the database level and you want to make it an autoincrementing sequence again do this
In the below example check what mymodel's table will be in Postgres in the example below its called mytable
// Pick a starting value for the serial, greater than any existing value in the table
SELECT MAX(id)+1 FROM mytable
// Create a sequence for the serial (tablename_columnname_seq is a good name)
CREATE SEQUENCE mytable_id_seq MINVALUE 3 (assuming you want to start at 3)
// Alter the default of the column to use the sequence
ALTER TABLE test ALTER id SET DEFAULT nextval('mytable_id_seq')
// Alter the sequence to be owned by the table/column;
ALTER SEQUENCE mytable_id_seq OWNED BY mytable.id
REF: Changing primary key int type to serial
You should allow Django to create the id as the primary key instead of explicitly putting it in your model. You could call it something else like mymodel_id if you need it as a separate field.
Example:
class Book(models.Model):
title = models.CharField(null=False, blank=False)
def __str__(self):
return str(self.id)
After that run:
python manage.py makemigrations
python manage.py migrate
If you need to integrate Django with an existing database you can try this: Integrating Django with an existing database
We have Django Model, use Binary Field for ID.
# Create your models here.
class Company(models.Model):
id = models.BinaryField(max_length=16, primary_key=True)
name = models.CharField(max_length=12)
class Meta:
db_table = "company"
We use MySQL Database and have error when migrate.
File "/home/cuongtran/Downloads/sample/venv/lib/python3.5/site-packages/MySQLdb/connections.py", line 270, in query
_mysql.connection.query(self, query)
django.db.utils.OperationalError: (1170, "BLOB/TEXT column 'id' used in key specification without a key length")
Do you have any solution? We need to use MySQL and want to use the Binary Field for ID.
Thank you!
I think you cannot achieve this. Based on Django documentation it looks like use of binary fields is discouraged
A field to store raw binary data. It only supports bytes assignment.
Be aware that this field has limited functionality. For example, it is
not possible to filter a queryset on a BinaryField value. It is also
not possible to include a BinaryField in a ModelForm.
Abusing BinaryField
Although you might think about storing files in the database, consider
that it is bad design in 99% of the cases. This field is not a
replacement for proper static files handling.
And based on a Django bug, it is most likely impossible to achieve a unique value restriction on a binary field. This bug is marked as wont-fix. I am saying most likely impossible as I did not find evidence to confirm that binary field is stored as a BLOB field but the error does allude to it.
Description
When I used a field like this:
text = models.TextField(maxlength=2048, unique=True)
it results in the following sql error when the admin app goes to make the table
_mysql_exceptions.OperationalError: (1170, "BLOB/TEXT column 'text' used in key specification without a key length")
After a bit of investigation, it turns out that mysql refuses to use unique with the column unless it is only for an indexed part of the text field:
CREATE TABLE `quotes` ( \`id\` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `text` longtext NOT NULL , \`submitTS\` datetime NOT NULL, `submitIP` char(15) NOT NULL, `approved` bool NOT NULL, unique (text(1000)));
Of course 1000 is just an arbitrary number I chose, it happens to be the maximum my database would allow. Not entirely sure how this can be fixed, but I figured it was worth mentioning.
MySQL restricts the primary key on BLOB/TEXT column to first N chars, when you generates migration file using Django's makemigrations command, BinaryField in Django is mapped to longblob which is BLOB column in MySQL without specifying the key length.
Which means your Django model definition :
class Company(models.Model):
id = models.BinaryField(max_length=16, primary_key=True)
name = models.CharField(max_length=12)
class Meta:
db_table = "company"
will be converted to SQL expression that causes this error (You can check out the detailed SQL expressions by sqlmigrate command) :
CREATE TABLE `company` (`id` longblob NOT NULL PRIMARY KEY,
`name` varchar(12) NOT NULL);
while the correct SQL expression for MySQL should be like this :
CREATE TABLE `company` (`id` longblob NOT NULL,
`name` varchar(12) NOT NULL);
ALTER TABLE `company` ADD PRIMARY KEY (id(16));
where PRIMARY KEY (id(16)) comes from your id length in the BLOB column, used to structure primary key index of the table.
So the easiest solution is as described in the accepted answer -- avoid BinaryField in Django as primary key, or you can manually add raw SQL scripts to your migration file if you really need BinaryField (BLOB column) to be primary key and you are sure the id field will NOT go beyond the specific size (in your case, 16 bytes).
i'm using djangorestframework. the models one meeting could have many participates.
So i tried to use ManytoManyField of django:
class Meeting(models.Model):
name=models.CharField(max_length=100)
participates=models.ManyToManyField(Person)
by python manager.py sqlall XXX the DB tables are:
CREATE TABLE "OA_meeting_participates" (
"id" integer NOT NULL PRIMARY KEY,
"meeting_id" integer NOT NULL,
"person_id" integer NOT NULL REFERENCES "OA_person" ("id"),
UNIQUE ("meeting_id", "person_id")
)
;
CREATE TABLE "OA_meeting" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(100) NOT NULL,
)
the problems comes: when i create a meeting by selecting some persons, server response 'participates' is an invalid keyword argument for this function.
since OA_meeting does not have participates field.
so how to solve it?
see the docs on manytomany fields. You need to create the meeting and person objects separately first, and then do meeting.partcipates.add(person)
(btw, i think the word you are looking for is participANts)
Im using a table constraint to create a composite primary key, I would like the id field to autoincrement, is this possible? or what are the alternatives?
CREATE TABLE IF NOT EXISTS atable(
id INTEGER NOT NULL, --I want to autoincrement this one
name TEXT NOT NULL,
anotherCol TEXT,
PRIMARY KEY(id, name));
No, there's only one primary key: that's the composite of id and name.
If you mean that you want id to be the primary key, and name to be an indexed alternate key, I'd say that you should give name a unique constraint and make id the primary key.
Here's the link to the SQLite FAQ page where your question of how to autoincrement an integer primary key is #1. http://www.sqlite.org/faq.html#q1
Here's your SQL reworked a little:
CREATE TABLE IF NOT EXISTS atable(
id INTEGER PRIMARY KEY, -- use NULL for this column on INSERT to autoinc
name TEXT NOT NULL,
anotherCol TEXT);
then create a unique index on NAME as suggested by duffymo and Kaleb.
It doesn't look to me that the OP want names to be unique. (But I could be wrong.) At any rate, you can
get an autoincrementing integer by using INTEGER PRIMARY KEY and inserting NULL into that column, and
declare a superkey by using a UNIQUE constraint on (id, name).
A superkey is just a candidate key (primary key in this case) plus one or more columns.
CREATE TABLE yourtable(
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
CONSTRAINT superkey UNIQUE (id, name)
);
If you turn on foreign key support using PRAGMA foreign_keys = on;, the superkey can be the target of foreign key constraints in other tables. But I'm not certain that's what you were looking for.