FieldError in manage.py check

Hi, I have a MarketCrop model and a Contract model, defined in the same module, where a MarketCrop has many Contracts. I’m able to create new Contracts for a MarketCrop in the shell like this:

from main.models.market_crop import MarketCrop, Contract
mc = MarketCrop.objects.get(pk=53)
c = Contract(market_crop_id=53, is_basis=True, contract_date=datetime.now(), bushels=1000, price=3.75)
c.save()

where the parent key is specified by ‘market_crop_id’.

I’m trying to implement a form that will allow Contracts to be added for an existing MarketCrop without the user having to redundantly specify the MarketCrop. For now, I’d like to do this using a hidden field ‘market_crop_id’ on the form (I’ll deal with security concerns later). But I’m stuck getting a FieldError when I try to run the local server. There’s probably a dumb mistake somewhere, but I’m not seeing it. I appreciate any help with this!

The url pattern is:

path('contract/create/<int:market_crop>/<int:is_basis>',
     login_required(ContractCreateView.as_view()), name='contract_create'),

and a typical url path looks like this: /contract/create/53/1/
The view is like this:

class ContractCreateView(CreateView):
    model = Contract
    form_class = ContractCreateForm
    template_name = 'main/contract_form.html'

    def dispatch(self, request, *args, **kwargs):
        """ get the info from the request path into extra_context """
        self.extra_context = {'market_crop': kwargs['market_crop'],
                              'is_basis': kwargs['is_basis']}
        return super().get(request, *args, **kwargs)

    def get_initial(self):
        """ convert extra_context data into initial data for the form """
        print(f'in get_initial: {self.extra_context=}')
        return {'market_crop_id': self.extra_context['market_crop'],
                'is_basis': 'on' if self.extra_context['is_basis'] == 1 else ''}

    def get_success_url(self):
        mc_id = self.kwargs.get('market_crop', None)
        return reverse('marketcrop_update', args=[mc_id])

The (crispy) form looks like this:

class ContractCreateForm(ModelForm):

    def __init__(self, *args, **kwargs):
        print(f'in form: {kwargs=}')
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.add_input(Submit('submit', 'Create'))
        self.helper.form_id = 'contractform'
        self.helper.layout = Layout(
            Fieldset('Contract Information',
                     'contract_date', 'bushels', 'price', 'terminal',
                     'contract_number', 'delivery_start_date',
                     'delivery_end_date',
                     Field('is_basis', type='hidden'),
                     Field('market_crop_id', type='hidden'),
                     )
        )

    class Meta:
        model = Contract
        fields = '''contract_date bushels price terminal
                    contract_number delivery_start_date
                    delivery_end_date is_basis market_crop_id'''.split()

The essential parts of the models are like this:

class MarketCrop(models.Model):
    """
    A crop which can be marketed and which has a unique set of futures prices
    for a given county.
    """
    assumed_basis_for_new = models.FloatField(
        default=0, validators=[MinVal(-2), MaxVal(2)],
        help_text="Assumed basis for non-contracted bushels.")
    farm_year = models.ForeignKey(FarmYear, on_delete=models.CASCADE,
                                  related_name='market_crops')
    market_crop_type = models.ForeignKey(MarketCropType, on_delete=models.CASCADE)
    fsa_crop = models.ForeignKey(FsaCrop, on_delete=models.CASCADE,
                                 related_name='market_crops')

class Contract(models.Model):
    """
    Represents a futures or basis contract
    """
    is_basis = models.BooleanField(
        default=False,
        help_text='Specifies a basis contract instead of a futures contract.')
    contract_date = models.DateField(
        default=datetime.today)
    bushels = models.IntegerField(default=0)
    price = models.FloatField(
        default=0, verbose_name="price per bushel")
    terminal = models.CharField(max_length=60, blank=True)
    contract_number = models.CharField(max_length=25, blank=True)
    delivery_start_date = models.DateField(
        null=True, blank=True)
    delivery_end_date = models.DateField(
        null=True, blank=True)
    market_crop = models.ForeignKey(
        MarketCrop, on_delete=models.CASCADE, related_name='contracts')

But the model form code is raising a FieldError, complaining that ‘maket_crop_id’ is an unknown field. I don’t understand this.

$ mpy check
Traceback (most recent call last):
File “/home/dow/python/ifbtdir/manage.py”, line 22, in
main()
File “/home/dow/python/ifbtdir/manage.py”, line 18, in main
execute_from_command_line(sys.argv)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/management/init.py”, line 442, in execute_from_command_line
utility.execute()
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/management/init.py”, line 436, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/management/base.py”, line 412, in run_from_argv
self.execute(*args, **cmd_options)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/management/base.py”, line 458, in execute
output = self.handle(*args, **options)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/management/commands/check.py”, line 76, in handle
self.check(
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/management/base.py”, line 485, in check
all_issues = checks.run_checks(
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/checks/registry.py”, line 88, in run_checks
new_errors = check(app_configs=app_configs, databases=databases)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/checks/urls.py”, line 14, in check_url_config
return check_resolver(resolver)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/core/checks/urls.py”, line 24, in check_resolver
return check_method()
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/urls/resolvers.py”, line 494, in check
for pattern in self.url_patterns:
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/utils/functional.py”, line 57, in get
res = instance.dict[self.name] = self.func(instance)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/urls/resolvers.py”, line 715, in url_patterns
patterns = getattr(self.urlconf_module, “urlpatterns”, self.urlconf_module)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/utils/functional.py”, line 57, in get
res = instance.dict[self.name] = self.func(instance)
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/urls/resolvers.py”, line 708, in urlconf_module
return import_module(self.urlconf_name)
File “/usr/lib/python3.10/importlib/init.py”, line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File “”, line 1050, in _gcd_import
File “”, line 1027, in _find_and_load
File “”, line 1006, in _find_and_load_unlocked
File “”, line 688, in _load_unlocked
File “”, line 883, in exec_module
File “”, line 241, in _call_with_frames_removed
File “/home/dow/python/ifbtdir/ifbt/urls.py”, line 21, in
path(‘’, include(‘main.urls’)),
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/urls/conf.py”, line 38, in include
urlconf_module = import_module(urlconf_module)
File “/usr/lib/python3.10/importlib/init.py”, line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File “”, line 1050, in _gcd_import
File “”, line 1027, in _find_and_load
File “”, line 1006, in _find_and_load_unlocked
File “”, line 688, in _load_unlocked
File “”, line 883, in exec_module
File “”, line 241, in _call_with_frames_removed
File “/home/dow/python/ifbtdir/main/urls.py”, line 4, in
from .views import (
File “/home/dow/python/ifbtdir/main/views.py”, line 24, in
from .forms import (FarmYearCreateForm, FarmYearUpdateForm, FarmCropUpdateForm,
File “/home/dow/python/ifbtdir/main/forms.py”, line 171, in
class ContractCreateForm(ModelForm):
File “/home/dow/python/ifbtdir/env/lib/python3.10/site-packages/django/forms/models.py”, line 320, in new
raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (market_crop_id) specified for Contract

If I change the name of the hidden field from ‘market_crop_id’ to ‘market_crop’, for example, I can see that the values in the url path are populated in the form hidden fields, but of course, then the form won’t validate.

I really appreciate any suggestions on this!

1 Like

A FieldError in Django is raised when there is an issue with a field in a model.
It usually occurs when the field name is not recognized or does not exist in the model.

It seems that you are encountering a django.core.exceptions.
FieldError with the message Unknown field(s) (market_crop_id) specified for Contract.
This error typically occurs when you have specified an unknown field in your Contract model.

To resolve this issue, you should check your Contract model and ensure that the field
market_crop_id is defined correctly. Make sure that the field name matches the one
specified in your model.

  • In your view do this, instead since you are using CBV:
class ContractCreateView(CreateView):
   model = Contract
   form_class = ContractCreateForm
   template_name = 'main/contract_form.html'

   def dispatch(self, request, *args, **kwargs):
       """ get the info from the request path into extra_context """
       self.extra_context = {
         'market_crop': kwargs['market_crop'],
       'is_basis': kwargs['is_basis']}
       return super().get(self.request, *args, **kwargs)

Thanks @Blaise-93. The view snippet in your reply is, I think, identical to what I posted eariler, but it helped me spot an error in my code. The super method “get” didn’t match the overridden method “dispatch”. I fixed that but an still having problems. Changing the field name to market_crop, which is the foreign key field name in my model is giving me other issues.

Hi Drake, I am glad I was able to help to an extent, just try and use self when on CBV, let me look at your codebase again and get back to you on this error, it’s more like a complex lookup error of your ‘market_crop’. However, I was just trying to point you to the right direction. I will BRB.

Creating contracts is working now after renaming the form field to ‘market_crop’, overriding the get method instead of dispatch, then adding a condition in get_initial to ensure that self.extra_context is not None (In the post, get_initial is being called a second time and in this case self.extra_context is None). I’m pretty sure this is not the optimal solution for this sort of common problem, and I’m open to suggestions to improve it.
Here’s the modified code that works.

class ContractCreateView(CreateView):
    model = Contract
    form_class = ContractCreateForm
    template_name = 'main/contract_form.html'

    def get(self, request, *args, **kwargs):
        self.extra_context = {'market_crop': kwargs['market_crop'],
                              'is_basis': kwargs['is_basis']}
        return super().get(request, *args, **kwargs)

    def get_initial(self):
        if self.extra_context:
            return {'market_crop': self.extra_context['market_crop'],
                    'is_basis': 'on' if self.extra_context['is_basis'] == 1 else ''}

    def post(self, request, *args, **kwargs):
        # TODO: ensure_same_user(self.get_object().market_crop.farm_year,
        #                  request, "Creating", "contracts")
        return super().post(request, *args, **kwargs)

    def get_success_url(self):
        mc_id = self.kwargs.get('market_crop', None)
        return reverse('marketcrop_update', args=[mc_id])

The form code just has the field name changed

class ContractCreateForm(ModelForm):

    def __init__(self, *args, **kwargs):
        print(f'in form: {kwargs=}')
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.add_input(Submit('submit', 'Create'))
        self.helper.form_id = 'contractform'
        self.helper.layout = Layout(
            Fieldset('Contract Information',
                     'contract_date', 'bushels', 'price', 'terminal',
                     'contract_number', 'delivery_start_date',
                     'delivery_end_date',
                     Field('is_basis', type='hidden'),
                     Field('market_crop', type='hidden'),
                     )
        )
    class Meta:
        model = Contract
        fields = '''contract_date bushels price terminal
                    contract_number delivery_start_date
                    delivery_end_date is_basis market_crop'''.split()
1 Like