Django - 许多关系都没有保存

时间:2017-07-12 12:50:42

标签: python django

我正在为教育学校创建一个应用程序。学校有一个RegularSchoolClass类(继承自一个基础的SchoolClass类),还有一个跟踪课程安排的LessonSchedule类。

特别是,SchoolClass(基类)与LessonSchedule有多对多的关系。特别是,SchoolClass对象应该有48个课程安排(例如第0周,第1周,第2周;一年48课)。同时,一个特定的课程表可以由多个SchoolClass对象共享,因此我选择了多对多关系。

我写了一些逻辑,每当用户在管理控制台中更改类的日期时,它应该自动更改链接到该类的所有LessonScheule。例如,如果一个班级最初是在星期二,并且它改为星期三,那么应该相应地切换所有课程表。

奇怪的是,这并不会显示在管理控制台中 - 即使在我保存之后,也默认为0课程计划。但是在控制台中,self.lesson_schedule.all()。count()显示48.想知道是否有人可以引导我找到正确的答案?

我检查了{Saving Many To Many data via a modelform in Django),我的情况似乎有所不同,因为我已经保存了父对象(我使用了后期保存)

models.py(适用于学校班级)

class SchoolClass(TimeStampedModel):
    lesson_schedule = models.ManyToManyField('LessonSchedule', null=True, blank=True)
    day = models.IntegerField(choices=DAYS, null=True)
    start_date = models.DateField(null=True)

    def __str__(self):
        return '{}'.format(self.lesson_schedule.all().count())

class RegularSchoolClass(DirtyFieldsMixin, SchoolClass):    
    def save(self, *args, **kwargs):
        self.clean()
        super().save(*args, **kwargs)    

    def save_without_signals(self):
        setattr(self, '_disable_signals', True)
        self.save()
        #this correctly prints 48 -> so lesson_schedule should be linked correctly
        print(self.lesson_schedule.all().count())
        setattr(self, '_disable_signals', False)

@receiver(post_save, sender=RegularSchoolClass)
def post_save_regular_school_class(sender, instance, created, **kwargs):
    #https://stackoverflow.com/questions/10840030/django-post-save-preventing-recursion-without-overriding-model-save
    #prevents infinite saving
    if getattr(instance, '_disable_signals', False):
        return

    #for new instances or when we have changed the day, we want to update start_date
    #and assign lesson schedules
    if created or (instance.is_dirty() and 'day' in instance.get_dirty_fields()):

        # existing lesson schedule needs to be unlinked
        for l in instance.lesson_schedule.all():
            instance.lesson_schedule.remove(l)

        #assigning new lesson schedule
        for l in LessonSchedule.objects.filter(start_date=instance.start_date):
            instance.lesson_schedule.add(l)

        instance.save_without_signals()

models.py(用于课程安排)

#used to track the day for a lesson
#for regular classes, start_date should be the date of the first lesson in the year 
class LessonSchedule(models.Model):
    start_date = models.DateField()
    lesson_index = models.IntegerField()
    lesson_date = models.DateField()

    class Meta:
        unique_together = 'start_date', 'lesson_index')

2 个答案:

答案 0 :(得分:1)

如果您使用ModelForm,可以尝试这种方式

class GrupoIncidenciaForm(forms.ModelForm):
id = forms.CharField(required=False, widget=forms.HiddenInput())

codigo = forms.CharField(required=True,
                         label='Código',
                         widget=forms.TextInput(attrs={'maxlength': '5', 'class': 'text-uppercase'}))

titulo = forms.CharField(required=True, label='Título', widget=forms.TextInput(attrs={'maxlength': '255'}))

class Meta:
    model = GrupoIncidencia
    fields = '__all__'
    labels = {
        'tipo': 'Tipo'
    }

def clean_codigo(self):
    return self.cleaned_data['codigo'].upper().zfill(5)

def __init__(self, *args, **kwargs):
    if kwargs.get('instance'):
        initial = kwargs.setdefault('initial', {})
        initial['incidencias'] = [t.pk for t in kwargs['instance'].incidencias.all()]
    forms.ModelForm.__init__(self, *args, **kwargs)

def save(self, commit=True):
    instance = forms.ModelForm.save(self, False)
    old_save_m2m = self.save_m2m

    def save_m2m():
        old_save_m2m()
        instance.incidencias.clear()
        for incidencia in self.cleaned_data['incidencias']:
            instance.incidencias.add(incidencia)

    self.save_m2m = save_m2m
    if commit:
        instance.save()
        self.save_m2m()

    return instance

答案 1 :(得分:0)

example

参见图片附件。只需使用admin from django.contrib import admin