Sort Django query result by number of matches - python

In my Django app, I have Blogs and BlogPosts.
Their models are basically this:
class Blog(models.Model):
name = models.CharField(Entry)
details = models.TextField()
...
class BlogPost(models.Model):
blog = models.ForeignKey(Blog)
title = models.CharField()
...
Given a list of blog names, I would like to return all of the BlogPosts that appear in at least one of the given blogs.
I've figured out how to do this using Q objects. I've created a query like this:
# Return blogs that appear in either nameOfBlog1 or nameOfBlog2
q1 = Q(blog__name = nameOfBlog1)
q2 = Q(blog__name = nameOfBlog2)
Blog.objects.filter(q1 | q2)
This works.
However, I would like to receive the results in the order of the BlogPosts that match the highest number of Blogs. So for example, the BlogPosts that appear in all of the Blogs I'm searching against, should appear first in the list, while BlogPosts that only appear in one of the Blogs should appear at the end.
Is there any way to do this in Django?

try this:
BlogPost.objects.filter(q1 | q2).annotate(blog_times=Count('id')).order_by('blog_times')

Related

Excluding existed users in the ManyToManyField

I am building a small BlogApp and I build a feature of adding favorite users. User can search and add the user in his favorite users list
I am now building a feature if searched user is already in another's users favorite user list then exclude the user from the result
For example :- If user_1 added user_50 in his favorite user's list. and then if user_2 searched user_50 then it will not show in the search list.
BUT when i try to exclude then it is not excluding.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,unique=True)
full_name = models.CharField(max_length=100,default='')
friends = models.ManyToManyField("Profile",blank=True)
email = models.EmailField(max_length=60,default='')
class FavouriteUsers(models.Model):
adder = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
favouriteUser = models.ManyToManyField(User, related_name='favouriteUser', blank=True)
views.py
def search_users_favourite(request):
q = request.GET.get('q')
exclude_this = FavouriteUsers.objects.filter(favouriteUser=request.user)
results = Profile.objects.filter(user__username__icontains=q).exclude(exclude_this)
serialized_results = []
for result in results:
serialized_results.append({
'id': result.id,
'username': result.user.username,
})
return JsonResponse({'results': serialized_results})
BUT this is showing :-
TypeError: Cannot filter against a non-conditional expression.
I have tried many times but it is still that error.
Any help would be Appreciated.
Thank You in Advance.
Try this query:
Profile.objects.filter(user__username__icontains=q, user__favouriteUser__isnull=True)
This will exclude all profiles that are already mapped in FavouriteUsers (already has been a favorite)
I think you should be doing it this way
exclude_this = FavouriteUsers.objects.filter(favouriteUser=request.user).values_list('favouriteUser__username',flat=True)
results = Profile.objects.filter(user__username__icontains=q).exclude(user__username__in=exclude_this) here, i assume you want to exclude usernames matching the entire name.
For a better answer, please attach the log of the error.
I spent hours tearing my hair out over this issue, so I wanted to post a quick response here on what is actually causing this exception:
The problem is this (pseudo code):
query = Model.objects.filter(something=value)
result = Model.objects.filter(query).first()
This won't work (apparently). Django hates it big time.
The problem is that you can't pass a QuerySet to filter or exclude.
Instead, use your QuerySet directly:
query = Model.objects.filter(something=value)
result = query.first()

Making a complicated query in Django all my follows posts

Imagine that:
I have "Posts", "Users", "UserFollowUser" models in a Django app...
I want to get all the POSTS from my POST model but only for people that I FOLLOW.
Every POST has a USER id of the user who is the author.
I mean, there's a register that says:
"Cris" follows "Larry"
I want to get the posts from Larry and some other people I follow.
I tried:
follows = UserFollowUser.objects.get(follower = request.user) #I AM request.user
posts = Post.objects.filter(user = follows.followed).order_by('-id')
But I can only get posts from ONE person because of the "GET" function in objects object.
What you need to do is get an array of user ids for your followers. Then use the __in syntax to make a query where you are asking for all posts whose user id is in the set of user ids of your followers. The code would look something like this:
follower_user_ids = UserFollowUser.objects.filter(follower__user_id = request.user.id)\
.values_list('follower__user_id', flat=True)\
.distinct()
posts = Post.objects.filter(user_id__in=follower_user_ids)
*this assumes UserFollowUser.follower is a foreign key to the User table.
This is code if you want to show posts of all users logged in user follows also your own posted posts in the feed:
follows_users = user.profile.follows.all()
follows_posts = Post.objects.filter(author_id__in=follows_users)
user_posts = Post.objects.filter(author=user)
post_list = (follows_posts|user_posts).distinct().order_by('-date_posted')
You can always take reference for social media django clone from https://github.com/uttampatel007/nccbuddy

Querying multiple tables in Django

I'm beginner in Django and Python, I started developing survey app. It's based on https://github.com/jessykate/django-survey
I added few features, but I'm having problem with results page, to be more precisely how to
get data to present them. Here's what models with most important fields look like:
class Survey(models.Model):
name = models.CharField(max_length=250)
class Question(models.Model):
text = models.TextField()
survey = models.ForeignKey(Survey)
choices = models.TextField()
class Response(models.Model):
survey = models.ForeignKey(Survey)
class AnswerBase(models.Model):
question = models.ForeignKey(Question)
response = models.ForeignKey(Response)
class AnswerText(AnswerBase):
body = models.TextField(blank=True, null=True)
class AnswerRadio(AnswerBase):
body = models.TextField(blank=True, null=True)
and few more Answer..
I think data in this format would be good to process later in js and display as bar char:
results = [{'some_question_text':
[{'answer':'answer1','count': 11},{'answer':'answer2','count': 6}, ..]}
,..]
I could't came up how to do it in django way, so i tried in sql. Problem is, it works only with one answer type, when I add another condition like 'or ab.id==polls_answerselect.answerbase_ptr_id' query returns strange results.
Here's what I've done:
cursor = connection.cursor()
cursor.execute("select q.text as qtext, ar.body as ans, ab.id as Aid, q.id as Qid, count(ar.body) as count \
from polls_answerbase ab, polls_answerradio ar, polls_question q, polls_survey s \
where ab.id==ar.answerbase_ptr_id \
and ab.question_id==q.id \
and s.id==q.survey_id \
group by ar.body")
rows = dictfetchall(cursor)
result = {}
for r in rows:
res[r['qtext']] = []
res[r['qtext']].append({'ans': r['ans'], 'count': r['count']})
What is better and correct way to solve my problem?
It looks like what you want here is a question list filtered by survey, and you want it in json format.
Take a look at http://django-rest-framework.org/ It comes with a set of predefined class based views that support multiple response formats, json being one of them. The tutorial on that site walks you through setting it up, and uses simple tests along the way to verify you're doing it right. You can do something similar for your models.
I'm a Python/Django beginner as well and found it very easy to pick up.

How to delete a many to many object without deleting all objects within the relationship?

In models.py I have...
class Siteinfo(models.Model):
url = models.CharField(max_length=100)
description = models.TextField()
class Makesite(models.Model):
sitename = models.CharField(max_length=100, unique = True)
siteinfo = models.ManyToManyField(Siteinfo)
ref_id = models.ManyToManyField(RefID)
def __unicode__(self):
return u'%s' %(self.sitename)
I'm trying to delete a instance of description and replace it with another instance and still have it be associated with the same url and still be the many to many object under say. Group on.
So group1 is the site name. to create the relation I have
url = request.POST['url']
description = request.POST['description']
datsite = Makesite.objects.get(sitename=site)
datsite.siteinfo.add(Siteinfo.objects.create(url=url,description=description))
But then when I try to delete and replace the description with this bit of code it also deletes the url.
name = Makesite.objects.get(sitename=site).siteinfo.values_list('description',flat=True)[0]
Makesite.objects.get(sitename=site).siteinfo.get(description=name).delete()
I guess I could try to write some code that could get around this problem but I'd rather find a way to just delete one and add another instance in its place.
Just to be picky, you should be using forms for processing user input.
It sounds like you want to be updating an instance, not deleting and adding one nearly exactly the same.
site_info = Makesite.objects.get(sitename=site).siteinfo.get(description=name)
site_info.description = "new description"
site_info.save()
Or, more simply:
site_info = Siteinfo.objects.get(makesite__sitename=site, description=name) # only 1 query
site_info.description = "new description"
site_info.save()

How to query datastore when using ReferenceProperty?

I am trying to understand the 1-to-many relationships in datastore; but I fail to understand how query and update the record of a user when the model includes ReferenceProperty. Say I have this model:
class User(db.Model):
userEmail = db.StringProperty()
userScore = db.IntegerProperty(default=0)
class Comment(db.Model):
user = db.ReferenceProperty(User, collection_name="comments")
comment = db.StringProperty()
class Venue(db.Model):
user = db.ReferenceProperty(User, collection_name="venues")
venue = db.StringProperty()
If I understand correctly, the same user, uniquely identified by userEmail can have many comments and may be associated with many venues (restaurants etc.)
Now, let's say the user az#example.com is already in the database and he submits a new entry.
Based on this answer I do something like:
q = User.all()
q.filter("userEmail =", az#example.com)
results = q.fetch(1)
newEntry = results[0]
But I am not clear what this does! What I want to do is to update comment and venue fields which are under class Comment and class Venue.
Can you help me understand how this works? Thanks.
The snippet you posted is doing this (see comments):
q = User.all() # prepare User table for querying
q.filter("userEmail =", "az#example.com") # apply filter, email lookup
- this is a simple where clause
results = q.fetch(1) # execute the query, apply limit 1
the_user = results[0] # the results is a list of objects, grab the first one
After this code the_user will be an object that corresponds to the user record with email "az#example.com". Seing you've set up your reference properties, you can access its comments and venues with the_user.comments and the_user.venues. Some venue of these can be modified, say like this:
some_venue = the_user.venues[0] # the first from the list
some_venue.venue = 'At DC. square'
db.put(some_venue) # the entry will be updated
I suggest that you make a general sweep of the gae documentation that has very good examples, you will find it very helpful:
http://code.google.com/appengine/docs/python/overview.html
** UPDATE **: For adding new venue to user, simply create new venue and assign the queried user object as the venue's user attribute:
new_venue = Venue(venue='Jeferson memorial', user=the_user) # careful with the quoting
db.put(new_venue)
To get all Comments for a given user, filter the user property using the key of the user:
comments = Comment.all().filter("user =", user.key()).fetch(50)
So you could first lookup the user by the email, and then search comments or venues using its key.

Categories

Resources