Django Error: TypeError: __init__() got an unexpected keyword argument 'attrs'

7.7k views Asked by At

I'm trying to create a form where I'm getting certain details from the user.

I have defined fields in forms.py and I'm also defining other attributes like placeholder and css class using django widget system. But it is showing me a TypeError:

TypeError: __init__() got an unexpected keyword argument 'attrs'

Following is my code:

models.py

from django.db import models

class Contact(models.Model):
    your_name = models.CharField(max_length=100) 
    your_email = models.EmailField()
    your_subject = models.CharField(max_length=100)
    your_comment = models.TextField(max_length=200)
 
 def __str__(self):
    return self.name

forms.py

from django.forms import ModelForm, TextInput, TextInput, EmailField
from .models import Contact

class ContactForm(ModelForm):
    class Meta:
        model = Contact
        fields = ('your_name', 'your_email', 'your_subject', 'your_comment')
        widgets = {
            'your_name' : TextInput(attrs={'placeholder': 'Name *', 'class': 'form-control'}),
            'your_email' : EmailField(attrs={'placeholder': 'Email *', 'class': 'form-control'}),
            'your_subject' : TextInput(attrs={'placeholder': 'Subject *', 'class': 'form-control'}),
            'your_comment' : Textarea(attrs={'placeholder': 'Comment *', 'class': 'form-control'}),
        }

I've read Django docs for Overriding default fields and also this question init() got an unexpected keyword argument 'attrs' but cannot fix the error.

I am quite new to Python and Django and would appreciate any help, thank you.

4

There are 4 answers

2
Pythonista On BEST ANSWER

TL;DR: EmailField is a just that a Field which can't be set as a widget, if you tried you'd run into the below problem, you want EmailInput which is the widget for EmailField.

First, TextInput and Textarea accept the keyword argument attrs in their __init__. So, these are fine.

Look at this line:

EmailField(attrs={'placeholder': 'Email *', 'class': 'form-control'}),

EmailField is a subclass of CharField which in turn is a subclass of Field. Throughout this hierarchy attrs will be passed along until it hits Field which doesn't accept attrs.

For reference here's the __init__ for Field:

  def __init__(self, required=True, widget=None, label=None, initial=None,
               help_text='', error_messages=None, show_hidden_initial=False,
               validators=(), localize=False, disabled=False, label_suffix=None):

The __init__ for CharField:

 def __init__(self, max_length=None, min_length=None, strip=True, empty_value='', *args, **kwargs)

      ....
      super(CharField, self).__init__(*args, **kwargs)
      # attrs is passed to Field -> error

The __init__ for EmailField:

 def __init__(self, *args, **kwargs):
    super(EmailField, self).__init__(*args, strip=True, **kwargs)
    # attrs is passed to CharField

There is a widget argument that is accepted in which you can place a widget that does accept the attrs keyword.

0
narendra-choudhary On

The error is in line

'your_email' : EmailField(attrs={}),

EmailField is a field, not a widget. Default widget for EmailField is EmailIput.

You need to provide a widget:

'your_email' : EmailInput(attrs={}),
0
7guyo On
from django.forms import ModelForm
from django import forms
from .models import Contact

class UserForm(ModelForm):
    class Meta:
        model = Contact
        fields = ('sender_name','sender_email')
        widgets = {
            'sender_name': forms.TextInput(attrs={'placeholder': 'Enter sender name'}),
        }

import forms and access the form fields with . operator

0
Super Kai - Kazuya Ito On

You use the form field forms.EmailField() for "widgets" which is wrong:

widgets = {
    # ...
    'your_email' : EmailField(attrs={...}), # Wrong
    # ...
}

So, instead, you need to use the widget forms.EmailInput() for "widgets" which is correct:

widgets = {
    # ...
    'your_email' : EmailInput(attrs={...}), # Correct
    # ...
}