0

Django 1.11. I have a model Article, and another model ReadArticles.

class Article(models.Model):
  name = models.CharField()
  length = models.IntegerField()

class ReadArticle(models.Model):
  user = models.ForeignKey(User)
  article = models.ForeignKey(Article)

I want to get a list of all articles which have not been read. I am already using Q:

length_filter = Q(length__lt=5000)
unread_articles = Article.objects.filter(length_filter).all()

How to I extend this to exclude all articles whose ID/User combination are in the read_articles table?

2
  • Are you looking for articles not read by current user, or not read by anyone? Commented Feb 21, 2019 at 14:29
  • Sorry for not being clear: yes, not read by the current user. Commented Feb 21, 2019 at 14:31

3 Answers 3

2

Since you haven't declared a customer related name, all what should be needed is .exclude:

Article.objects.filter(length__lt=5000).exclude(readarticle__user=request.user)
Sign up to request clarification or add additional context in comments.

5 Comments

Did it list choices in the exception?
@GluePear that's not possible with the models you've shown us. "To refer to a “reverse” relationship, just use the lowercase name of the model." (see this)
Yes, it lists id, name and length
This is the correct answer, unless your models aren't exactly defined as you're showing us.
@dirkgroten True, I simplified my models
1

Try the following query, substituting a user object for <USER TO FILTER FOR>:

Article.objects.exclude(id__in=[ra.article.id for ra in ReadArticle.objects.filter(user=<USER TO FILTER FOR>)])

2 Comments

id__in=[ra.article.id for ra in ....] is a bit easier than the double loop. But this will make two queries to the database rather than a single query.
You could also use .values("id") to skip the list comprehension, or probably id__in=Subquery(ReadArticle.objects.filter(user=<user>).values("id")) could work as well.
-1

You can exclude Article has referred ReadArticle objects with current user.

Article.objects.filter(
    length__lt=5000,
).exclude(
    readarticle__user=current_user,
)

6 Comments

This would only work if readarticle were a field in Article, right? Or at least that's what my error message is telling me.
No, readarticle is a ReadArticle class reference, so it check if there any ReadArticle models that is connected to Article for this queryset it shows only Article with no ReadArticle references.
this doesn't work because Article has no attribute user
Fixed it. Please see change version.
@dirkgroten you are right, I think the only way is to exclude Article with ReadArcticle with current user.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.