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
для классов.