Is it possible to filter a queryset in custom manager to filter differently for different Users. I want one employee should have access to data in a particular range of dates only.
class UserWiseManager(models.manager)
.
.
class ItemsSold(models.Model):
date = model.DateField()
item = models.CharField(max_length=50)
objects = UserWiseManager()
You can pass User instance directly to the manager, like this:
class UserWiseQuerySet(models.QuerySet)
def for_user(self, user):
if user.is_anonymous():
return self.filter(date__gte=(now() - timedelta(days=1))
else:
return self
UserWiseManager = UserWiseQuerySet.as_manager()
class ItemsSold(models.Model):
date = model.DateField()
item = models.CharField(max_length=50)
objects = UserWiseManager()
def view(request):
items = ItemsSold.objects.for_user(request.user)
Related
so I have 4 models
class User(models.Model):
userID = models.CharField(pk = True)
......
class Producer(models.Model):
userID = models.OneToOneField('Users.User',on_delete=CASCADE,primary_key=True)
.....
class Buyer(models.Model):
userID = models.OneToOneField('Users.User',on_delete=CASCADE,primary_key=True)
.....
class Inventory(models.Model):
item_id = models.UUIDField(primary_key=True,auto_created=True,default=uuid.uuid4)
producerID = models.ForeignKey('Producers.Producer',on_delete=CASCADE)
.....
class Cart(models.Model):
userID = models.OneToOneField(Buyer, on_delete = CASCADE,primary_key = True)
last_updated = models.DateTimeField(auto_now = True)
class Cart_Item(models.Model):
cart_item_id = models.UUIDField(primary_key=True,auto_created=True,default= uuid.uuid4)
item_id = models.ForeignKey('Inventory.Inventory', on_delete= SET_NULL,null=True)
userID = models.ForeignKey(Cart,on_delete=CASCADE)
......
I then have a post-only view which processes all cart Items in order to create an order as follows
class PlaceOrderView(generics.CreateAPIView):
def post(self, request, *args, **kwargs):
user = request.user
cart = Cart_Item.objects.select_for_update().filter(userID = user).order_by('item_id__producerID')
order = {'producer':'',
'items': []
}
for item in cart:
if order['producer'] == item.values('item_id.producerID'):
order['items'].append(item)
else:
self.placeOrder(order)
order['producer'] = item.values('item_id.producerID')
order['items'] = []
order['items'].append(item)
def placeOrder(self,order):
with transaction.atomic():
#Business logic on order.
What Im trying to do is to group all cart Items by items owned by specific producers, and then place an order for that group of cart Items. Where I am having trouble is in accessing the nested field "producerID" of cart Item, which needs to be done in order to group all of my cart Items.
My placeOrder method, uses the cartItem object and so they are passed directly in the function. Currently I am serializing cart Items in the for loop just to compare the producerID's but this feels inefficient. I've read django documentation on the topic of fields, but there is not much support for nested fields. Some simple explanation on the topic would be great!
.values() is a queryset method, but since you are iterating the qs and working with each individual item you dont need it. If you have and Item you should be apple to access the fk relation
Have you tried:
order['producer'] = item.itemId.producerID
My project is a social networking site that can send requests to friends and make friends.
I have extended django's existing user model using oneToone field .
So far i've been able to do the above said thing but when ever a user accepts the request , Both the user who sent request and also the user accepted it must increment a value in their extended user model which stores the value of their friends count .
I'm facing difficulties trying to solve this .
I've also used signals but it doesn't work .
Here is my code:
models.py:
class Friends(models.Model):
"""Model for saving relationship of user and friends"""
request_id = models.ForeignKey(User,on_delete=models.CASCADE,related_name='current_user')
friend_id = models.ForeignKey(User,on_delete=models.CASCADE,related_name='user_friend')
created_on = models.DateTimeField(auto_now_add=True,auto_now=False)
class Meta:
verbose_name_plural = "Friends"
def __str__(self):
return str(self.friend_id)
class Profile(models.Model):
user = models.OneToOneField(User,related_name='profile',on_delete=models.CASCADE)
location = models.CharField(max_length=30,blank=True)
friends_count = models.PositiveIntegerField(default=0)
profile_pic = models.ImageField(upload_to='profile_pics/',blank=True,null=True)
def natural_key(self):
return (self.user.username,)
signals.py:
#receiver(post_save,sender=Friends)
def update_friends_count(sender,instance,created,**kwargs):
if created:
user_profile = Profile(user = instance.request_id)
user_profile.friends_count=F('friends_count')+1
user_profile.save()
Any help would be greatly appreciated!!!!! Thank you in advance!!!
You were initializing a new instance of Profile every time a friend is made. Instead you can use get_or_create to generate a profile or retrieve the one associated with that id. Next, you want to update both users so fetch the other update the counts and save.
#receiver(post_save,sender=Friends)
def update_friends_count(sender,instance,created,**kwargs):
if created:
user_profile, profile_created = Profile.objects.get_or_create(user = instance.request_id)
user_profile.friends_count=F('friends_count')+1
user_profile.save()
friend_profile, profile_created = Profile.objects.get_or_create(user = instance.friend_id)
friend_profile.friends_count=F('friends_count')+1
friend_profile.save()
With Q filter and update
Profile.objects.filter(
Q(user=instance.request_id) |
Q(user=instance.friend_id)
).update(
friends_count=F('friends_count')+1
)
This last query uses the django.db.models Q object to make an SQL OR statement to retrieve the two profile instances; that of the requested and the requester: the update call acts on the query and updates all instances in the list
Given I have:
class Publisher(Model):
pass
class Author(Model):
name = models.CharField(...)
publisher = models.ForeignKey(Publisher)
is_alive = models.BooleanField(...)
objects = models.Manager() # Default Manager
alives = AliveManager() # Custom Manager
Right now I can filter using:
Publisher.objects.filter(author__name='xxx', author__is_alive=True)
My question is there anyway to take advantage of a custom reverse manager in the filter statement?
publisher.author_set(manager="alives")
gives me this for a given publisher.
I guess this is the relevant bit in the docs:
[...] default filtering in its get_queryset() method, that filtering would apply to the all() call.
class AliveManager(Manager):
def get_queryset(self):
qs = super(AliveManager, self).get_queryset()
return qs.filter(is_alive=True)
class Author(Model):
name = models.CharField(...)
publisher = models.ForeignKey(Publisher)
is_alive = models.BooleanField(...)
objects = models.Manager() # Default Manager
alives = AliveManager() # Custom Manager
# returns all alive authors
publisher.author_set(manager='alives').all()
# filters through alive authors
publisher.author_set(manager='alives').filter(author__name='xxx')
I want to make a custom manager for my models stored in my database 'db2' so that i don't have to do model.objects.using('db2').all().
The code for my models and custom manager is
class ViewerProfileManager(models.Manager):
def get_query_set(self):
return super(ViewerProfileManager,self).using('db2').get_query_set() # results in recursion error
class ViewerProfile(models.Model):
name = models.CharField(max_length=32)
count = models.IntegerField(blank=True,null=True)
objects = models.Manager()
profiles = ViewerProfileManager()
-------------
>>> ViewerProfile.profiles.all() # maximum recursion depth exceeded error
What's wrong with what i am doing here and how to make it work?
SOLUTION : If you just want to use another database 'db2' for every query just use this
class ViewerProfile(models.Model):
name = models.CharField(max_length=32)
count = models.IntegerField(blank=True,null=True)
objects = models.Manager()
profiles = objects.db_manager('db2') # manager for evaluating querysets on database db2
Later on if you want to add custom querysets override objects manager by making a class inheriting from models.Manager and define your querysets in it.
You can call the method on the parent (using super()) or do the appropriate handling of the _db attribute on the manager (a string containing the name of the database to use).
If you want to return a custom QuerySet class from the get_query_set method :
class ViewerProfileManager(models.Manager):
def get_query_set(self):
qs = CustomQuerySet(self.model)
if self._db is not None:
qs = qs.using(self._db)
return qs
or use this:
class ViewerProfileManager(models.Manager):
using="db"
def get_query_set(self,request):
return super(ViewerProfileManager,self).queryset(request).using(self.using)
class ViewerProfile(models.Model):
name = models.CharField(max_length=32)
count = models.IntegerField(blank=True,null=True)
objects = models.Manager()
profiles = ViewerProfileManager()
self._db is going to be affected by the name of your database.
I'd like to filter the related entries in the manager:
class UserTravelsCarsManager(models.Manager):
def for_user(self, user):
return super(UserTravelsCarsManager, self).get_query_set().filter(user=user)
class TravelsCars(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=255)
...
objects = UserTravelsCarsManager()
class UserTravelsManager(models.Manager):
def for_user(self, user):
return super(UserTravelsManager, self).get_query_set().filter(user=user)
class Travels(models.Model, ClonableMixin):
user = models.ForeignKey(User)
vehicle = models.ForeignKey(TravelsCars)
...
objects = UserTravelsManager()
It won't work by itself. I get all of the cars for all users. I've tried:
return super(UserTravelsManager, self).get_query_set().filter(user=user, vehicle__user=user)
Which also doesn't work.
UPDATE:
Just to be clear the entries for Travels are filtered. Just the related TravelsCars aren't filtered if I query them through Travels.
What am I doing wrong?
Instead of super(UserTravelsCarsManager, self).get_query_set().filter... try to use self.filter(user=user). Same in UserTravelsManager