Horai Nuri
Horai Nuri

Reputation: 5578

Cannot query "user": Must be "Model" instance

I'm trying to filter users on my private user to user chat, I'm getting the buyer's username with a model (User) and the seller's username with another model (Profile).

The problem is that I don't understand how I can resolve this issue and why it occurs :

ValueError: Cannot query "user_39": Must be "Profile" instance.

On my view :

uc = userComment.objects.all().first()
users = userComment.objects.filter(Q(buyer=uc.buyer) | Q(seller=uc.seller)) #error occurs with this line

pdb.set_trace()

(Pdb) uc.seller
<Profile: user_39>
(Pdb) uc.buyer
<User: user_4>

Here are my two models.

class Profile(models.Model):
    name = models.CharField(max_length=120)
    user = models.OneToOneField(User, null=True, blank=True)

class userComment(models.Model):
    buyer = models.ForeignKey(User, related_name="buyer", null=True)
    seller = models.ForeignKey(Profile, related_name="seller", null=True)
    sent_at = models.DateTimeField(auto_now_add=True)
    comment = models.TextField(max_length=255, null=True)

On my models I don't want to change userComment.seller to ForeignKey(User, ...)

How can I resolve this issue ?


Full code as requested :

views.py

def addComment(request, gig_id):
    gig = Gig.objects.get(id=gig_id)
    uc = userComment.objects.all().first()
    users = userComment.objects.filter(Q(Q(buyer=uc.buyer) & Q(seller=uc.seller)) | Q(Q(buyer=uc.seller) & Q(seller=uc.buyer))).order_by('sent_at')

    if request.method == 'POST':
        form = userCommentForm(request.POST, request.FILES)
        if form.is_valid():
            form.save(buyer=request.user)
            return HttpResponseRedirect('../' + str(gig.id))
    ...

forms.py

class userCommentForm(forms.Form):
    seller = CommaSeparatedUserField(label=_(u"seller"))
    comment = forms.CharField(label=_(u"comment"), widget=forms.Textarea())

    def save(self, buyer):
        sellers = self.cleaned_data['seller']
        comment = self.cleaned_data['comment']
        message_list = []

        for seller in sellers:
            sl = Profile.objects.get(user=seller) #Connection made here.
            msg = userComment(buyer=buyer, seller=sl, comment=comment,)
            ...
        ...

PDB Debug

(Pdb) uc = userComment.objects.all().first()
(Pdb) print('Seller class: %s' % uc.seller.__class__.__name__)
Seller class: Profile
(Pdb) users = userComment.objects.filter(buyer_id=uc.buyer_id)
(Pdb) print(users.count())
3
(Pdb) users = userComment.objects.filter(seller_id=uc.seller_id)
(Pdb) print(users.count())
4
(Pdb) users = userComment.objects.filter(Q(seller_id=uc.seller_id) | Q(buyer_id=uc.buyer_id))
(Pdb) print(users.count())
4
(Pdb) users = userComment.objects.filter(buyer=uc.buyer)
(Pdb) print(users.count())
3
(Pdb) users = userComment.objects.filter(seller=uc.seller)

Upvotes: 5

Views: 12627

Answers (2)

2ps
2ps

Reputation: 15966

Update: Oh, that is very different code, it looks like your actual query is this:

userComment.objects.filter(Q(
    Q(buyer=uc.buyer) & Q(seller=uc.buyer)
) | Q(
    Q(buyer=uc.seller) & Q(seller=uc.buyer)
)).order_by('sent_at')

I would try:

userComment.objects.filter(Q(
    Q(buyer_id=uc.buyer_id) & Q(seller__user_id=uc.buyer_id)
) | Q(
    Q(buyer_id=uc.seller.user_id) & Q(seller__user_id=uc.buyer_id)
)).order_by('sent_at')

This is very odd, as your code seems fine from first glance. I would recommend trying the following code to debug the issue:

uc = userComment.objects.all().first()
print 'Seller class: %s' % uc.seller.__class__.__name__
users = userComment.objects.filter(buyer_id=uc.buyer_id)
print users.count()
users = userComment.objects.filter(seller_id=uc.seller_id)
print users.count()
users = userComment.objects.filter(Q(seller_id=uc.seller_id) | Q(buyer_id=uc.buyer_id))
print users.count()
users = userComment.objects.filter(buyer=uc.buyer)
print users.count()
users = userComment.objects.filter(seller=uc.seller)
print users.count()

Upvotes: 1

Shang Wang
Shang Wang

Reputation: 25559

In your model userComment you have seller as ForeignKey to Profile, but sounds like you want it to be on User:

class userComment(models.Model):
    buyer = models.ForeignKey(User, related_name="buyer", null=True)
    seller = models.ForeignKey(User, related_name="seller", null=True)

Edit:

Sorry I answered it too quickly, your error basically said: you queried with the criteria uc.buyer on both buyer field and seller field, but seller is defined as a foreign key to Profile, so you can't use a user object to query on Profile field. Maybe you want this instead?

users = userComment.objects.filter(Q(buyer=uc.buyer) | Q(seller=uc.seller))

ReEdit:

You should use User as foreign key seller for userComment because that's what a relationship looks like and you could get all information you need use the relations. With User as foreign key, you could do everything:

# get a user's profile
profile = user.profile
# query with profile's information on `userComment`
userComment.objects.filter(buyer__profile__name='Tom')

Check django doc on how to query across relationships.

Upvotes: 5

Related Questions