How to Solve Error Message TypeError at /save_staff/ MultiValueDict.get() missing 1 required positional argument: ‘key’ when running Django Application

Posted on

Introduction

This article is also has a connection or a relation with a previous article exist. In that previous article, there is an attempt for achieving a certain purpose. That article is ‘How to Use ModelForm to Create a Form for submitting User Input in Django Application‘. On the way performing the steps exist in that article, the error message appear. Actually, below is the complete error message :

TypeError at /save_staff/

MultiValueDict.get() missing 1 required positional argument: 'key'

Request Method:     POST
Request URL:    http://localhost:8000/save_staff/
Django Version:     4.1.1
Exception Type:     TypeError
Exception Value:    

MultiValueDict.get() missing 1 required positional argument: 'key'

So, upon submitting a form generated from a ModelForm, the above error message appear. In the above error message, not every part of the error message is shown. But at certain point, there is a certain part which exist and it is pointing the actual error message. In other words, actually there is a line of error message which is clearly pointing a specific line. That line is triggering the error messages. It exist in the following line :

        staff.unit = request.POST.get()

So, the reason for the trigger of the error message is very simple. It is because the line of source code above does not have the correct format. In the above line of source code, it is a line which has a certain function for trying to retrieve data from a POST method request. But unfortunately, it is triggering the error message. Before getting on to the part for solving the problem, below is the structure of the Django project :

C:\project>dir
Volume in drive C is Windows-SSD
Volume Serial Number is CA30-19A4

Directory of C:\project

09/06/2022 07:13 AM <DIR>          .
09/06/2022 10:42 AM <DIR>          ..
09/06/2022 08:19 PM <DIR>          apps
08/24/2022 09:30 AM        159,744 db.sqlite3
08/20/2022 05:17 PM            683 manage.py
08/20/2022 05:18 PM <DIR>          project
09/06/2022 07:14 AM            126 requirements.txt
3 File(s) 160,553 bytes
4 Dir(s) 65,556,508,672 bytes free

C:\project>

Furthermore, below is the structure of the project apps. It is an ‘apps’ folder exist inside the project folder :

(env) C:\project\apps>dir
Volume in drive C is Windows-SSD
Volume Serial Number is CA30-19A4

Directory of C:\project\apps

09/06/2022 08:19 PM <DIR>       .
09/06/2022 07:13 AM <DIR>       ..
08/24/2022 10:02 AM         215 admin.py
08/24/2022 08:43 AM         146 apps.py
09/17/2022 02:18 PM         454 forms.py
08/26/2022 02:19 PM <DIR>       migrations
08/26/2022 02:05 PM       1,548 models.py
09/06/2022 07:01 PM <DIR>       templates
08/24/2022 08:43 AM          63 tests.py
09/06/2022 08:03 AM         118 urls.py
09/08/2022 06:43 AM         871 views.py
08/24/2022 08:43 AM           0 __init__.py
09/08/2022 06:43 AM <DIR>       __pycache__
7 File(s) 2,961 bytes
6 Dir(s) 66,276,225,024 bytes free

(env) C:\project\apps>

How to Solve Error Message TypeError MultiValueDict.get() missing 1 required positional argument: ‘key’

In this case, before getting into the defail of the solving steps, below is the content of the ‘views.py’ file which is the cause of the error message to appear. It is actually where the line of the source code triggering the error appear :

def add_staff(request):
    form = StaffForm
    context = {'form':form}
    return render(request,"add_staff.html", context)
def save_staff(request):
    if request.POST:
        staff = Staff()
        staff.unit = request.POST.get()
        staff.name = request.POST.get('name')
        #print("Name : ",staff.name)
        print("Staff Name : ",staff.name)
        staff.save()
    else:
        print("Not a POST request")
    return render(request,"list_staff.html")

Apparently, the step solving the error is quite simple. In this case, TypeError is hinting there is an error for the type of MultiValueDict.get(). Since the get() method is a method for returning multi value in a dictionary form, it is missing in the syntax. It is actually missing the key where it has to be specified. Like in the next line :

        staff.name = request.POST.get('name')

The above line is also has a similar syntax pattern but with a ‘key’ definition in it. In the above context, it is a key ‘name’. So, in order to solve the problem there is two ways to do it :

  1. First, the easy way is just remove it. It is the most simple way which is actually eliminating the problem.

  2. The second is to modify it. In other words, just add any ‘key’ which is available as it exist as the name of the property located in the form properties. Obviously, it is the form properties where the data comes from. It is where the source of the request POST method originally comes from. In order to choose another property which is retrieved from the model attribute which is the base property of the ModelForm, below is the ModelForm with its associated model. In other words, check the ‘forms.py’ for checking the ModelForm as it exist below :

    class StaffForm(ModelForm):
        class Meta:
            model = Staff
            fields = '__all__'
  3. Since the ModelForm of ‘StaffForm’ is using ‘Staff’ as its model where the ‘StaffForm’ which is the ModelForm is using all of its field in the form, check the model ‘Staff’ to check another property or attribute beside ‘name’. Below is the content of the ‘models.py’ which is specifically in the part for declaring ‘Staff’ model :

    class Staff(models.Model):
        id_unique = models.AutoField(primary_key=True)
        user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, default=None)
        name = models.CharField(max_length=255, default="")
        unit = models.ForeignKey(Unit, on_delete=models.CASCADE, null=True, blank=True, default=None)
        def __str__(self):
            return '%s' %(self.name)

    Aside from ‘name’, there is another attribute which is possible as the property of the form. It is ‘user’ and also ‘unit’. In that case, just change the line triggering error message as follows :

            staff.unit = request.POST.get('unit')

    Why choosing ‘unit’ as the key ?. It is obvious since it is trying to pass the value retrieved from the get method() using the key ‘unit’, it must passed to the attribute of ‘unit’ of the staff object. So, the revision will be as follows :

    def add_staff(request):
        form = StaffForm
        context = {'form':form}
        return render(request,"add_staff.html", context)
    
    def save_staff(request):
        if request.POST:
            staff = Staff()
            staff.unit = request.POST.get('unit')
            staff.name = request.POST.get('name')
            #print("Name : ",staff.name)
            print("Staff Name : ",staff.name)
            staff.save()
        else:
            print("Not a POST request")
        return render(request,"list_staff.html")
  4. Last but not least, just execute the ‘add_staff’ URL to access the associated page in the Django application once more. After that, give the proper entry input and then submit it. If there are no other error messages appear, it will end as in the article ‘How to Use ModelForm to Create a Form for submitting User Input in Django Application‘.

Leave a Reply