Django: создание записи из сообщения формы в другом приложении

У меня есть 3 приложения в рамках одного проекта: Регистрации Модель Регистрация учащиеся Модель:Учащийся трек Модель: LearnerTrack

Когда я создаю объект ученика, у меня есть представление в learner_track, которое получало экземпляр ученика и создавало соответствующие записи отслеживания на основе курса, на который ученик регистрировался. Однако при создании отношения внешнего ключа оно перестает работать и выдает ошибку:

Cannot assign "UUID('11456134-fab7-41f7-a7be-6bdaf423d1c6')": "LearnerTrack.learnerId" должен быть экземпляром "Learner".

Learner model.py

class Learner(models.Model):
 class Status(models.TextChoices):
       LIVE = 'Live', 'Live'
       COMPLETE = 'Complete', 'Complete'
       DEFERRED = 'Deferred', 'Deferred'
       WITHDRAWN = 'Withdrawn', 'Withdrawn'
 status = models.CharField(
       max_length=25,
       choices = Status,
       default = Status.LIVE
  )
 learnerId = models.UUIDField(primary_key=True, default=uuid.uuid4)
 contractId = models.PositiveIntegerField(default = 1)
 firstname = models.CharField(max_length=150)
 middlename = models.CharField(max_length=150, blank=True, null=True)
 surname = models.CharField(max_length=150)
 uln = models.ForeignKey(Registration, on_delete=models.CASCADE)
 postcode = models.CharField(max_length=8)
 area = models.CharField(max_length=10)
 created = models.DateTimeField(auto_now_add=True)
 funding = models.SmallIntegerField()
 groupId = models.ForeignKey(Group, on_delete=models.PROTECT)
 courseId = models.ForeignKey(Course, default = 'WMCASec', on_delete=models.CASCADE)
 postcode_code = models.FloatField(default=1.0)

 notes = models.TextField(blank = True, null = True)

 objects = models.Manager() #The default manager
 live = LiveManager()
 complete = CompleteManager()
 deferred = DeferredManager()
 withdrawn = WithdrawnManager()

 def clean(self):
      if self.postcode:
           self.postcode = self.postcode.replace(" ","").upper()
           #all postcode data saved in same way


 def __str__(self):
     return f"{self.learnerId}"
 
 def get_absolute_url(self):
      return reverse('learner-detail', args=[str(self.learnerId)])

 def save(self, *args, **kwargs):
    super(Learner, self).save(*args, **kwargs)

 class Meta:
     ordering = ['surname']
     indexes = [models.Index(fields=['-created'])]

learners view.py

def add_new_learner(request, uln, *args, **kwargs):
registration = Registration.objects.get(uln=uln)
learner_instance = Learner.objects.filter(uln=uln)
learners = Learner.objects.all()
registered_groups = list(learner_instance)
initial_dict = {
    'firstname' : registration.firstname,
    'middlename' : registration.middlename,
    'surname' : registration.surname,
    'uln' : registration.uln,
    'postcode' : registration.postcode,
    'area' : registration.area,
    'postcode_code' : registration.postcode_code,
    'ethnicity' : registration.ethnicity,
    'funding' : registration.funding,
    'notes':registration.notes,
        }
   
if request.method == 'POST':
    form = CreateLearnerForm(request.POST or None)
    
    if form.is_valid():
        form.save(*args, **kwargs)

        return HttpResponseRedirect("/learners/learner_list/") 
               
else:
    form = CreateLearnerForm(request.POST or None, initial = initial_dict)  

context = {"form":form, 'learners':learners, 'registration':registration, "learner_instance":learner_instance, "registered_groups":registered_groups,
            }
return render(request, 'learners/add_new_learner.html', context,)

track models.py

class LearnerTrack(models.Model):
 contractId = models.PositiveIntegerField(default=1)
 learnerId = models.ForeignKey('learners.Learner', on_delete=models.CASCADE)
 groupId =  models.CharField(max_length=20, null=True, blank=True)
 firstname = models.CharField(max_length=50, null=True, blank=True)
 surname = models.CharField(max_length=50, null=True, blank=True)
 courseId = models.CharField(max_length=20, null=True, blank=True)
 aimId = models.CharField(max_length=20, null=True, blank=True)
 uln = models.PositiveBigIntegerField()
 startDate = models.DateField(null=True, blank=True)
 endDate = models.DateField(null=True, blank=True)
 achieved = models.BooleanField(default=False)
 pfrStart = models.PositiveBigIntegerField(default=0)
 pfrEnd = models.PositiveIntegerField(default=0)
 funding = models.FloatField(default=0.00)
 notes = models.CharField(max_length=1000, null=True, blank=True)
 created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
 var = models.PositiveIntegerField(default = 0) # store variables like hours for WRAP

 class Meta:
   unique_together = ('uln', 'aimId')

 def __str__(self):
      return f"{self.firstname} {self.surname}"
 

 


@receiver(post_save, sender='learners.Learner')
def create_profile(sender, instance, created, **kwargs):
aims = CourseAim.objects.all()

if created:        
    for aim in aims:
        pcode = 1.0
        if aim.uplift == True:
            pcode = instance.postcode_code

        if aim.courseId == instance.courseId:
            
                LearnerTrack.objects.create(learnerId=instance.learnerId, groupId = instance.groupId,
                courseId=instance.courseId, aimId = aim.aimId, contractId = instance.contractId,
                funding = aim.funding * pcode,
                uln = instance.uln,
                firstname = instance.firstname,
                surname = instance.surname)

Я новичок в django, поэтому прошу простить любые ошибки новичков в кодировании. Я очень хочу научиться.

Спасибо

Это происходит потому, что вы пытаетесь присвоить UUID там, где модель ожидает объект instance:

class LearnerTrack(models.Model):
 ...
 learnerId = models.ForeignKey('learners.Learner', on_delete=models.CASCADE)
 ...

Вы спускаете экземпляр вниз, чтобы получить доступ к UUID и пытаетесь присвоить его.

LearnerTrack.objects.create(
    learnerId=instance.learnerId,
    ...
)

Таким образом, просто сверните и назначьте экземпляр напрямую:

LearnerTrack.objects.create(
    learnerId=instance,
    ...
)

p.s. Одна из хороших практик кодирования - поддерживать регулярную структуру при именовании переменных и классов. В python snake_case для переменных/функций и PascalCase для классов.

Вернуться на верх