From d7519b4417d6f36c913fb4454ce0c40d26774b17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Herv=C3=A9=20=20MENAGER?= <herve.menager@pasteur.fr>
Date: Mon, 22 May 2017 17:02:35 +0200
Subject: [PATCH] remodel MDDR activity classes through a ManyToMany field

fixes #39
---
 ippisite/db.sqlite3                           | Bin 1536000 -> 1548288 bytes
 .../migrations/0018_auto_20170522_1501.py     |  41 ++++++++++++++++++
 ippisite/ippidb/models.py                     |  20 ++++-----
 3 files changed, 51 insertions(+), 10 deletions(-)
 create mode 100644 ippisite/ippidb/migrations/0018_auto_20170522_1501.py

diff --git a/ippisite/db.sqlite3 b/ippisite/db.sqlite3
index 8606d46f594d3b1d168826016966cfb95c9e8726..7ec7dd61212668b2fff2d44382e67427c4c30d13 100644
GIT binary patch
delta 2248
zcmah~ZA?>F7{2HBwx@;LURu5c`6!GiOoV%HzmX0rP^{Z6bQZNNT5f5Pwv^8z&}0e}
zgCp6TYs}5umM!S!k1dheOw?o<+y1DF$+Bd@KQ1yee@?Px*+1NA>t_qI&6Atc^FHr+
zp7*?O@6^4+Q_Dx*->N*0VIYD%{os>lYBk{a*WDK=QMuF`gE?kg>WwRx%cQS0mW#2X
zT^9e)kl*W}X~yX0$HIedmSzmJj%D49j%E^zowRNz%c>b&1I;!tnmV1%Xry)Vg)JT^
zDIw>J71~&qx~hP>Pd<?EP~254$p0Yc72WdB726cs&{0-WTo@K<fB;m|-1tIm6aZDs
zS6c<jW3SiU0M}!A^&_AuHdp_)sFL)=AYFlzo_IBFBuh((qI!@L81i~Y_@1!;m_Iz(
z)6b8NHpNdgo)o1hyPFdf<#GX8y0wYGit0Dv#813|D1PE{40hZW6MqrE5JJTwaVEaj
zu~&4soB(FL$?NO)g?;Xf^RVlw{hmI4;OIvC*GdRrz?*olcLVa(IMw-2g9;MoFvSn@
zS<;#<mE98GA<iMyv&7+<T~N%;iY=bNU|4798`cCzHKy_Lkx)-)C`9XhM+bBUx^Iy0
zYO@Bpz@9*t(?xU6R+bAK2y!gP*bh3i?JZsX_J~F6idZJNfHmNXI9Pkg7HN;Iev%uz
z^6^3GP*<}}ZwokLXFlEPw6QMMrE7O`5mzKQ(G{@!xt0U{_Q1X%7uwf{)*;Smqg@eu
z(B5K+xY#%SoYSJQ4bbLPQ|M7&sA*$^PTRoh>NI+jPG^eWIa`~R1r_TUwM2cOSdWvR
ztto1%L>zdTF_;L7-8-v}w_W;HP59+jLLjHI_r&)7JTH+u<(%A#D%DR4i$_F+vI)B`
z5dpjjyOw%fjlXqwKzT?{({z=o`B3M<pt03xZLw6DJUjFr2i-Lp)(%b>jGaB9L4z+;
zKj0W{Zrf}1cCm+A!Xamn@wJRUww3JlXSTE&Eu)E6JQOM(g8M2+Rb$le)Q{8!>Lk@m
zwNcebl!_AC9szklMm1oW$O2-E9~Lk99)XW&AfE#?jvzuH5X1<QB|yVR6v(;=cEjD<
z#eZWY){7|~D2nB#?1rrUvP&|II4}B6l#2(^M(R5pTkWV>a!kPmF@a$sIa>aN10ufK
zfdc@93SMeDzt#b+yaNe?s7%%_z-4HV$ZpHtleHtk*|NOG=>{<d%(mydU0^Q5(j!l1
zOr0FE#%WV3ZnLg$<_FZNJ#}JY)GyNY(?&!$G(Q~*fw>Bc6)y%YNp8XQUyHM`o0znl
zx<ZXf<nSBGY3L$Oi}Jyr*iB^bOLC?n8j%)Gm-6@wC#;`@TZGUG4(pzzawp~bMl(mx
z?f1HAmeKMi4<mfPf)}gOIUpi{HgUed%|SAml}(TM|E!hjcDq2Ig850ZKAl{tuCC1Z
zH$kc@Yi3@FP9jg`JeYAj^OTdGK<Hk<^Rg2*c&|~%^V*~hWqR0Hnv0F|P|xLgQFvZ@
z!h~>vU%_*8l46fVCy?0vJcu^GOspCmvXN!CrnlFm^>`WK-4(n{<xW4bO<?9=b+U{b
ztABaosX17dOt86~?Z{58db2x;M8{zv&x6?};kUWRZI&q}(MTCLP$jJ1!MEq6+Y%h7
zpgvhhVPqQA2<A)D5@kktgyCuMYEk-IE^!Bm>emSJFQgU%euY`kIGFcLTccyJ&}_zM
zO2fRT-<NvfWfpz2-@!yeYmv};3Lec-ciL@^&eoca=rKuQj~N%%=0Q1~F2&7knrxE#
w7n98`UX&svo>>Ul2qc0WL4iOa<RB;!R0z2Uc?kJSix&$zZY*@G7lv~F10oFZV*mgE

delta 1008
zcmaKrZD><h7{~9)eLG3+y(ejE>(Z?zG0t|z_U5Hc+O4B1HnuJroq|@{G|fwiw(Cp!
zLO+bYWKt#!<}Pv=^Mj<-esprF!4G5g<wGY7gfXl_p<3qG3NqX$>l1bPAY<p=AN+aF
zbDs0R{JGQ1-P7w`-&a}383s)-rDYhr=<%cR8$Anzt;Tsxw6y5f<!-F!xA%&|M^e@<
zWi^w-U7>tTHl%0r9%W6*%YR81lpgu2)CIluk`}0|5UMLjSwEtv4BPa)Cx--XXCE8E
z^!7u8P5bARtR1dfK?SY6egu84&DDR+I;AO1RGs=KYDm(aM|bE`pPgslR$C9i+y+UX
z`T{Cxo@iq9cc^^I>Ez_!%@%=QWt2PeH&UA!8}IY0uyv2uS1)-?SRgwYQXoI*%9ZB|
zOx?}7*$C3sFFEw^^<NxZT0X;3Y1+JB>v(Vh&do{m=WdqMV{2!vr&L((!HG`q+1{h6
z%;|K-eduUMHgP;2Jv2Ge-`{Ys!yg_P8jb{xx3}#HWrGu)iPX8MZzz7GufDy-r+R~X
z)xchF$l>)i!y8cRe2rdjAdquzQs*Yxum~i~kf-D>Ss>?0nuNiCpU|2uBx|>Rv=&lZ
z=qDAK=8$RtSbzg~Kqw$p+#*O`M6F`$Zb*+XX-0Xb*ySd3v*}CYbt5DGAuRJRxOw(h
z)@C>d+r!$EXl>!xw3z43Gwr#cSQ(3;nJjhA<L$*njImHtC>`{vzEVgiOi`HMMjy;$
z>Ae=u0{);_a=9Eeu7PB7B$gN)7#bY=DjCZpUA40$*N7`;%n>wutaO7t_I_imDd_hm
zeW^74?xEq03*@G))%e5GmH&6<%40(XZCSv$Xe9KXMm!EzJTaOX&x}sS68-UP7Od6g
z8pO&-1mzBn#(VoyrLQdsG)AAS8l1(c^yM|&Nt+)Tc2Uc$SWYir#dcJC^IMS%vQ;L5
zipydUVp}m5g!|&FKkd9AGq{J`Bx8asE(!9#4}S}~*7!1XqV%i16I8y2_i^MU>Vtf4
x6h#+^wxY1T6U=WH_u1!`7BOH1On@1X02xpK0$2bmPzKn5a$s9wX|dw)%4^79Ma}>K

diff --git a/ippisite/ippidb/migrations/0018_auto_20170522_1501.py b/ippisite/ippidb/migrations/0018_auto_20170522_1501.py
new file mode 100644
index 00000000..2986ba98
--- /dev/null
+++ b/ippisite/ippidb/migrations/0018_auto_20170522_1501.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2017-05-22 15:01
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('ippidb', '0017_auto_20170519_1500'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='MDDRActivityClass',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('activity_class', models.CharField(max_length=100, unique=True, verbose_name='Activity Class')),
+            ],
+            options={
+                'verbose_name_plural': 'MDDR activity classes',
+            },
+        ),
+        migrations.AlterUniqueTogether(
+            name='mddrcompoundactivityclass',
+            unique_together=set([]),
+        ),
+        migrations.RemoveField(
+            model_name='mddrcompoundactivityclass',
+            name='mddr_compound',
+        ),
+        migrations.DeleteModel(
+            name='MDDRCompoundActivityClass',
+        ),
+        migrations.AddField(
+            model_name='mddrcompoundimport',
+            name='activity_classes',
+            field=models.ManyToManyField(to='ippidb.MDDRActivityClass'),
+        ),
+    ]
diff --git a/ippisite/ippidb/models.py b/ippisite/ippidb/models.py
index 00dd5ee9..48fb10e3 100644
--- a/ippisite/ippidb/models.py
+++ b/ippisite/ippidb/models.py
@@ -243,6 +243,15 @@ class Compound(models.Model):
     mddr_compound = models.ForeignKey('MDDRCompoundImport', blank=True, null=True)  
 
 
+class MDDRActivityClass(models.Model):
+    activity_class = models.CharField('Activity Class', max_length=100, unique=True)  
+
+    class Meta:
+        verbose_name_plural = "MDDR activity classes"
+
+    def __str__(self):
+        return self.activity_class
+
 class MDDRCompoundImport(models.Model):
     mddr_compound_id = models.IntegerField('MDDR compound ID')  
     mddr_name = models.CharField('MDDR name', max_length=40)  
@@ -250,6 +259,7 @@ class MDDRCompoundImport(models.Model):
     canonical_smile = models.CharField('Canonical Smile', max_length=500, unique=True, blank=True, null=True)  
     #TODO index this table on canonical_smile
     db_import_date = models.DecimalField('MDDR release year/month', max_digits=6, decimal_places=0)  
+    activity_classes = models.ManyToManyField(MDDRActivityClass)
 
     class Meta:
         # over multiple releases of the MDDR database, the same compound can evolve in its development phase
@@ -257,16 +267,6 @@ class MDDRCompoundImport(models.Model):
         unique_together = (('mddr_compound_id', 'mddr_name', 'dvpmt_phase'),)
         verbose_name_plural = "MDDR compound imports"
 
-
-class MDDRCompoundActivityClass(models.Model):
-    mddr_compound = models.ForeignKey(MDDRCompoundImport)  
-    activity_class = models.CharField('Activity Class', max_length=100)  
-
-    class Meta:
-        unique_together = (('mddr_compound', 'activity_class'),)
-        verbose_name_plural = "MDDR compound activity classes"
-
-
 class MDDRSimilarity(models.Model):
     canonical_smile_ippidb = models.CharField('Canonical Smile for IPPIDB compound', max_length=500, unique=True, blank=True, null=True)
     canonical_smile_mddr = models.CharField('Canonical Smile for MDDR Compound', max_length=500, unique=True, blank=True, null=True)
-- 
GitLab