Отношения «многие ко многим» Прямое назначение передней стороне множества «многие ко многим» запрещено - PullRequest
1 голос
/ 19 февраля 2020

Я создал несколько моделей, одна из которых имеет отношение многие ко многим.

class PBSItems(models.Model):
    PBSCode = models.CharField(max_length=6, primary_key=True)
    RestrictFlag = models.CharField(max_length=1)
    eAuthQuant = models.TextField()

    def __str__(self):
        return self.PBSCode

class Restrictions(models.Model):
    IndicatId = models.IntegerField(primary_key=True)
    RestrictFullText = models.CharField(max_length=17040)

    def __str__(self):
        return self.IndicatId

class Drug(models.Model):
    PBSCode = models.ForeignKey(PBSItems, null=True, on_delete = models.CASCADE)

    def __str__(self):
        return self.PBSCode

class Links(models.Model):
    PBSCode = models.ManyToManyField(Drug)
    IndicatId = models.ForeignKey(Restrictions, on_delete = models.CASCADE)

    def __str__(self):
        return self.IndicatId

Однако, как только я создаю экземпляры для PBSItems, Restrictions and Drug, и я пытаюсь создать экземпляр для Links, Я получаю следующее сообщение:

TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use PBSCode.set() instead.

Как использовать PBSCode.set () в модели или как обойти эту проблему?

Большое спасибо

РЕДАКТИРОВАНИЕ:

Я использую команды управления для создания экземпляров

Load_Links

from csv import DictReader
import csv, os
from datetime import datetime
from django.core.management.base import BaseCommand
from myapp.models import Links, PBSItems
from pytz import UTC

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        now = datetime.now()
        yearid=str(now.year)
        monthid= now.month
        if monthid<10:
            monthid="0"+str(monthid)
        else:
            monthid=str(monthid)
        fN_Link = os.path.join("data - "+yearid+monthid+"01"+"\\LinkExtract_"+yearid+monthid+"01.txt")
        print(fN_Link)
        with open(fN_Link) as file:
            Link_reader = csv.reader(file, delimiter='\t')
            for row  in Link_reader:
                links = Links()
                if row != []:
                    links.PBSCode, _ = PBSItems.objects.get_or_create(PBSCode = row[0])
                    links.IndicatId = row[1].strip()
                    links.save()
        self.stdout.write(self.style.SUCCESS('Data imported successfully')) 

Load_Restrictions

from csv import DictReader
import csv, os
from datetime import datetime
from django.core.management.base import BaseCommand
from myapp.models import Restrictions
from pytz import UTC

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        now = datetime.now()
        yearid=str(now.year)
        monthid= now.month
        if monthid<10:
            monthid="0"+str(monthid)
        else:
            monthid=str(monthid)
        fN_Restrict = os.path.join("data - "+yearid+monthid+"01"+"\\RestrictionExtract_"+yearid+monthid+"01.txt")
        print(fN_Restrict)
        with open(fN_Restrict) as file:
            Restrict_reader = csv.reader(file, delimiter='\t')
            for row  in Restrict_reader:
                restrict = Restrictions()
                if row != []:
                    restrict.IndicatId1 = row[0]
                    restrict.RestrictFullText = row[1]
                    restrict.save()
        self.stdout.write(self.style.SUCCESS('Data imported successfully')) 

Load_PBS_Items

from csv import DictReader
import csv, os
from datetime import datetime
from django.core.management.base import BaseCommand
from myapp.models import PBSItems, PrescriberType, Note, Caution
from pytz import UTC
import pandas as pd

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        now = datetime.now()
        yearid=str(now.year)
        monthid= now.month
        if monthid<10:
            monthid="0"+str(monthid)
        else:
            monthid=str(monthid)
        fN_PBSItems = os.path.join("data - "+yearid+monthid+"01"+"\\PBS_Item_Table_"+yearid+monthid+"01.txt")
        print(fN_PBSItems)
        df=pd.read_csv(fN_PBSItems,sep='\t', header=None)
        df.columns = ['PBSCode'] 
        df = df[df['EndDate'] =='        ']
        for index, row in df.iterrows():
            pbsitems = PBSItems()
            pbsitems.PBSCode = row[0]
            pbsitems.RestrictFlag = row[1]
            pbsitems.eAuthQuant = row[2]
            pbsitems.save()
        self.stdout.write(self.style.SUCCESS('Data imported successfully'))

Load_Drug

from csv import DictReader
import csv, os
from datetime import datetime

from django.core.management.base import BaseCommand

from myapp.models import Drug, PBSItems, Manfr, ATC
from pytz import UTC

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        now = datetime.now()
        yearid=str(now.year)
        monthid= now.month
        if monthid<10:
            monthid="0"+str(monthid)
        else:
            monthid=str(monthid)
        fN_Drug = os.path.join("data - "+yearid+monthid+"01"+"\\drug_"+yearid+monthid+"01.txt")
        print(fN_Drug)
        with open(fN_Drug) as file:
            Drug_reader = csv.reader(file, delimiter='!')
            for row  in Drug_reader:
                drug = Drug()
                if row != []:
                    drug.ProgramCode = row[0]
                    drug.PBSCode, _  = PBSItems.objects.get_or_create(PBSCode = row[1])
                    drug.save()
        self.stdout.write(self.style.SUCCESS('Data imported successfully')) 

EDIT (2): рекомендуемые изменения в LoadLinks

from csv import DictReader
import csv, os
from datetime import datetime
from django.core.management.base import BaseCommand
from myapp.models import Links, PBSItems, Restrictions
from pytz import UTC

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        now = datetime.now()
        yearid=str(now.year)
        monthid= now.month
        if monthid<10:
            monthid="0"+str(monthid)
        else:
            monthid=str(monthid)
        fN_Link = os.path.join("data - "+yearid+monthid+"01"+"\\LinkExtract_"+yearid+monthid+"01.txt")
        print(fN_Link)
        with open(fN_Link) as file:
            Link_reader = csv.reader(file, delimiter='\t')
            for row  in Link_reader:
                links = Links()
                if row != []:
                    pbs_items, _ = PBSItems.objects.get_or_create(PBSCode = row[0])
                    links.PBSCode.append(pbs_items)
                    links.IndicatId = row[1].strip()
                    links.save()

Изменения в модели Links

class Links(models.Model):
    PBSCode = models.ForeignKey(Drug, on_delete = models.PROTECT, null = True)
    #PBSCode = models.ManyToManyField(Drug)
    IndicatId = models.ForeignKey(Restrictions, on_delete = models.CASCADE)

    def __str__(self):
        return self.IndicatId

1 Ответ

0 голосов
/ 21 февраля 2020

У вас есть:

links.PBSCode, _ = PBSItems.objects.get_or_create(PBSCode = row[0])

Вам необходимо добавить или установить для вновь созданного экземпляра PBSItems значение links.PBSCode.

pbs_items, _ = PBSItems.objects.get_or_create(PBSCode = row[0])
links.PBSCode.append(pbs_items)
# Or if you want to reset the whole relationship to just this one instance
links.PBSCode.set([pbs_items])

Кроме того, в отрасли рекомендуется именовать поля в случай змеи, такой как links.pbs_code. А также назвать модели в качестве единственного экземпляра, где это имеет смысл. Так что PBSItems будет PBSItem и Links до Link. И, наконец, при именовании отношения ForeignKey лучше не указывать суффикс Id, если в этом нет необходимости, поскольку при доступе к этому свойству он предоставляет вам экземпляр этого отношения. Так что Link.IndicatId станет Link.indicat.

...