Django foreign key specify field values - group by groups - django

Is it possible to make a foreign key value from specific values in the field from the table?
For EXA: To create a new record, HR and POC have foreign key via the employee table, but HR can bring only "HR" (hr1, hr2) values from "name" field - group by group_name field. Also POC table: all values grouped by "POC" (poc1 and poc2)
TNX alot

I found a solution.
In Django model should add "limit_choices_to" into the field.
limit_choices_to={"group_code": "2"}
group_code: group by this field from Group model, "2" the value for lookup
employee_type = models.ForeignKey(
Group,
related_name="employee_type",
verbose_name="Employee Type",
on_delete=models.CASCADE,
limit_choices_to={"group_code": "2"},
blank=False,
default="None",
)

Related

Django filter table by foreign keys in related manager column

I have three models in my Django application:
class MainData(models.Model):
# bunch of fields
class Label(models.Model):
label = models.CharField(max_length=512, null=True, unique=True)
class MapData(models.Model):
labelMatch = models.ForeignKey(Label, on_delete=models.CASCADE)
mainMatch = models.ForeignKey(MainData, on_delete=models.CASCADE)
Through my application, I have the user enter a label in a search box. What I would like to do is return the MainData rows whos' MapData.label_match field is the entry in Label.
For example, say the user enters the string 'main32' into the search box. My current thought is to first find Label rows that match 'main32', then use the RelatedManager labelmatch_set to get all of the MapData rows that MapData.mainMatch points to. So if there are 10 MapData rows whose labelMatch points to a Label entry with label='main32', I then want to retrieve all 10 MainData rows that the foreign key mainMatch points to.
Hopefully I explained that ok. I have gotten to:
matching_label_rows = Label.objects.filter(input)
matching_main_data_rows = matching_label_rows.mainMatch_set.????
How can I retrieve the pointed to MainData rows from matching_label_rows.mainMatch_set? And can this operation be done as a one-liner?
Instead of finding the matching Labels first, you can filter MainData on the mapdata__labelMatch relationship:
matching_main_data_rows = MainData.objects.filter(mapdata__labelmatch__label__icontains=input)
Lookups that span relationships

Altering primary key of Django models with many-to-many relationships

I have two models, Image and Dataset that are connected through a many-to-many relationship:
class Image(models.Model):
id = models.CharField(max_length=255, primary_key=True)
datasets = models.ManyToManyField(Dataset, blank=True)
class Dataset(models.Model):
...
I wanted to use a sequential integer as id instead of the VARCHAR. So I renamed the id field to id_old, which made Django create an integer auto-field as an id column with the following migrations like I wanted, to which I added to delete the id_old field.
operations = [
migrations.RenameField(
model_name='image',
old_name='id',
new_name='id_old',
),
migrations.AddField(
model_name='image',
name='id',
field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
But the problem is that now the through table in Postgres backend has the image_id column with type VARCHAR, hence I get the following error if I want to add a dataset to an image:
operator does not exist: character varying = integer
LINE 1: ...tasets" WHERE ("app_image_datasets"."image_id" = 12764 AN...
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
Since the image_id field didn't get altered during these operations, I also lose the relationships between datasets and images.
So how can I alter a primary key field in a model with M2M relationships?

Clojure Luminus Migrations - Only one table per migration file

I'm creating a web app with Clojure and Luminus, but when I create a migration file with all the tables I need, it will only create the first. This is my user-table.up.sql file:
CREATE TABLE UserTable (
id INTEGER PRIMARY KEY AUTOINCREMENT,
first_name VARCHAR(50),
last_name VARCHAR(50),
gender VARCHAR(50),
email VARCHAR(50) UNIQUE,
password VARCHAR(400),
time_stamp TIMESTAMP,
is_active BOOLEAN
);
CREATE TABLE LoginTable (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
time_stamp TIMESTAMP
);
When I run lein run migrate, only the table UserTable is created. Is this supposed to work like this? Do I need to create a migration file for each table?
As you are using Luminus, you are probably using Migratus. If you want to execute multiple statements in one sql file, read this:
https://github.com/yogthos/migratus#multiple-statements
Just to let Michiel answer here according your case, to run multiple statements in your migration, separate them with --;; in your case:
CREATE TABLE UserTable (
id INTEGER PRIMARY KEY AUTOINCREMENT,
first_name VARCHAR(50),
last_name VARCHAR(50),
gender VARCHAR(50),
email VARCHAR(50) UNIQUE,
password VARCHAR(400),
time_stamp TIMESTAMP,
is_active BOOLEAN
);
--;;
CREATE TABLE LoginTable (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
time_stamp TIMESTAMP
);

Porting (postgresql) SQL into django model classes

I am porting a database schema (by hand), from (postgresql) SQL to django (1.10) model.
Here is my SQL:
CREATE TABLE ref_continent (
id SERIAL PRIMARY KEY,
name VARCHAR(64)
);
CREATE UNIQUE INDEX idxu_continent_nm ON ref_continent (name);
CREATE TABLE ref_geographic_region (
id SERIAL PRIMARY KEY,
continent_id INTEGER REFERENCES ref_continent(id) ON DELETE RESTRICT ON UPDATE CASCADE,
name VARCHAR(256)
);
CREATE UNIQUE INDEX idxu_geogreg_nm ON ref_geographic_region (name);
I am particularly interested in how to create the UNIQUE INDEX and how to link the FK to the PKey, since (AFAIK), django creates the primary key id behind the scenes?
According to docs
Note that when unique is True, you don’t need to specify db_index,
because unique implies the creation of an index.
Well, when you link a model as a foreign key, it links to default FK(that's id by default).
models.ForeignKey('app_name.ref_continent', )
there is another class class META that is used to fix these things. You don't have to almost ever specify to link FK to PK of other table, this is all done by Django. Have a at source code
models.py
class ref_continent(models.Model):
# Fields
name = models.CharField(max_length=64,unique=True)#making unique=True will generate query that will have UNIQUE INDEX both in PLSQL
def __unicode__(self):
return u'%s' % self.pk
class ref_geographic_region(models.Model):
# Fields
name = models.CharField(max_length=64,unique=True)
# Relationship Fields
continent_id = models.ForeignKey('app_name.ref_continent', )
def __unicode__(self):
return u'%s' % self.pk

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.