Django: ValueError: Cannot create form field because its related model has not been loaded yet

Question:

I’m having some trouble with a Django project I’m working on. I now have two applications, which require a fair bit of overlap. I’ve really only started the second project (called workflow) and I’m trying to make my first form for that application. My first application is called po. In the workflow application I have a class called WorkflowObject, which (for now) has only a single attribute–a foreign key to a PurchaseOrder, which is defined in po/models.py. I have imported that class with from po.models import PurchaseOrder.

What I’m trying to do is have a page where a user creates a new PurchaseOrder. This works fine (it’s the same form that I used in my PurchaseOrder application), and then uses that instance of the class to create a WorkflowObject. The problem now, is that I get the error: ValueError: Cannot create form field for 'purchase' yet, because its related model 'PurchaseOrder' has not been loaded yet. I’m really not sure where to start with this. It was working ok (allowing me to create a new PurchaseOrder and forward to a url with its primary key in the url) until I added the view that should allow me to create a new WorkflowObject. I’ll put that specific view here:

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django_tables2 import RequestConfig
from po.models import PurchaseOrderForm, PurchaseOrder
from workflow.models import POObject, WorkflowForm


def new2(request, number):
 po=PurcchaseOrder.objects.get(pk=number)
 if request.method == 'POST':
   form = WorkflowForm(request.POST)
   if form.is_valid():
      new_flow = form.save()
      return HttpResponse('Good')
   else:
      return render(request, 'new-workflow.html', {'form': form, 'purchase': po})
  else:
    form = WorkflowForm()
    return render(request, 'new-workflow.html', {'form': form, 'purchase': po})

The lines of code that seem to be causing the error (or at least, one of the lines that is shown in the traceback) is:

class WorkflowForm(ModelForm):
   purchase = forms.ModelChoiceField(queryset = PurchaseOrder.objects.all())

EDIT:
I seem to have made a very noob mistake, and included parentheses in my definition of WorkflowObject, that is, I had said purchase=models.ForeignKey('PurchaseOrder'), instead of purchase=models.ForeignKey(PurchaseOrder)

Asked By: Daniel Rosenthal

||

Answers:

Firstly, you can try reduce code to:

def new2(request, number):
    po=PurcchaseOrder.objects.get(pk=number)

    form = WorkflowForm(request.POST or None)
    if form.is_valid():
        new_flow = form.save()
        return HttpResponse('Good')
    else:
        return render(request, 'new-workflow.html', {'form': form, 'purchase': po})

Secondly, I not understood why you at other case wrote forms.ModelChoiceField(...) and another case ModelForm instance forms.ModelForm ?

Answered By: Abbasov Alexander

Seems, that there are nothing special in your WorkflowForm, so you can define it as follows:

class WorkflowForm(ModelForm):
    class Meta:
        model = WorkflowObject

Field for relation will be created automatically.

Documentation: Creating forms from models

Answered By: krasnoperov

I had a similar problem and was able to resolve this by declaring all my modelForm classes below all my class models in my models.py file. This way the model classes were loaded before the modelForm classes.

Answered By: Fadyboy

Just ran into this problem. I had a string value in the to= value of a ForeignKey (intentionally). The error was thrown because I changed my app’s name from messages to messaging (because messages conflicted with django.contrib.messages), but forgot to change the model’s ForeignKey string value.

For example:

# messaging/models.py

class Thread(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)

class Message(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    thread = models.ForeignKey('messages.Thread', on_delete=models.CASCADE) # <- here!

The error:

ValueError: Cannot create form field for 'thread' yet, because its related model 'messages.Thread' has not been loaded yet

The solution was simply to change:

models.ForeignKey('messages.Thread', ...

to:

models.ForeignKey('messaging.Thread', ...
Answered By: Jarad
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.