processing data from django form

Question:

I have a form with a drop down list:

CATEGORY_CHOICES= [
    ('sport', 'Sport'),
    ('mini', 'Mini'),
    ('economy', 'Economy'),
    ('electro', 'Electro'),
    ('business', 'Business'),
    ]

class CategoryChoice(forms.Form):
    category= forms.CharField(label='Поиск по категории:', widget=forms.Select(choices=CATEGORY_CHOICES, ), required = False) 

URLS.PY

    urlpatterns = [
    
    path("productsHTML/<str:uuid>", productHTML, name = "productHTML"),
    path("productsHTML/", productsHTML, name = "productsHTML"),
]

VIEWS.PY

def productsHTML(request):
    
    all_products = {"products": Product.objects.all()}
    return render(request, "products.html",all_products) 

def productHTML(request, uuid):
    product = Product.objects.get(id = uuid)
    img = product.category
    slovar = {"product": product, "img": img.image}
    return render(request, "product.html", slovar)

I need that when choosing a category and pressing the "search" button, the user will be redirected to the page with the goods of the selected category?

I have no idea how to link the html template, view.py and urls.py together.
Could you please help me? I will be very grateful.

Answers:

TL;DR:

Original: make sure that you capture the ‘category’ value from the form, then convert it into whatever format you set as the ‘name’ inside your url config, and use the redirect function based on that.

Updated: Rather than setting the name and redirecting, we do a get query on the Product model based on the return value of ‘category’, and send this uuid to the detail-view in the redirect.

—— ORIGINAL ANSWER ——

I’d need to see your exact views.py and urls.py files to give an answer that is perfect for your specific use case, but assuming you’ve followed the standard Django conventions my guess is that your code should look something like this:

views.py file

from django.shortcuts import render, redirect

from . import models, forms

def search(request):
    form = forms.CategoryChoice(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        category = form.cleaned_data['category'].lower()
        new_destination = category + '_list'
        # This will output e.g. 'sport_list' or 'mini_list'
        return redirect(f'{new_destination}', permanent=True)
    context = {
        'form': form,
    }
    return render(request, 'app/search.html', context)

# I assume your views look roughly like this or the class-based equivalents
def sport_list(request):
    queryset = models.Sport.objects.all()
    context = {
        'objects': queryset
    }
    return render(request, 'app/sport_list.html', context)

def mini_list(request):
    queryset = models.Mini.objects.all()
    context = {
        'objects': queryset
    }
    return render(request, 'app/mini_list.html', context)
# ETC...

urls.py file

from django.urls import path

from . import views

urlpatterns = [
    path('search/', views.search, name='search'),
    path('sport_list/', views.sport_list, name='sport_list'),
    path('mini_list/', views.mini_list, name='mini_list'),
    # ETC...
]

—— UPDATED ANSWER ——

If I understand correctly that ‘category’ is a field for a ‘Product’, then I recommend you use a forms.ModelForm with a SelectField widget. This has the massive advantage of not needing to hard code your choices. See below:

forms.py

from django import forms

from .models import Product

class CategoryChoice(forms.ModelForm):
    class Meta:
        model = Product
        fields = ('category',)
        widgets = {
            'category': forms.Select(),
        }

You can then implement your views like this (urls as you have them are fine):

views.py

from django.shortcuts import render, redirect

from .models import Product
from .forms import CategoryChoice

def productsHTML(request):
    form = CategoryChoice(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        category = form.cleaned_data['category']
        product = Product.objects.get(category=category)
        uuid = product.id
        return redirect('productHTML', uuid=uuid, permanent=True)
    all_products = Product.objects.all()
    context = {
        'form': form,
        'products': all_products,
    }
    return render(request, "products.html", context) 

def productHTML(request, uuid):
    product = Product.objects.get(id = uuid)
    img = product.category
    slovar = {"product": product, "img": img.image}
    return render(request, "product.html", slovar)

Notes:

(1) you should probably set ‘category’ to be ‘unique=True’ inside your Product model, if this is how you implement your model, as otherwise you may get unpredictable results if two ‘products’ have the same ‘category’.

(2) I would avoid using the names ‘productsHTML’ and ‘productHTML’ in your views and url config. The more standard naming convention would be ‘product_list’ and ‘product_detail’. HTML is handled solely by the templates in Django.

Answered By: KingRanTheMan
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.