I'm running Django 1.9.5 and PostgreSQL 9.5. The model for my app is:
from django.db import models
class users(models.Model):
userId = models.AutoField(primary_key=True)
userUserKey = models.CharField(max_length=255)
userUserName = models.CharField(max_length=255)
userLastName = models.CharField(max_length=255)
userFirstName = models.CharField(max_length=255)
userActive = models.IntegerField()
userStartEmployment = models.DateField(default='2015-01-01")
userEndEmployment = models.DateField(null=True)
The migration file shows:
...
('userStartEmployment', models.DateField(default='2015-01-01')),
...
sqlmigrate shows:
BEGIN;
--
-- Create model users
--
CREATE TABLE "login_users" (
"userId" serial NOT NULL PRIMARY KEY,
"userUserKey" varchar(255) NOT NULL,
"userUserName" varchar(255) NOT NULL,
"userLastName" varchar(255) NOT NULL,
"userFirstName" varchar(255) NOT NULL,
"userActive" integer NOT NULL,
"userStartEmployment" date NOT NULL,
"userEndEmployment" date NULL);
COMMIT;
When I run migrate, there are no errors and the table is created without any default value. This is trivial to do in SQL. From a PostgreSQL create table script:
"userStartEmployment" date DEFAULT '2015-01-01'::date,
I'm tempted to bail on using Django for this, but I'd really like to figure out how to leverage the framework as much as I can.
How can I set a default value that is a set value (i.e. not derived from something like default=datetime.now)?
Django never sets defaults in the database. It will happily use whatever value you give it as the default, though, so it is perfectly possible to pass a static date:
userStartEmployment = models.DateField(default=datetime.date(2015,1,1))
Related
I have two models:
class StateTax(models.Model):
name = models.CharField(max_length=256)
abbr = models.CharField(max_length=64, primary_key=True)
rate = models.IntegerField(default=0)
class Account(models.Model):
name = models.CharField(max_length=32)
tax_regions = models.ManyToManyField(SalesTaxRegion, blank=True, null=True, related_name="accounts")
However the SQL Django creates during syncdb seems to ignore the primary_key option. For example:
CREATE TABLE `airship_salestaxregion` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(256) NOT NULL,
`abbr` varchar(64) NOT NULL,
`rate` integer NOT NULL
)
;
CREATE TABLE `airship_account_tax_regions` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`account_id` integer NOT NULL,
`salestaxregion_id` integer NOT NULL,
UNIQUE (`account_id`, `salestaxregion_id`)
)
;
(note there is still an ID column in the first table and the relationship table references it)
As Like It says in the comment, you're getting your tables mixed up, you've given us python code for StateTax, not SalesTaxRegion.
I've tested your StateTax code with Django 1.4 and Postgres 9.2 and I get the following -
-- DROP TABLE testing_statetax;
CREATE TABLE testing_statetax
(
name character varying(256) NOT NULL,
abbr character varying(64) NOT NULL,
rate integer NOT NULL,
CONSTRAINT testing_statetax_pkey PRIMARY KEY (abbr)
)
There's no additional id field added.
I have a model that is backed by a database view.
class OrgCode(models.Model):
org_code = models.CharField(db_column=u'code',max_length=15)
org_description = models.CharField(max_length=250)
org_level_num = models.IntegerField()
class Meta:
db_table = u'view_FSS_ORG_PROFILE'
I need to reference this in another model
class AssessmentLocation(models.Model):
name = models.CharField(max_length=150)
org = models.ForeignKey(OrgCode)
I can't run syncdb because foreign key constraints cannot be created referencing a view.
u"Foreign key 'FK__main_asse__org__1D114BD1'
references object 'view_FSS_ORG_PROFILE'
which is not a user table.", None, 0, -214
7217900), None)
Command:
CREATE TABLE [main_assessmentlocation] (
[id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY,
[name] nvarchar(150) NOT NULL,
[org] int NOT NULL REFERENCES [view_FSS_ORG_PROFILE] ([id]),
)
The workaround is to take out the Meta:db_table pointing to the view and let sync db create the the OrgCode table, then put the Meta:db_table back in after syncdb.
Is there a way to prevent the creation of foreign key constraints for certain models or fields?
Update: I added a static method to the related model indicating it's a view
class OrgCode(models.Model):
org_code = models.CharField(max_length=15)
org_description = models.CharField(max_length=250)
#staticmethod
def is_backend_view():
return True
Then overrode DatabaseCreation.sql_for_inline_foreign_key_references in django_mssql creation.py:
def sql_for_inline_foreign_key_references(self, field, known_models, style):
try:
field.rel.to.is_backend_view()
return "", False
except:
return super(DatabaseCreation,self).sql_for_inline_foreign_key_references(field, known_models, style)
The generated sql from syncdb leaves out the constraint:
CREATE TABLE [main_assessmentlocation] (
[id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY,
[name] nvarchar(150) NOT NULL,
[org] int, -- NO FK CONSTRAINT ANYMORE --
);
It does involve hacking django_mssql so I'm going to keep on trying, maybe hooking into the django.db.backends.signals.connection_created signal will work...
django development version has a db_constraint field for ForeignKey model field - docs.
If you set managed=False (Django docs) in your model's Meta class, Django will not create the table when you run syncdb.
class AssessmentLocation(models.Model):
name = models.CharField(max_length=150)
org = models.ForeignKey(OrgCode)
class Meta:
managed = False
Django has a hook to provide initial sql data. We can (ab?)use this to get Django to create the table immediately after running syncdb.
Create a file myapp/sql/assessmentlocation.sql, containing the create table statement:
CREATE TABLE [main_assessmentlocation] (
[id] int IDENTITY (1, 1) NOT NULL PRIMARY KEY,
[name] nvarchar(150) NOT NULL,
[org] int, -- NO FK CONSTRAINT ANYMORE --
);
If you have other models with foreign keys to the AssessmentLocation model, you may have problems if Django tries to apply the foreign key constraint before executing the custom sql to create the table. Otherwise, I think this approach will work.
I have tested to "inspectdb" but I think my schema is to complex, for
example... for the table "tdir_files_context" (djangoinspectdb.JPG
"image in attachment") I got this model:
class TdirFilesContext(models.Model):
id_category = models.ForeignKey(TdirCategories, db_column='id_category')
id_file_context = models.CharField(max_length=20)
n_file_context = models.CharField(max_length=150)
coment = models.CharField(max_length=2000)
id_user_db_ins = models.CharField(max_length=45)
id_user_db_upd = models.CharField(max_length=45)
id_user_sys_ins = models.CharField(max_length=45)
id_user_sys_upd = models.CharField(max_length=45)
date_ins = models.DateTimeField()
date_last_upd = models.DateTimeField()
class Meta:
db_table = u'tdir_files_context'
This database table have Two primary keys and One foreign key. The
Django Model handle this kind of database tables?
First, no table can have two primary keys. That's just not possible. I'll just assume yours has a primary key composed of two columns, id_category and id_file_context.
Unfortunately, Django doesn't currently support models with composite primary keys, it can only handle tables with exactly one columns as their primary key.
<plug type="shameless">There is work underway on making this possible with Django, see https://code.djangoproject.com/ticket/373 and my work on this from last Google Summer of Code: https://github.com/koniiiik/django </plug>
Other than that though, ForeignKeys are perfectly fine with Django and I see no other problems with your table.
koniiiik just brought a very interesting answer about composite primary keys.
But when I see your definition of the model, I'm not sure you really want two primary keys, but just one foreign key and one primary key as :
class TdirCategories(models.Model):
id_category = models.AutoField(primary_key=True)
class TdirFilesContext(models.Model):
id_category = models.ForeignKey(TdirCategories, db_column='id_category')
id_file_context = models.AutoField(primary_key=True)
n_file_context = models.CharField(max_length=150)
coment = models.CharField(max_length=2000)
id_user_db_ins = models.CharField(max_length=45)
id_user_db_upd = models.CharField(max_length=45)
id_user_sys_ins = models.CharField(max_length=45)
id_user_sys_upd = models.CharField(max_length=45)
date_ins = models.DateTimeField()
date_last_upd = models.DateTimeField()
class Meta:
db_table = u'tdir_files_context'
the command python manage.py syncdb executes it well and after a python manage.py name_of_your_app_containing_the_model sql
You get a correct :
BEGIN;
CREATE TABLE "app_tdircategories" (
"id_category" integer NOT NULL PRIMARY KEY
)
;
CREATE TABLE "tdir_files_context" (
"id_category" integer NOT NULL REFERENCES "app_tdircategories" ("id_category"),
"id_file_context" integer NOT NULL PRIMARY KEY,
"n_file_context" varchar(150) NOT NULL,
"coment" varchar(2000) NOT NULL,
"id_user_db_ins" varchar(45) NOT NULL,
"id_user_db_upd" varchar(45) NOT NULL,
"id_user_sys_ins" varchar(45) NOT NULL,
"id_user_sys_upd" varchar(45) NOT NULL,
"date_ins" datetime NOT NULL,
"date_last_upd" datetime NOT NULL
)
;
COMMIT;
hope it helps :)
Django 1.3
Python 2.7
In fixing one error, I've developed another. I'm not even sure where to begin, I'm so frustrated.
I got my app to show up in the Django admin section, and when I click on "add", it brings up the form. When I fill it out & submit it, it results in this error:
Exception Value: (1048, "Column 'user_id' cannot be null")
Seems simple & clear, but if I add user_id to my admin.py, then it results in the error I just fixed. If I leave it out and use the code that fixes the old error, then I get this error. Here's the relevant code:
admin.py (I commented out the code I was using, as that caused the earlier error)
from timeslip.models import Timeslip
from django.contrib import admin
class TimeslipAdmin(admin.ModelAdmin):
pass
#fields = ['user_id','day','hours_as_sec','part_of_day','drove','gas_money','notes']
admin.site.register(Timeslip, TimeslipAdmin)
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Timeslip(models.Model):
user=models.ManyToManyField(User)
day = models.DateField()
hours_as_sec = models.PositiveIntegerField()
part_of_day = models.CharField(max_length=16,choices=PART_O_DAY)
drove = models.BooleanField(default=False)
gas_money = models.DecimalField(max_digits=5,decimal_places=2)
notes = models.TextField()
class UserProfile(models.Model):
user = models.ForeignKey(User)
url = models.URLField("Website", blank=True)
position = models.CharField(max_length=50, blank=True)
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
If I make Timeslip's user=, into a ForeignKey(User) instead of a ManyToManyField(User), the error becomes:
Exception Value: (1062, "Duplicate entry '2' for key 'user_id'")
...which I understand, but that's exactly what I'm trying to do here now -- make multiple timeslips for each user.
How do I do that? I keep getting ridiculous errors no matter what I try, and it's hard finding documentation on this even though it seems like it would be a common & basic thing.
Update:
New question. Is Django caching stuff? I removed something from the model and reset everything but it still shows the old form. If it's showing me something it cached - How do I flush that cache?
Anyway, here's the output when I run manage.py sqlall timeslip
BEGIN;
CREATE TABLE `timeslip_timeslip` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`user_id` integer NOT NULL,
`day` date NOT NULL,
`hours_as_sec` integer UNSIGNED NOT NULL,
`part_of_day` varchar(16) NOT NULL,
`drove` bool NOT NULL,
`gas_money` numeric(5, 2) NOT NULL,
`notes` longtext NOT NULL
)
;
ALTER TABLE `timeslip_timeslip` ADD CONSTRAINT `user_id_refs_id_bb29929c` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
CREATE TABLE `timeslip_userprofile_user` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`userprofile_id` integer NOT NULL,
`user_id` integer NOT NULL,
UNIQUE (`userprofile_id`, `user_id`)
)
;
ALTER TABLE `timeslip_userprofile_user` ADD CONSTRAINT `user_id_refs_id_c73880a3` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
CREATE TABLE `timeslip_userprofile` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`url` varchar(200) NOT NULL,
`company` varchar(50) NOT NULL
)
;
ALTER TABLE `timeslip_userprofile_user` ADD CONSTRAINT `userprofile_id_refs_id_d05b8c80` FOREIGN KEY (`userprofile_id`) REFERENCES `timeslip_userprofile` (`id`);
CREATE INDEX `timeslip_timeslip_fbfc09f1` ON `timeslip_timeslip` (`user_id`);
COMMIT;
My DjangoApp is using categories to generate a navigation and to put stuff in those categories.
There are two types of categories:
ParentCategories (top categories)
ChildCategories (sub categories that have a ParentCategory as a parent)
Because those to categories are so similar I don't want to use two different models.
This is my category model:
class Category(models.Model):
name = models.CharField(max_length=60)
slug = models.SlugField(max_length=80, blank=True)
is_parent = models.BooleanField()
parent = models.ForeignKey('self', null=True, blank=True)
In my djangoadmin the parent won't be represented.
If I use python manage.py sql I get:
CREATE TABLE "catalog_category" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(60) NOT NULL,
"slug" varchar(80) NOT NULL,
"is_parent" bool NOT NULL
)
;
So the parent relationship won't even be created.
Is there a handy way of fixing this?
I know I could just alter the table but I'm flushing/deleting the database quite a lot because the app changes rapidly and I don't want to alter the table everytime manually.
btw: my dev db is of course sqlite3.
On the server we'll use postgresql
Something else is going on - that definition of parent is fine. If I run manage.py sql on an app with that model copy-pasted in, I get:
BEGIN;
CREATE TABLE "bar_category" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(60) NOT NULL,
"slug" varchar(80) NOT NULL,
"is_parent" bool NOT NULL,
"parent_id" integer
)
;
COMMIT;