Django:创建一个ManyToMany()关系来存储多值

时间:2016-05-23 08:44:00

标签: python django django-models django-forms django-views

我在Diagnosis中有models.py表。 diagnosis_option可以在diagnosis_option_value字段中存储多个值(可能多于一个)。

这是我的Diagnosis表格。

class Diagnosis(models.Model):

    age_of_diagnosis = models.IntegerField(null=True,blank=True)
    age_at_onset_of_symptoms = models.IntegerField(null=True,blank=True)
    diagnosis_option_value = (
        ('', 'Please select a diagnosis'),
        ('b-thalassaemia syndromes', 'b-thalassaemia syndromes'),
        ('a-thalassaemia syndromes', 'a-thalassaemia syndromes'),
        ('Sickle cell syndromes', 'Sickle cell syndromes'),
        ('Other haemoglobin variants','Other haemoglobin variants'),
        ('Rare cell membrane disorders','Rare cell membrane disorders'),
        ('Rare cell enzyme disorders','Rare cell enzyme disorders'),
        ('Congenital dyserythropoietic anaemias','Congenital dyserythropoietic anaemias')
    )
    diagnosis_option = models.CharField( max_length=30)
    record_of_genotype = models.CharField(max_length=45,null=True,blank=True)
    # icd_10_code = models.ForeignKey(icd_10)
    icd_10_code = models.CharField('ICD-10 code', max_length=20,null=True,blank=True)
    # icd_10_desc = models.CharField('ICD-10 description',max_length=80,null=True,blank=True)
    icd_10_desc = models.ForeignKey(icd_10)
    orpha_code = models.CharField('Oprha code', max_length=20,null=True,blank=True)
    comment = models.CharField(max_length=100,null=True,blank=True)
    #diagnosis_genotype = models.CharField('Diagnosis genotype', max_length=100, null=True, blank=True)

    diagnosis_circumstances = models.CharField(max_length=150)
    diagnosis_circumstances_date = models.DateField('Date of diagnosis',null=True,blank=True)
    date_of_input= models.DateField(null=True,blank=True)
    pub_date = models.DateTimeField(auto_now=True)
    author = models.ForeignKey(User)
    patient = models.ForeignKey(Demographic)
    history = HistoricalRecords()


    def __str__(self):
        return str(self.patient)

为了保存多个值,建议创建另一个表以保持ManytoMany关系。

我创建了DiagnosisOption,如下所示:

class DiagnosisOption(models.Model):
    diag_option_value = models.CharField(max_length=30)
    diag_option = models.ManyToManyField(Diagnosis)

    def __str__(self):
        return self.diag_option

diag_option如何从diagnosis_option获取值?

forms.py我的代码是下面的代码。对于diagnosis_option,我使用forms.CheckboxSelectMultiple()小部件。

class DiagnosisForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):

        super(DiagnosisForm, self).__init__(*args, **kwargs)

        self.fields['diagnosis_circumstances_date']= forms.DateField(label=('Date'),required=False,
        widget=DateTimePicker(options={"format": "YYYY-MM-DD",
                                       "pickTime": False,
                                       "startDate": "1900-01-01"}))

        self.helper=FormHelper(form=self)

        self.fields['icd_10_desc']= forms.ModelChoiceField(queryset=icd_10.objects.all(),
                                    widget=autocomplete_light.ChoiceWidget("icd_10Autocomplete"))
        self.fields['icd_10_desc'].label = "ICD-10 description"
        diagnosis_option_value = (
        ('b-thalassaemia syndromes', 'b-thalassaemia syndromes',),
        ('a-thalassaemia syndromes', 'a-thalassaemia syndromes'),
        ('Sickle cell syndromes', 'Sickle cell syndromes'),
        ('Other haemoglobin variants','Other haemoglobin variants'),
        ('Red cell membrane disorders','Red cell membrane disorders'),
        ('Red cell enzyme disorders','Red cell enzyme disorders'),
        ('Congenital dyserythropoietic anaemias','Congenital dyserythropoietic anaemias')
    )
        self.fields['diagnosis_option']=forms.MultipleChoiceField(choices=diagnosis_option_value, widget=forms.CheckboxSelectMultiple())


        diagnosis_circumstances_value = (
        ('Antenatal diagnosis','Antenatal diagnosis'),
        ('Neonatal diagnosis','Neonatal diagnosis'),
        ('By the presence of affected related','By the presence of affected related'),
        ('Clinical diagnosis', 'Clinical diagnosis'),
        ('Other','Other')

        )
        self.fields['diagnosis_circumstances']=forms.MultipleChoiceField(choices=diagnosis_circumstances_value, widget=forms.CheckboxSelectMultiple())
        #self.fields['patient'].queryset = Demographic.objects.filter(patient_id=self.instance.patient)
        self.helper.field_class = 'col-md-8'
        self.helper.label_class = 'col-md-3'

        #self.helper.form_class = 'forms-horizontal'
        self.helper.layout = Layout(
            Fieldset (
                # 'patient',
                '<b>Diagnosis information</b>',
                Div(
                    #HTML(u'<div class="col-md-2"></div>'),
                    Div('age_of_diagnosis',css_class='col-md-6'),
                    Div('age_at_onset_of_symptoms',css_class="col-md-6"),
                    css_class='row',
                    ),



                'diagnosis_option',
                'record_of_genotype',
                'icd_10_desc',
                'icd_10_code',
                'orpha_code',
                'comment',
                ),

            Fieldset(
                '<b>Diagnosis circumstances</b>',
                'diagnosis_circumstances',
                'diagnosis_circumstances_date',
                #'diagnosis_circumstances_caring_year',
                ),



            FormActions(
                Submit('submit', "Save changes"),
                Submit('cancel',"Cancel")
            ),
        )
        self.helper.form_tag = False
        self.helper.form_show_labels = True

    class Meta:
        model = Diagnosis
        exclude = ['patient', 'author']

        list_display = ('patient', 'pub_date', 'author')
        # autocomplete_js_attribute={'name': 'icd_10_code'}

这是关于AKS提出的解决方案的解决方案:

models.py

class DiagnosisOption(models.Model):
    diagnosis_option_value = (
        ('', 'Please select a diagnosis'),
        ('b-thalassaemia syndromes', 'b-thalassaemia syndromes'),
        ('a-thalassaemia syndromes', 'a-thalassaemia syndromes'),
        ('Sickle cell syndromes', 'Sickle cell syndromes'),
        ('Other haemoglobin variants','Other haemoglobin variants'),
        ('Rare cell membrane disorders','Rare cell membrane disorders'),
        ('Rare cell enzyme disorders','Rare cell enzyme disorders'),
        ('Congenital dyserythropoietic anaemias','Congenital dyserythropoietic anaemias')
    )

    diag_option = models.CharField( max_length=50)

    def __str__(self):
        return self.diag_option

class Diagnosis(models.Model):

    ...
    diagnosis_option = models.ManyToManyField(DiagnosisOption)

forms.py: 在DiagnosisForm

diagnosis_option_value = (
        ('b-thalassaemia syndromes', 'b-thalassaemia syndromes',),
        ('a-thalassaemia syndromes', 'a-thalassaemia syndromes'),
        ('Sickle cell syndromes', 'Sickle cell syndromes'),
        ('Other haemoglobin variants','Other haemoglobin variants'),
        ('Red cell membrane disorders','Red cell membrane disorders'),
        ('Red cell enzyme disorders','Red cell enzyme disorders'),
        ('Congenital dyserythropoietic anaemias','Congenital dyserythropoietic anaemias')
    )
        self.fields['diagnosis_option']=forms.MultipleChoiceField(choices=DiagnosisOption.objects.all().values_list('id','diag_option'), widget=forms.CheckboxSelectMultiple())

views.py

request.method=POST

my_diagnosis = DiagnosisForm(request.POST, prefix='diag')

for formfield in my_diagnosis:
                dia_id = formfield.name
                if formfield.name == 'diagnosis_option':
                    dig_opt_list =  formfield.value()

my_diagnosis_object = my_diagnosis.save(commit=False)
            my_diagnosis_object.author = request.user
            my_diagnosis_object.patient = my_demographics_object
            my_diagnosis_object.save()

            for x in xrange(0, len(dig_opt_list)):
                my_diagnosis_object.diagnosis_option.add(dig_opt_list[x])

2 个答案:

答案 0 :(得分:0)

我会按照以下方式接近它:

将选项移至DiagnosisOption class:

class DiagnosisOption(models.Model):
    diagnosis_option_value = (
        ('', 'Please select a diagnosis'),
        ('b-thalassaemia syndromes', 'b-thalassaemia syndromes'),
        ('a-thalassaemia syndromes', 'a-thalassaemia syndromes'),
        ('Sickle cell syndromes', 'Sickle cell syndromes'),
        ('Other haemoglobin variants','Other haemoglobin variants'),
        ('Rare cell membrane disorders','Rare cell membrane disorders'),
        ('Rare cell enzyme disorders','Rare cell enzyme disorders'),
        ('Congenital dyserythropoietic anaemias','Congenital dyserythropoietic anaemias')
    )

    diag_option = models.CharField( max_length=30)

    def __str__(self):
        return self.diag_option

并在ManyToManyField类中将其添加为Diagnosis

class Diagnosis(models.Model):

    # other fields

    diagnosis_options = models.ManyToManyField(DiagnosisOption)

答案 1 :(得分:0)

您应该从诊断中删除diagn_option。 然后你将DianosisOption作为一个单独的模型。 创建ManyToMany时,您可以双向访问。在下面的例子中,我给Diagosis命名了diagnosis_options - &gt; DiagnosisOption关系,这样您就可以通过以下方式获得所有选项:

yourDiagnosisInstace.diagnosisOptions.all()

如果语法错误,我希望它有所帮助,我没有时间对其进行测试。

class DiagnosisOption(models.Model):
diagnosis_option_value = (
    ('', 'Please select a diagnosis'),
    ('b-thalassaemia syndromes', 'b-thalassaemia syndromes'),
    ('a-thalassaemia syndromes', 'a-thalassaemia syndromes'),
    ('Sickle cell syndromes', 'Sickle cell syndromes'),
    ('Other haemoglobin variants','Other haemoglobin variants'),
    ('Rare cell membrane disorders','Rare cell membrane disorders'),
    ('Rare cell enzyme disorders','Rare cell enzyme disorders'),
    ('Congenital dyserythropoietic anaemias','Congenital dyserythropoietic anaemias')
)
name = models.CharField(max_length=30, choices=diagnosis_option_value)
diag_option = models.ManyToManyField(Diagnosis,  related_name="diagnosis_options")

def __str__(self):
    return self.name