Django: create record from form post in another app
I have 3 apps within a project: registrations Model Registration learners Model:Learner track Model: LearnerTrack
When I create a learner object I've a view in learner_track which had been receiving the learner instance and creating relevant tracking records based on the course the learner was registering on. However, when creating a foreign key relationship it stops working and gives an error:
Cannot assign "UUID('11456134-fab7-41f7-a7be-6bdaf423d1c6')": "LearnerTrack.learnerId" must be a "Learner" instance.
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)
I'm new to django so please forgive any rookie errors in coding. I'm eager to learn.
Thank you
That happens because you are trying to assign an UUID
where the model expects an object instance
:
class LearnerTrack(models.Model):
...
learnerId = models.ForeignKey('learners.Learner', on_delete=models.CASCADE)
...
You are drilling down the instance to access the UUID
and trying to assign it.
LearnerTrack.objects.create(
learnerId=instance.learnerId,
...
)
Thus, just roll-up and assign the instance directly:
LearnerTrack.objects.create(
learnerId=instance,
...
)
p.s. One good coding practice is to maintain a regular structure while naming your variables and classes. In python snake_case
for variables/functions and PascalCase
for classes.