简体   繁体   中英

Django how to properly submit form and handle request?

I'm new to Django/Python and working on a webapp that queries a DB of cars based on selects/dropdowns on the home page and sends the user to a details page about the car they selected. This is done through a 'make', 'model', and 'trim' dropdown box. What I'm having trouble understanding and getting errors doing, is submitting the trim ID upon clicking a button that will submit the form. I know what needs to happen I just don't know how to do so using Django views and templates.

The make box is populated via returned queryset from IndexView. The model box is populated via jQuery/Ajax dependent upon which make was selected in the make box. The trim box is the same way, populated dependent upon what was selected in the model box. I now need to be able to submit the form (which really only needs to submit the trim ID because the trim IS the specified car) in order to show details about the car that the user has chosen.

This is the error I am getting:

Reverse for 'search' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['search/(?P<trim>\\d+)/$']

This is basically what my homepage template looks like:

  <form action="{% url 'search:search' trim.id %}" class="form-inline" id="dropdownText"> <div class="form-group" id="dropdownGroup"> <span style="display:inline-block" class="selectBox"> <select class="form-control" id="make"> <option value='empty'></option> {% for make in allMakes %} <option value="{{ make.id }}">{{ make.name }}</option> {% endfor %} </select> <label for="make" style="display:block">Make</label> </span> <span style="display:inline-block" class="selectBox"> <select class="form-control" id="model" disabled> <!-- List each make's model's name with JQ. --> </select> <label for="model" style="display:block">Model</label> </span> <span style="display:inline-block" class="selectBox"> <select class="form-control" id="trim" name="selectedTrim" disabled> <!-- List all trims for each make/model with JQ. --> </select> <label for="trim" style="display:block">Trim</label> </span> </div> <div class="text-center"> <button type="submit" class="btn btn-default" id="go">GO!</button> </div> </form> 

URLs:

# Index
url(r'^$', views.IndexView.as_view(), name='index'),

# /trimId
url(r'^(?P<pk>\d+)/$',
DetailView.as_view(), name='detail'),

# /search
url(r'^search/(?P<trim>\d+)/$', views.search, name='search'),

# Uses Ajax/JSON to change the model/trim boxes. Use make
# and model instead of pk to pass them into the view fxns.
url(r'^getmodels/(?P<make>\d+)/', views.getModels, name='getmodels'),
url(r'^gettrims/(?P<model>\d+)/', views.getTrims, name='gettrims'),

Views:

class IndexView(generic.ListView):
    template_name = 'search/index.html'

    # Name of the template varible.
    context_object_name = 'allMakes'

        def get_queryset(self):
            # Return what will be listed in index.html
            return Make.objects.all()

class DetailView(generic.DetailView):
    model = Trim
    template_name = 'search/detail.html'

# Take in the request and the ID for the selected Make
# and return something that we can work with in JS!
def getModels(request, make):
    selectedMake = Make.objects.get(id=make)

    # Get the models based on what was selected as the make.
    models = Model.objects.all().filter(make=selectedMake)
    # Translate to JSON
    jsonModels = serializers.serialize("json", models)
    # Return the JSON.
    return HttpResponse(jsonModels, content_type='application/javascript')

def getTrims(request, model):
    selectedModel = Model.objects.get(id=model)

    trims = Trim.objects.all().filter(model=selectedModel)
    jsonTrims = serializers.serialize("json", trims)
    return HttpResponse(jsonTrims, content_type='application/javascript')

# Can I make this redirect to the DetailView with the ID for the
# trim to show details for?
def search(request, trim):
    selectedTrim = get_object_or_404(Trim, pk=trim)
    context = {'trim': selectedTrim}
    return render(request, 'search/detail.html', context)

That error:

Reverse for 'search' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['search/(?P<trim>\\d+)/$']

means that you didn't give the id parameter (you called it trim). It should be part of the arguments or keyword arguments.

I assume that's because there is no trim object in the template here:

<form action="{% url 'search:search' trim.id %}"

Is that template rendered via a DetailView? If that's the case the following would probably work:

<form action="{% url 'search:search' object.id %}"

The solution to the problem I was having lied in my url patterns. By taking out the ID portion of the search URL, and changing the view as such:

def search(request):

    trim = request.GET['selectedTrim']
    selectedTrim = get_object_or_404(Trim, id=trim)
    context = {'trim': selectedTrim}
    return render(request, 'search/detail.html', context)

and my form action to:

action="{% url 'search:search' %}"

I was able to successfully pass the selected trim to the view via request method, and not through the url regex variable, which was causing the error due to the selected trim ID not actually existing via context provided to the template (I think).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM