0

models.py

Create your models here.

class DeviceType(models.Model):
    device_type = models.CharField(max_length=200,unique=True)

class Repair(models.Model):
    device_type                     = models.ForeignKey(DeviceType,to_field='device_type')
    submitted_by                    = models.ForeignKey(User,to_field='username')
    comments                        = models.TextField()
    repair_request_date             = models.DateField(default=datetime.now)
    repair_status                   = models.ForeignKey(RepairStatus, to_field="repair_status", null=True)
    repair_cost_estimate            = models.FloatField(null=True)

views.py

def repair_form(request):
    dlist = get_my_choices(request.user)
    if request.method == "POST":
        form = RepairForm(request.POST,device_type = dlist, submitted_by = request.user)
        #print(form)
        if form.is_valid():
            print("Inside repair form")
            post = form.save(commit=False)
            post.submitted_by = request.user
            print(post.pk)
            post.save()
            return redirect("RepairRequest")
    else:
        dlist = get_my_choices(request.user)
        print("Inside else of repair form")
        form = RepairForm( device_type = dlist, submitted_by = request.user)
        print("else form: ", form)
        return render(request, "Form_template.html", {"form": form,\
                                                      "name": "Repair Request Form"})

forms.py

class RepairForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        print("kwargs: ",kwargs)
        dlist = kwargs["device_type"]
        print("Inside init of RequestForm")
        super(RepairForm, self).__init__(*args, **kwargs)
        self.fields["device_type"] = forms.ChoiceField(choice = [dlist])
        self.fields["submitted_by"] = kwargs["submitted_by"]



    class Meta:
        print("Inside Meta of RepairForm")
        model = Repair
        print("model: ", model)
        fields = "__all__"
        print("fields: ", fields)
        exclude = ("repair_cost_estimate","repair_status","submitted_by","repair_request_date",)

I am trying to create a dynamic dropdown list in django forms. Dynamic in the sense that the dropdown list will only populate with the data that is associated with the given user. In my case, each user may have a laptop, mouse, etc. with him. I have written the code shown above. Every time I execute the code I get the following error:

TypeError at /user_dashboard/RepairRequest.html
__init__() got an unexpected keyword argument 'submitted_by'
Request Method: GET
Request URL:    http://127.0.0.1:8000/user_dashboard/RepairRequest.html
Django Version: 1.11.13
Exception Type: TypeError
Exception Value:    
__init__() got an unexpected keyword argument 'submitted_by'
Exception Location: E:\inventory management\inventory_management_service\inventory_management_app\forms.py in __init__, line 15
Python Executable:  C:\Anaconda2\python.exe
Python Version: 2.7.14
Python Path:    
['E:\\inventory management\\inventory_management_service',
 'C:\\Anaconda2\\python27.zip',
 'C:\\Anaconda2\\DLLs',
 'C:\\Anaconda2\\lib',
 'C:\\Anaconda2\\lib\\plat-win',
 'C:\\Anaconda2\\lib\\lib-tk',
 'C:\\Anaconda2',
 'C:\\Users\\Jaimik Jain\\AppData\\Roaming\\Python\\Python27\\site-packages',
 'C:\\Anaconda2\\lib\\site-packages',
 'C:\\Anaconda2\\lib\\site-packages\\win32',
 'C:\\Anaconda2\\lib\\site-packages\\win32\\lib',
 'C:\\Anaconda2\\lib\\site-packages\\Pythonwin',
 'C:\\Anaconda2\\lib\\site-packages\\pywinpty-0.5-py2.7-win-amd64.egg']
Server time:    Thu, 7 Jun 2018 09:56:44 +0000

I request your help at the earliest.

2
  • You should pop submitted_by before performing a super().__init__ call. Commented Jun 7, 2018 at 10:08
  • I popped the values but, I get this error, "TypeError at /user_dashboard/RepairRequest.html __init__() got an unexpected keyword argument 'choice' ". What could be the cause? @WillemVanOnsem Commented Jun 7, 2018 at 10:13

2 Answers 2

1

The problem is in your here pass parameters submitted_by and device_type to the RepairForm constructor. Since you mention those explicitly, it means that those are stored in the kwargs dictionary.

You however do not modify this dictionary, before performing a super().__init__(*args, **kwargs) call. As a result, the superclass (the ModelForm) will receive these parameters as well, but it does not understand how to handle those parameters. As a result it will error.

You thus need to remove those parameters from the kwargs. For example with .pop(..):

class RepairForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        dlist = kwargs.pop("device_type")
        submitted_by = kwargs.pop("submitted_by")
        super(RepairForm, self).__init__(*args, **kwargs)
        self.fields["device_type"] = forms.ChoiceField(choices=[dlist])
        self.fields["submitted_by"] = submitted_by

Youshould also use choices=... as parameter when initializing a ChoiceField, instead of choice=....

I think there are multiple extra errors, but I hope this provides some good directions.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks a lot. It helped but, after changing the code, I get this: ValueError at /user_dashboard/RepairRequest.html too many values to unpack @WillemVanOnsem
@AishwaryShukla: yes you probably should write choices=dlist, instead of wrapping it in an extra list.
It's still the same. @WillemvanOnsem
@AishwaryShukla: well I would advice you to inspet what dlist actually contains. choices should be an iterable of 2-tuples: docs.djangoproject.com/en/2.0/ref/models/fields/#field-choices
What alternatives are present for choicefield? @WillienVanOnsem
1

What does your Repair model look like?

If field device_type is a foreign key to a model that contains your users devices, I think it would be a lot easier to override that fields queryset in your view rather than messing with form init. You could do:

form = RepairForm()
form.fields['device_type'].queryset = MyDeviceModel.objects.filter(user=request.user)

Note there's also no need to be passing submitted_by when calling RepairForm() - the field is excluded on the form itself and your already handling populating the submitted_by field correctly within your if form.is_valid() block so I don't think that's accomplishing anything.

EDIT

views.py

def repair_form(request):
    if request.method == "POST":
        form = RepairForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.submitted_by = request.user
            post.save()
            return redirect("RepairRequest")
    else:
       form = RepairForm()
       form.fields['device_type'].queryset = DeviceType.objects.filter(user=request.user)

       return render(request, "Form_template.html", {"form": form, "name": "Repair Request Form"})

forms.py

class RepairForm(forms.ModelForm):

   class Meta:
      model = Repair
      exclude = ( "repair_cost_estimate","repair_status","submitted_by","repair_request_date",)

7 Comments

Here MyDeviceModel must be replaced by the model name that exists in my DB right? @WilliamShaw
Yes, correct, assuming that is how your models are set up - if you like to add your Repair model to your original post I may be able to assist further.
Updated. @WilliamShaw
Updated. @WilliamShaw
@AishwaryShukla I've edited my answer the views and forms that should work for you. Note I also removed the "fields = 'all' because it's not necessary to call both fields and exclude. Sorry if the formatting/indentation is slightly off, I'm on mobile. I hope this helps.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.