Django Comparing user's list - django

I have a like feature which allows students to like in other pictures.
def LikePicture(request,picture_id):
p = Picture.objects.get(pk=picture_id)
new_like, created = Like.objects.get_or_create(user=request.user, picture_id=picture_id)
return HttpResponseRedirect(reverse('world:Boat', kwargs={'animal_id': the_id }))
At the moment , I'm trying to implement a restriction toward the people who likes a particular picture.
I want only the people who are friends with a particular users to like their's picture and the only way
I can do this is by implementing a friend models.
2 Users can only be friends if both users add each other.
I'm planning to use this friendship models unless someone has a better friendship models that we can both use to implement the restriction.
class Friendship(models.Model):
from_friend = models.ForeignKey(User, related_name='friend_set')
to_friend = models.ForeignKey(User, related_name='to_friend_set')
def __unicode__(self):
return u'%s, %s' % (
self.from_friend.username,self.to_friend.username)
class Meta:
unique_together = (('to_friend', 'from_friend'), )
We can bulid a relationship with
>>> user1 = User.objects.get(id=1)
>>> user2 = User.objects.get(id=2)
>>> friendship1 = Friendship(from_friend=user1, to_friend=user2)
>>> friendship1.save()
>>> user1.friend_set.all()
[<Friendship: user1, user2>, <Friendship: user1, user3>]
but inorder to become friends . the other users has to add the other users.
>>> friendship3 = Friendship(from_friend=user2, to_friend=user1)
>>> friendship3.save()
>>> user2.friend_set.all()
[<Friendship: user2, user1>]
Now , The problem is how can we edit the like function so it would only allows friends to like a picture.
I have thought of a way but I couldn't find a way to implement it into my like function. My idea is because we can grab the User object who own the picture and the guy who's trying to like the picture . We can compare each other friendlist .
We get the user object who own the picture and we get the user object whose trying to like the picture.We then compare if the user who's own the picture has the user who's trying to like his picture on his friendlist >>> user1.friend_set.all()
and we do it in reverse . If the user owner's picture is inside the request.user friendlist .Allow Like!!! .
So it's like , if both users have each other in the same friendlist . Allow like!!!
It would be something similar to this function
def Like(request,picture_id):
user1 = User.objects.get(user=request.user) # The Guy who trying to like the picture
p = Picture.objects.get(pk=picture_id)
user2 = User.objects.get(picture=p) # The owner of the picture
if user1 is in user2.friend_set.all() AND if user2 is in user1.friend_set.all():
new_like, created = Like.objects.get_or_create(user=request.user, picture_id=picture_id)
else:
message ('You can only like if you are an friend ')
return HttpResponseRedirect(reverse('world:Boat', kwargs={'animal_id': the_id }))
return HttpResponseRedirect(reverse('world:Boat', kwargs={'animal_id': the_id }))
Or we can compare Users object
>>> [friendship.to_friend for friendship in
user1.friend_set.all()]
[<User: user2>, <User: user3>]

Little bit improvement required:
class FriendshipManager(models.Manager):
def is_friends(self, user_a, user_b):
if self.get_query_set().filter(
user__id=user_a.id, friend__id=user_b.id, is_accepted=True).exists() or \
self.get_query_set().filter(
user__id=user_b.id, friend__id=user_a.id, is_accepted=True).exists():
return True
else:
return False
class Friendship(models.Model):
user = models.ForeignKey(User)
friend = models.ForeignKey(User, related_name='friends')
is_accepted = models.BooleanField(default=False)
objects = FriendshipManager()
def __unicode__(self):
return u'%s, %s' % (
self.user.username, self.friend.username)
class Meta:
unique_together = (('user', 'friend'), )
def Like(request, picture_id):
user = request.user
p = get_object_or_404(Picture, pk=picture_id)
pic_owner = p.user # i hope you have user relationship with pic here
if Friendship.objects.is_friends(user, pic_owner) \
pic_owner.id == user.id:
# if the pic owner and requested user are friends
# or user is liking his own pic
new_like, created = Like.objects.get_or_create(
user=user, picture=p)
else:
message ('You can only like if you are friends')
return HttpResponseRedirect(
reverse('world:Boat', kwargs={'animal_id': the_id }))
return HttpResponseRedirect(
reverse('world:Boat', kwargs={'animal_id': the_id }))
Added is_accepted field to make sure other person approved the friend request.
Added is_friendsmethod in manager which will be used to check if two users are friends.
In view also checked if requested user and picture owner are same then it means user can like its own posted picture. This code is untested but I hope this will serve you well.

Related

getting the followers from a list of userID using twepy

userID = "#niveakalmar" <- I wanna have a list of users here and scrape all the followers of which one
user = api.get_user(userID)
for friend in user.friends():
print(friend.screen_name)
followers and friends are different endpoints
this is the followers: you can adapt for freinds by changing followers to friends
def get_follower_list(num_followers, id):
follower_list = []
for follower in tweepy.Cursor(api.followers, id).items(num_followers):
follower_list.append(follower.screen_name)
return follower_list
# get initial list of followers
num_followers = 5
user_list = ['GEODIS_Group']
for user_handle in user_list:
# print(user_handle)
followers = get_follower_list(num_followers, user_handle)
print(followers)

Returning array of deleted objects in single GraphQL mutation (graphene-django)

While in the past I used a GraphQL mutation that deletes a single record, I came up with the idea that this is not ideal in the case I want to delete several records at once since it ended up by calling the mutation that delete 1 record several times (in a loop) which results in several API call over the network.
So I decided to instead modify the mutation to accept has an argument a list of objects or IDs (whatever) on which I can loop in the backend. By doing this, it does only 1 call to the API with all the records to delete.
I managed to do it and the only blocking point that I face is the return statement. I couldn't figure out how to write it.
So if I have a model (in my schema) such as :
class UserType(DjangoObjectType):
class Meta:
model = User
fields = (
'id',
'username',
'password',
'first_name',
'last_name',
'is_active',
'group_ids',
)
full_name = graphene.String()
full_identification = graphene.String()
In the past I used :
class DeleteUser(graphene.Mutation):
username = graphene.String()
class Arguments:
id = graphene.ID()
def mutate(self, info, **kwargs):
user = get_object_or_404(User, id=kwargs['id'])
user.delete()
return user
class Mutation(graphene.ObjectType):
delete_user = DeleteUser.Field()
But now I want to do something such as :
class DeleteUsers(graphene.Mutation):
users = graphene.List(UserType)
username = graphene.String()
class Arguments:
ids = graphene.List(graphene.ID)
def mutate(self, info, **kwargs):
deleted_users = []
for user in User.objects.filter(id__in=kwargs['ids']):
user.delete()
deleted_users.append(user)
return deleted_users
class Mutation(graphene.ObjectType):
delete_users = DeleteUsers.Field()
You can see in the mutate(..) method of DeleteUsers class that I try to return the deleted_users to be able to do something like : "Users X, Y and Z have been deleted" in the frontend.
But I haven't been able to retrieve the data of the users. How can I achieve it ? Maybe I'm missing something.
Currently the GraphQL query I tried for that is :
mutation {
deleteUsers(
ids: [5,6,7],
) {
users {
username
}
}
}
but it doesn't work, saying users is null... Don't know how I could retrieve the users in the query.
Thanks in advance.
Well I finally figured out what was the problem (seems talking about a problem solves it, next time I'll try with a plastic duck).
While the deleted_users was a correct list with the Users, the ouput type of my mutation wasn't set.
So the solution is to add :
class Meta:
output = graphene.List(UserType)
in my mutation
which results in :
class DeleteUsers(graphene.Mutation):
class Arguments:
ids = graphene.List(graphene.ID)
class Meta:
output = graphene.List(UserType)
def mutate(self, info, **kwargs):
deleted_users = []
for user in User.objects.filter(id__in=kwargs['ids']):
user.delete()
deleted_users.append(user)
return deleted_users
Which can be called with the following :
mutation {
deleteUsers(
ids: [5,6,7],
) {
username
firstName
# ...
# And other fields ...
# ...
}
}

Django how to annotate count nested forloop queryset dictionary

Good Day,
My Problem is:
my project depending on giving points to users who make any actions like (post, comment, favorite, likes ......).
So, in users list page i want to list all users and other data for each user (name, points, badges, ....)
to give the users points i have to count his posts, comments, likes, and so on.....
i tried several methods and ways but all is failed to get annotate or prefetch_related or select_related
Models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
Views.py
def user_list(request):
users = User.objects.all()
template = 'user/users_list.html'
nested_posts = {}
for user in users:
posts = user.posts.all()
nested_posts[user, posts] = posts.count()
print("nested : ", nested_posts)
context = {
'users': users,
'user':user,
'posts': posts,
'nested_posts': nested_posts,}
return render(request, template, context)
when i print nested .. i found the count of every user' posts .. but how can i make it as variable to re-use in calculated field
QuerySet
nested : {(<User: Fareed>, <QuerySet [<Post: Senior Purchasing Specialist>]>): 1,
(<User: Hussein>, <QuerySet [<Post: Senior Software Development Engineer in Test>]>): 1,
(<User: Karima>, <QuerySet []>): 0,
(<User: Yahia>, <QuerySet []>): 0}
and i also tried :
GetUserID = User.objects.get(id=2)
var01 = GetUserID.posts.all().count()
but this was for one user with (id=2) .. and sure all users got the total posts of user(id=2) not for each of them.
and i also tried :
Posts_count_per_user = User.posts.annotate(posts_count=Count('posts'))
User_Score_of_posts = Posts_count_per_user.aggregate(posts_score=Count('posts_count') * 1000)
but i got this error:
'ReverseManyToOneDescriptor' object has no attribute 'annotate'
any suggestions please ...
Thanks in advance,
Have you tried this,
user_qs = User.objects.annotate(posts_count=Count('posts'))
# usage
for user_instance in user_qs:
print("post count: ", user_instance.posts_count)
print("post score: ", user_instance.posts_count * 1000)
Or you can annotate the post score in the DB level itself,
from django.db.models import F, Count
user_qs = User.objects.annotate(posts_count=Count('posts'), posts_score=F('posts_count') * 1000)

How to write python-django queries which is ultimately going to call these queries from django

I want to write all types of complex queries,
for example :
If someone wants information "Fruit" is "Guava" in "Pune District" then they will get data for guava in pune district.
htt//api/?fruit=Guava&?district=Pune
If someone wants information "Fruit" is "Guava" in "Girnare Taluka" then they will get data for guava in girnare taluka.
htt://api/?fruit=Guava&?taluka=Girnare
If someone wants information for "Fruit" is "Guava" and "Banana" then they will get all data only for this two fruits, like wise
htt://api/?fruit=Guava&?Banana
But, when I run server then I cant get correct output
If i use http://api/?fruit=Banana then I get all data for fruit which is banana, pomegranate, guava instead of get data for fruit is only banana. So I am confuse what happen here.
can you please check my code, where I made mistake?
*Here is my all files
models.py
class Wbcis(models.Model):
Fruit = models.CharField(max_length=50)
District = models.CharField(max_length=50)
Taluka = models.CharField(max_length=50)
Revenue_circle = models.CharField(max_length=50)
Sum_Insured = models.FloatField()
Area = models.FloatField()
Farmer = models.IntegerField()
def get_wbcis(fruit=None, district=None, talkua=None, revenue_circle=None, sum_insured=None, area=None,min_farmer=None, max_farmer=None, limit=100):
query = Wbcis.objects.all()
if fuit is not None:
query = query.filter(Fruit=fruit)
if district is not None:
query = query.filter(District=district)
if taluka is not None:
query = query.filter(Taluka=taluka)
if revenue_circle is not None:
query = query.filter(Revenue_circle= revenue_circle)
if sum_insured is not None:
query = query.filter(Sum_Insured=sum_Insured)
if area is not None:
query = query.filter(Area=area)
if min_farmer is not None:
query = query.filter(Farmer__gte=min_farmer)
if max_farmer is not None:
query = query.filter(Farmer__lt=max_farmer)
return query[:limit]
Views.py
class WbcisViewSet(ModelViewSet):
queryset = Wbcis.objects.all()
serializer_class = WbcisSerializer
def wbcis_view(request):
fruit = request.GET.get("fruit")
district = request.GET.get("district")
taluka = request.GET.get("taluka")
revenue_circle = request.GET.get("revenue_circle")
sum_insured = request.GET.get("sum_insured")
area = request.GET.get("area")
min_farmer = request.GET.get("min_farmer")
max_farmer = request.GET.get("max_farmer")
wbcis = get_wbcis(fruit, district, taluka,revenue_circle,sum_insured,area, min_farmer, max_farmer)
#convert them to JSON:
dicts = []
for wbci in wbcis:
dicts.append(model_to_dict(wbci))
return JsonResponse(dicts)
Serializers.py
from rest_framework.serializers import ModelSerializer
from WBCIS.models import Wbcis
class WbcisSerializer(ModelSerializer):
class Meta:
model = Wbcis
fields=('id','Fruit','District','Sum_Insured','Area','Farmer','Taluka','Revenue_circle',)
whats need changes in this code for call these queries to get exact output?
I don't think that you're actually calling that view, judging by your usage I presume you're calling the viewset itself and then ignoring the query params.
You should follow the drf docs for filtering but essentially, provide the get queryset method to your viewset and include the code you currently have in your view in that
class WbcisViewSet(ModelViewSet):
queryset = Wbcis.objects.all() # Shouldn't need this anymore
serializer_class = WbcisSerializer
def get_queryset(self):
fruit = self.request.query_params.get("fruit")
....
return get_wbscis(...)

StringField is defined as unique, but duplicates are saved silently

I defined a simple Document, like this:
class Company(Document):
screen_name = StringField(max_length=100, required=True, unique=True)
official_name = StringField(required=False)
meta = {
'indexes': [{'fields': 'screen_name', 'unique': True}]
}
but when I am writing a test
#use_tdb
def test_company3():
""" test company2 """
company = Company(screen_name='asdasd')
company.save()
company = Company(screen_name='asdasd')
with nt.assert_raises(OperationError):
company.save()
pprint([(x.id, x.screen_name,) for x in Company.objects.all()])
It actually saves both of them. And I see in output:
[(ObjectId('4f719f915c121a21ad000003'), u'asdasd'),
(ObjectId('4f719f915c121a21ad000004'), u'asdasd')]
Any ideas, what I've done wrong?
Thanks
That is may be required drop_collection.
def test_company3():
""" test company2 """
Company.drop_collection()
company = Company(screen_name='asdasd')
company.save()
company = Company(screen_name='asdasd')
with nt.assert_raises(OperationError):
company.save()
pprint([(x.id, x.screen_name,) for x in Company.objects.all()])
See this tests. Mongoengine is all tests is passed.
https://github.com/hmarr/mongoengine/blob/master/tests/document.py#L875
Mongoengine team Recently relaeed 0.6.3.