Django. user_id null & duplicate error - django

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;

Related

Specifying a default value for Django DateField and Postgresql

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))

Adding values in my database via a ManyToMany relationship represented in admin.py

I've got a tiny little problem that, unfortunately, is taking all my time.
It is really simple, I already have my database and I created then modified models.py, and admin.py. Some staff users, who will need to enter values in my database, need the simpliest form to do so.
Here is my database :
-- Table NGSdb.line
CREATE TABLE IF NOT EXISTS `NGSdb`.`line` (
`id` INT NOT NULL AUTO_INCREMENT ,
`value` INT NOT NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
CREATE UNIQUE INDEX `value_UNIQUE` ON `NGSdb`.`line` (`value` ASC) ;
-- Table NGSdb.run_has_sample_lines
CREATE TABLE IF NOT EXISTS `NGSdb`.`run_has_sample_lines` (
`line_id` INT NOT NULL ,
`runhassample_id` INT NOT NULL ,
PRIMARY KEY (`line_id`, `runhassample_id`) ,
CONSTRAINT `fk_sample_has_line_line1`
FOREIGN KEY (`line_id` )
REFERENCES `NGSdb`.`line` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_sample_has_line_run_has_sample1`
FOREIGN KEY (`runhassample_id` )
REFERENCES `NGSdb`.`run_has_sample` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
-- Table NGSdb.run_has_sample
CREATE TABLE IF NOT EXISTS `NGSdb`.`run_has_sample` (
`id` INT NOT NULL AUTO_INCREMENT ,
`run_id` INT NOT NULL ,
`sample_id` INT NOT NULL ,
`dna_quantification_ng_per_ul` FLOAT NULL ,
PRIMARY KEY (`id`, `run_id`, `sample_id`) ,
CONSTRAINT `fk_run_has_sample_run1`
FOREIGN KEY (`run_id` )
REFERENCES `NGSdb`.`run` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_run_has_sample_sample1`
FOREIGN KEY (`sample_id` )
REFERENCES `NGSdb`.`sample` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
Here is my models.py :
class Run(models.Model):
id = models.AutoField(primary_key=True)
start_date = models.DateField(null=True, blank=True, verbose_name='start date')
end_date = models.DateField(null=True, blank=True, verbose_name='end date')
project = models.ForeignKey(Project)
sequencing_type = models.ForeignKey(SequencingType)
def __unicode__(self):
return u"run started %s from the project %s" % (self.start_date,self.project)
class Line(models.Model):
id = models.AutoField(primary_key=True)
value = models.IntegerField()
def __unicode__(self):
return u"%s" % str(self.value)
class RunHasSample(models.Model):
id = models.AutoField(primary_key=True)
run = models.ForeignKey(Run)
sample = models.ForeignKey(Sample)
dna_quantification_ng_per_ul = models.FloatField(null=True, blank=True)
lines = models.ManyToManyField(Line)
def __unicode__(self):
return u"Sample %s from run %s" % (self.sample, self.run)
And here is my admin.py :
class RunHasSamplesInLine(admin.TabularInline):
model = RunHasSample
fields = ['sample', 'dna_quantification_ng_per_ul', 'lines']
extra = 6
class RunAdmin(admin.ModelAdmin):
fields = ['project', 'start_date', 'end_date', 'sequencing_type']
inlines = [RunHasSamplesInLine]
list_display = ('project', 'start_date', 'end_date', 'sequencing_type')
As you can see, my samples are displayed in lines in the run form so that the staff can easily fullfill the database.
When I try to fill the database I have this error :
(1054, "Unknown column 'run_has_sample_lines.id' in 'field list'")
Of course, there are no field "lines" in my database ! It is a many to many field so I already created my intermediate table !
Okay okay ! So I tried to create the model for the intermediate table (run_has_sample_lines) and add a "through" to the ManyToManyField in the RunHasSample model. But, as I add manually the "through", I cannot use the ManyToMany field. The only way to add lines to the admin view is to stack them in lines... As you can see the samples are already in lines, it is impossible to put a new "inlines" in the already in lines samples...
Finally, I just tried to see what django had created with the manage.py sqlall.
I see that :
CREATE TABLE `run_has_sample_lines` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`runhassample_id` integer NOT NULL,
`line_id` integer NOT NULL,
UNIQUE (`runhassample_id`, `line_id`)
)
;
ALTER TABLE `run_has_sample_lines` ADD CONSTRAINT `line_id_refs_id_4f0766aa` FOREIGN KEY (`line_id`) REFERENCES `line` (`id`);
It seems that there are no foreign key on the run_has_sample table whereas I created it in the database in the first place. I guess that the problem is coming from here but I cannot resolve it and I really hope that you can...
Thank you very much !
you may wish to try a 'through' attribute on the many-to-many relationship and declare your intermediate table in Django.
I found where the problem is...
It is not a problem in the ManyToManyField but in the intermediate table. Django refused that my intermediate table doesn't have an unique id !
So, in the sql which created django, it created automatically an unique id named "id", but in my database I didn't create one (because the couple of two foreign key is usually enough).
Next time, I'll be more carefull.

Django: ManyToManyField creates duplicate column name

I have two types of users in my application: auth.User, which comes from django.contrib.auth (the standard Django authentication module) and mysql.User, which is in my own module. In addition, mysql.User inherits from an abstract model. The whole thing looks similar to this (some fields were omitted for brevity):
class Resource(Model):
class Meta:
abstract = True
owners = ManyToManyField('auth.User', related_name='%(class)s_owners')
class User(Resource):
name = CharField(max_length=16)
host = CharField(max_length=64)
class Database(Resource):
name = CharField(max_length=64)
As you can see, I want to make it so that multiple auth.Users may "own" a given mysql.User and a given mysql.Database, hence the ManyToManyFields. However, when I go to run ./manage.py syncdb I get the error:
_mysql_exceptions.OperationalError: (1060, "Duplicate column name 'user_id'")
Indeed, ./manage.py sql mysql shows the source of the error (again, some columns and ALTER TABLE statements omitted for brevity):
CREATE TABLE `mysql_database` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(64) NOT NULL,
UNIQUE (`server_id`, `name`)
);
CREATE TABLE `mysql_user` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`name` varchar(16) NOT NULL,
`host` varchar(64) NOT NULL,
UNIQUE (`server_id`, `name`, `host`)
);
CREATE TABLE `mysql_database_owners` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`database_id` integer NOT NULL,
`user_id` integer NOT NULL,
UNIQUE (`database_id`, `user_id`)
);
CREATE TABLE `mysql_user_owners` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`user_id` integer NOT NULL,
`user_id` integer NOT NULL, -- <<<<< here is the conflict >>>>>
UNIQUE (`user_id`, `user_id`)
);
Notice how the intermediate table for Database is created without a naming conflict but the table for User has a conflict. I don't see where a ManyToManyField provides a way for one to provide column names in the intermediate table, but unfortunately I think that's what I need.
Another method I tried was to explicitly create the intermediate table and use the through option of ManyToManyField, like so:
class Resource(models.Model):
class Meta:
abstract = True
owners = models.ManyToManyField('auth.User', related_name='%(class)s_owners', through='Owner')
class Owner(models.Model):
user = models.ForeignKey('auth.User', related_name='Resource_owners')
resource = models.ForeignKey(Resource)
But then I get this error:
AssertionError: ForeignKey cannot define a relation with abstract class Resource
Which is to be expected with Django.
So, short of renaming mysql.User to something like mysql.DBUser, is there any way to avoid the naming conflict created by Django?
How about creating the many to many table separately, avoiding the use of the ManyToMany field? You could use a manager or method to return a list of users for a given resource and visa versa.
class Resource(models.Model):
...
class Meta:
abstract = True
def owners(self):
return ResourceOwner.objects.filter(resource=self)
class ResourceOwners(models.Model):
resource = models.ForeignKey(Resource)
owner = models.ForeignKey(User)
class Meta:
abstract = True

Why django doesn't generate a constraint for many-to-many mapping as follows:

Question> Why django 1.3 ('ENGINE': 'django.db.backends.sqlite3' ) doesn't apply constraint on the tag_id attribute of table bookmarks_tag_bookmark?
Generated:
CREATE TABLE "bookmarks_tag_bookmarks" (
"id" integer NOT NULL PRIMARY KEY,
"tag_id" integer NOT NULL,
"bookmark_id" integer NOT NULL REFERENCES "bookmarks_bookmark" ("id"),
UNIQUE ("tag_id", "bookmark_id")
)
;
Expected:
CREATE TABLE "bookmarks_tag_bookmarks" (
"id" integer NOT NULL PRIMARY KEY,
"tag_id" integer NOT NULL REFERENCES "bookmarks_tag" ("id"),
"bookmark_id" integer NOT NULL REFERENCES "bookmarks_bookmark" ("id"),
UNIQUE ("tag_id", "bookmark_id")
)
;
# ----- Detail of The Coding ------------ #
user#ubuntu:~/Documents/Django/django_bookmarks$ cat bookmarks/models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Link(models.Model):
url = models.URLField(unique=True)
class Bookmark(models.Model):
title = models.CharField(max_length=200)
user = models.ForeignKey(User)
link = models.ForeignKey(Link)
class Tag(models.Model):
name = models.CharField(max_length=64, unique=True)
bookmarks = models.ManyToManyField(Bookmark)
user#ubuntu:~/Documents/Django/django_bookmarks$ python manage.py syncdb
user#ubuntu:~/Documents/Django/django_bookmarks$ python manage.py sql bookmarks
BEGIN;
CREATE TABLE "bookmarks_link" (
"id" integer NOT NULL PRIMARY KEY,
"url" varchar(200) NOT NULL UNIQUE
)
;
CREATE TABLE "bookmarks_bookmark" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(200) NOT NULL,
"user_id" integer NOT NULL REFERENCES "auth_user" ("id"),
"link_id" integer NOT NULL REFERENCES "bookmarks_link" ("id")
)
;
CREATE TABLE "bookmarks_tag_bookmarks" (
"id" integer NOT NULL PRIMARY KEY,
"tag_id" integer NOT NULL,
"bookmark_id" integer NOT NULL REFERENCES "bookmarks_bookmark" ("id"),
UNIQUE ("tag_id", "bookmark_id")
)
;
CREATE TABLE "bookmarks_tag" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(64) NOT NULL UNIQUE
)
;
COMMIT;
user#ubuntu:~/Documents/Django/django_bookmarks$
Because bookmarks_tag is not created at that point, so it can't define the constraint at table creation time. However if you do manage.py sqlall you will see that it later does an ALTER TABLE to add the constraint once all the tables are created.
(Although it's worth pointing out that Sqlite ignores contraints except in very recent versions, and even then only if specifically enabled.)

django recursive relationships

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;