Home > other >  TypeError: 'ModelBase' object is not iterable when trying to use Exclude
TypeError: 'ModelBase' object is not iterable when trying to use Exclude

Time:06-15

I have the following two models:

class Listings(models.Model):
    CATEGORY = [
    ("Miscellaneous", "Miscellaneous"),
    ("Movies and Television", "Movies and Television"),
    ("Sports", "Sports"),
    ("Arts and Crafts", "Arts and Crafts"),
    ("Clothing", "Clothing"),
    ("Books", "Books"),
]
    title = models.CharField(max_length=64)
    description = models.CharField(max_length=500)
    bid = models.DecimalField(max_digits=1000000000000, decimal_places=2)
    image = models.URLField(null=True, blank=True)
    category = models.CharField(max_length=64, choices=CATEGORY, default=None)
    user = models.ForeignKey(User, on_delete=models.CASCADE, default="")

class CloseListing(models.Model):
    listings = models.ForeignKey(Listings, on_delete=models.CASCADE, default="")
    user = models.ForeignKey(User, on_delete=models.CASCADE, default="")

I want to be able to query through all the objects of every listing that is not in the CloseListing model. How can I do this?

I tried the code in the answer, and I am still not able to query through all the objects of every listing not in the CloseListing model. I think it might have to do with how I am saving the model. The following code is the part of the view that deals with the CloseListing model.

def index(request):
    listings = Listings.objects.all().exclude(id__in=CloseListing)
    return render(request, "auctions/index.html",{
        "listings": Listings.objects.all()
    })

error message: TypeError: 'ModelBase' object is not iterable because of listings = models.ForeignKey(Listings, on_delete=models.CASCADE, default="").

closeListing part of views.py

@login_required(login_url='login')
def listing(request, id):
    #gets listing
    listing = get_object_or_404(Listings.objects, pk=id)
    sellar = listing.user

    #close listing code
    if sellar == request.user:
        closeListingButton = True
    else: 
        closeListingButton = False
    closeListing = ''
    try:
        has_closed = get_list_or_404(CloseListing, Q(
            user=request.user) & Q(listings=listing))
    except:
        has_closed = False
    if has_closed:
        closeListing = False
    else: 
        closeListing = True

   if request.method == "POST":
       #close listing code
        if request.POST.get('close'):
          CloseListing.objects.create(user=request.user,
 listings=listing)
            closeListing = True
            closeListingButton = False
            add_or_remove_watchlist = True
            winning_bid = Bids.objects.aggregate(Max('bid'))
            winning_bid = Bids.objects.latest('bid')
            winner = winning_bid.user
            return render(request, "auctions/listing.html",{
                        "auction_listing": listing,
                        "comments": comment_obj,
                        "bids": bid_obj,
                        "closeListingButton": closeListingButton,
                        "closeListing": closeListing,
                        "closedMessage": "This listing is closed.",
                        "winner": winner
            })
            return render(request, "auctions/listing.html",{
                 "auction_listing": listing,
                 "closeListingButton": closeListingButton, 
                 "closeListing": closeListing
            })

CodePudding user response:

You should not query directly through model, which is CloseListing, you can first filter all close listings from CloseListing model then exclude all those listings which are in CloseListing by exclude().

views.py

def index(request):
    close_listings = CloseListing.objects.values('listings')
    listings=Listings.objects.exclude(id__in=close_listings)
    return render(request, "auctions/index.html",{
        "listings": listings
    })

I'd recommend you to add __str__ in Listing model as:

class Listings(models.Model):
    CATEGORY = [
        ("Miscellaneous", "Miscellaneous"),
        ("Movies and Television", "Movies and Television"),
        ("Sports", "Sports"),
        ("Arts and Crafts", "Arts and Crafts"),
        ("Clothing", "Clothing"),
        ("Books", "Books"),
    ]
    title = models.CharField(max_length=64)
    description = models.CharField(max_length=500)
    bid = models.DecimalField(max_digits=1000000000000, decimal_places=2)
    image = models.URLField(null=True, blank=True)
    category = models.CharField(max_length=64, choices=CATEGORY, default=None)
    user = models.ForeignKey(User, on_delete=models.CASCADE, default="")

    def __str__(self) -> str:
        return f'{self.title}'

By adding __str__ you would see instances title instead of objects.

  • Related