0

Currently using the Tango with Django book for reference. I have a bunch of products in my database in categories which are referenced with Foreign Key relationships. I seem to have an issue with returning the product view, which houses all the information about that particular product.

Example: There are two Dell laptops, one iPhone, and two iPads in the database. The product information will be returned for the iPhone, but for the iPads and the Dell laptops, it will return the message "get() returned more than one Product -- it returned 2!" which of course means that it's found two products with similar matching names. I've tried changing the name__icontains to name__iexact in the def product_view but then it stops working completely, am I missing something very obvious? As it feels like I am.

    url(r'^products/(?P<category_name_url>\w+)/$', views.category_view, name='category_view'),
    url(r'^products/(?P<category_name_url>\w+)/(?P<product_name_url>\w+)', views.product_view, name='product_view')

def category_view(request, category_name_url):
    context = RequestContext(request)

    category_list = Category.objects.order_by('name')
    category_name = category_name_url.replace('_', ' ')
    context_dict = {'category_name': category_name,
                    'categories': category_list}

    try:
        category = Category.objects.get(name__iexact=category_name)
        product = Product.objects.filter(category=category)

        context_dict['product'] = product
        context_dict['category'] = category

    except Category.DoesNotExist:
        pass

    return render_to_response('category_view.html', context_dict, context)

def product_view(request, category_name_url, product_name_url):
    context = RequestContext(request)

    category_list = Category.objects.order_by('name')
    category_name = category_name_url.replace('_', ' ')
    product_name = product_name_url.replace('-', ' ')
    context_dict = {'category_name': category_name,
                    'product_name': product_name,
                    'categories': category_list}

    try:
        category = Category.objects.get(name__iexact=category_name)
        product = Product.objects.get(name__icontains=product_name)
        context_dict['category'] = category
        context_dict['product'] = product

    except Product.DoesNotExist:
        pass

    return render_to_response('product_view.html', context_dict, context)

2 Answers 2

2

I've tried changing the name_icontains to name_iexact in the def product_view but then it stops working completely, am I missing something very obvious?

That might be because product name that you searched does not exactly match with the one stored.

If you want to do approximation/fuzzy search you can use __icontains(), but use only one search result.

Sample code:

try:
        category = Category.objects.get(name__iexact=category_name)
        #use .filter()
        product = Product.objects.filter(name__icontains=product_name)[0]
        context_dict['category'] = category
        context_dict['product'] = product

    except IndexError:
        #product does not exists
        pass
Sign up to request clarification or add additional context in comments.

4 Comments

Ahh brilliant, it seems to work but say I have two products named iPhone 5c and iPhone 5s, clicking on the 5c will take me to the 5c page, but clicking on the 5s page will take me to the 5c page. I've run some queries directly from the shell, such as Product.objects.filter(name__icontains="iphone 5c") Product.objects.filter(name__iexact="iphone 5c") Product.objects.filter(slug__iexact="iphone-5c")
All of these return iPhone 5c, and if I just define "iPhone" it returns all of them. The URL being passed through (I assume) is iphone-5c which should return iPhone 5c or iPhone 5s respectively, but if I specify the query as slug__iexact it doesn't return anything.
@user2942863, If you want to exact match use name__iexact, but make sure the string you are querying exactly matches with field you are searching against.
Thanks for the advice. It was weird because when I ran the queries in the terminal, they were returning the correct objects. Turned out to be a missing hyphen in the URL mapping regular expression, so hyphens were being ignored. Not sure if I should be surprised it was that simple but ah well! Lesson learnt. Thanks again.
1

So I'm assuming you want more than one product as you have more than one match with your query. "Get" expects to only grab one matching item. If you want both items to iterate through them, than drop the get and use filter. this will return an iterable set of objects you can parse through in your template or view.

if you have a list of iterable objects;

{% for i in product_match_list %}
{{ i.foreign_key_name.foreign_key_attribute }}
{% endfor %}

if you have one object returned by get;

{{ object_variable_name.foreign_key_name.foreign_key_attribute }}

Comments

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.