Attribute Error: 'QuerySet' object has no attribute 'name'

Question:

in my Django project, I have a list of items where users specify categories while submitting "Crate New Item" form. The default route shows this list of items with the title, description and category of the item. Users can click on each category to be redirected to that related category’s page where I’m trying to display all items under that category.

To do that, I want to check if the category submitted in the form is already in our Category database. If yes, the item should be added under the existing category’s page and if not, a new category should be created.

However, I get an attribute error while trying to check that in form submission and I’m stuck. Would appreciate any help.

AttributeError at /create
'QuerySet' object has no attribute 'name'
error line :  if category == all_categories.name: 

models.py:

class User(AbstractUser):
    pass

class Category(models.Model):
    name = models.CharField(max_length = 64, null = True)


class AuctionItem(models.Model):
    user = models.ForeignKey(User, on_delete = models.CASCADE, related_name = "created_by")
    title = models.CharField(max_length = 64)
    description = models.TextField()
    price = models.DecimalField(max_digits = 100 ,decimal_places = 2)
    image = models.URLField(blank = True)
    category = models.ForeignKey(Category, on_delete = models.CASCADE, related_name = "item_category")
    date = models.DateTimeField(auto_now_add = True)

urls.py:

urlpatterns = [
    path("", views.index, name="index"),
    path("login", views.login_view, name="login"),
    path("logout", views.logout_view, name="logout"),
    path("register", views.register, name="register"),
    path("create", views.create_listing, name="create"),
    path("listing/<int:listing_id>", views.listing, name = "listing"),
    path("<str:user>/watchlist", views.watchlist, name= "watchlist"),
    path("closed", views.closed, name = "closed"),
    path("category/<int:category_id>", views.category, name = "category")
]

views.py:

@login_required 
def create_listing(request):
    if request.method == "POST": #if the create listing form is submitted
        title = request.POST["title"] #get the provided title
        description = request.POST["description"] #get the provided description
        price = request.POST["price"] #get the provided price
        image = request.POST["image"] #get the provided image
        category = request.POST["category"] #get the provided category
    
        all_categories = Category.objects.filter(name = category)
    
        if category == all_categories.name:
            item = AuctionItem.objects.create( #create new auction item with given properties
                user = request.user,
                title = title,
                description = description,
                price = price,
                image = image,
                category = category
            )
        else:
            new_category = Category.objects.create(name = category)
            item = AuctionItem.objects.create( #create new auction item with given properties
                user = request.user,
                title = title,
                description = description,
                price = price,
                image = image,
                category = new_category
            )

        return HttpResponseRedirect(reverse("index")) #after submitting the form, redirect user to the main page

    return render(request, "auctions/create_listing.html")

def category(request, category_id):
    category = Category.objects.get(id=category_id)
    items = AuctionItem.objects.filter(category=category)
    return render(request, "auctions/category.html", {
        "items" : items,
        "name" : category.name
    })

category.html:

{% extends "auctions/layout.html" %}

{% block body %}
    <h2>Category: {{name}}</h2>
    {% for item in items %}
    <div class = "frame">
        {% if item.image %}
            <img src="{{item.image}}" style= "width: 15vw;">
        {% endif %}
        {% if user.is_authenticated %}
        <h4><a href="{% url 'listing' item.id %}">{{item.title}}</a></h4>
        {% else %}
        <h4>{{item.title}}</h4>
        {% endif %}
        <br>
        <div id="text"><strong>Starting Price:</strong> ${{item.price}}</div>
        <div id="text"><strong>Description:</strong> {{item.description}}</div>
        {% if item.category %}
        <div id="text"><strong>Category: </strong><a href="{% url 'category' item.category.id %}">{{ item.category.name }}</a></div>
        {% endif %}
        <br>
        <div id="created">Created by {{item.user}}, on {{item.date}}</div>
    </div>
    {% endfor %}

{% endblock %}
Asked By: user17470872

||

Answers:

This is the problem:

all_categories = Category.objects.filter(name = category)

filter() Returns a new QuerySet containing
objects that match the given lookup parameters.

You need to use one of these because there is no such data in your table.

# import Http404
from django.http import Http404

# try except logic
try:
    all_categories = Category.objects.get(name = category)
except Category.DoesNotExist:
    raise Http404("Given query not found....")

or

# import get_object_or_404()
from django.shortcuts import get_object_or_404

all_categories = get_object_or_404(Category, name = category)
Answered By: Shahab Rahnama

In your views.py file, You want to do a comparison name attribute on a list.

        all_categories = Category.objects.filter(name = category)
    
        if category == all_categories.name:

the all_categories is a list of category objects.
all_categories = [ object, object, object]

And when you want to compare it like this:

if category == all_categories.name:

The name attribute no longer exists for the all_categories = [ object, object, object].

you should check your category like this:

if Category.objects.filter(name=category).exists():
    ... use the exist category to relate you AuctionItem ...
else:
    ... create new category for relate your AuctionItem ...
Answered By: User12
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.