Django Model Manager related filter - django

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

Related

How to get object using filter on ManyToManyField

Why target_dialogue is always None?
Model:
class Dialogue(models.Model):
name = models.CharField(max_length=30, blank=True)
is_conference = models.BooleanField(default=False)
participants = models.ManyToManyField(
Person,
related_name='dialogues',
)
def __str__(self):
return self.name or str(self.pk)
And in view I want to get suitable dialogue which contain in participants field 2 objects - user and companion. And if this dialogue doesn't exist I create it:
target_dialogue = None
try:
target_dialogue = Dialogue.objects.get(is_conference=False,participants__in=[user, companion])
except ObjectDoesNotExist:
target_dialogue = Dialogue()
target_dialogue.save()
target_dialogue.participants.add(user)
target_dialogue.participants.add(companion)
finally:
return render(request, 'dialogues/dialogue.html', {
'dialogue': target_dialogue,
})
But target_dialogue is always None. What's a reason of it? I was supposed to solve only a trouble in getting a dialogue from db in order to bad filter parameters, but now I have doubts about it. Maybe something else?
request.user is not a object of Person model with which you have the relation in Dialogue.
You have to first fetch the person object:
user = Person.objecs.get(user=request.user). # According to your person model
Follow same for companion and then query:
target_dialogues = Dialogue.objects.filter(is_conference=False,participants__in=[user,companion]

Django custom manager for Users

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)

Django Custom Manager add attribute

I have a Django Model that looks like this:
class MyModel(models.Model):
field1 = models.IntegerField()
field2 = models.IntegerField()
nonDbField = SomeObject()
objects = MyCustomManager()
field1 is actually a PK to an abstract class of SomeObject.
I want a custom manager that for every value returned by any of the functions (all, filter, get, etc) does the following:
value.nonDbField = SomeObject.objects.get(pk=value.field1)
I've tested that I can manually override get like so:
class MyCustomManager(models.Manager):
def get(self, *args, **kwargs):
value = super(MyCustomManager, self).get(*args, **kwargs)
value.nonDbField = SomeObject.objects.get(listid=value.itemListID)
return value
but wondered if there was an easier way to do it across all functions.
There's going to be plenty of you that will say, "Why are you doing this?". It has to do with a model inheritance of a legacy, but still active database.
If you need nonDbField's value to be related to the field1 (or any other field in the model) you can try something like this:
Class MyModel(models.Model):
# your fields here...
def _nonDbField(self):
return SomeObject.objects.get(pk=self.field1)
nonDbField = property(_nonDbField)
This allows you to do something like this:
MyModel.objects.get(pk=1).nonDbField
Keep in mind that you are making a database query each time you access nonDbField (which may or may not be detrimental to your DB performance).
you can use property for your calculated fields
Class MyModel(models.Model):
# your fields here...
first_name = models.CharField()
last_name = models.CharField()
#property
def fullname(self):
return f"{self.first_name} {self.last_name}"
This allows you to do something like this:
obj = MyModel.objects.get(pk=1)
print(obj.fullname)

Django: Adding property to User model after creating model based on abstract class

I have a normal model and an abstract model like so:
class TaggedSubject(models.Model):
user = models.ForeignKey(User, null=True, blank=True)
category = models.CharField(max_length=200)
foo = models.CharField(max_length=50)
bar = models.CharField(max_length=50)
# etc
content_type = models.ForeignKey(ContentType)
content_object_pk = models.CharField(max_length=255)
content_object = generic.GenericForeignKey("content_type", "content_object_pk")
def __unicode__(self):
if self.user:
return "%s" % (self.user.get_full_name() or self.user.username)
else:
return self.label
class Taggable(models.Model):
tagged_subjects = generic.GenericRelation(TaggedSubject, content_type_field='content_type', object_id_field='content_object_pk')
#property
def tagged_users(self):
return User.objects.filter(pk__in=self.tagged_subjects.filter(user__isnull=False).values("user"))
class Meta:
abstract = True
The Taggable abstract model class then gets used like so:
class Photo(Taggable):
image = models.ImageField(upload_to="foo")
# ... etc
So if we have a photo object:
photo = Photo.objects.all()[0]
I can all the users tagged in the photo with photo.tagged_users.all()
I want to add the inverse relation to the user object, so that if I have a user:
user = User.objects.filter(pk__in=TaggedSubject.objects.exclude(user__isnull=True).values("user"))[0]
I can call something like user.tagged_photo_set.all() and have it return all the photo objects.
I suspect that since TaggedSubject connects to the Taggable model on a generic relation that it won't be possible to use it as a through model with a ManyToMany field.
Assuming this is true, this is the function I believe I'd need to add (somehow) to the User model:
def tagged_photo_set(self):
Photo.objects.filter(pk__in=TaggedSubject.objects.filter(user=self, content_type=ContentType.objects.get_for_model(Photo))
I'm wondering if it's possible to set it up so that each time a new model class is created based on Taggable, it creates a version of the function above and adds it (ideally as a function that behaves like a property!) to User.
Alternatively, if it is somehow possible to do ManyToMany field connections on a generic relation (which I highly doubt), that would work too.
Finally, if there is a third even cooler option that I am not seeing, I'm certainly open to it.
You could use add_to_class and the class_prepared signal to do some post processing when models subclassing your base class are set up:
def add_to_user(sender, **kwargs):
def tagged_FOO_set(self):
return sender.objects.filter(pk__in=TaggedSubject.objects.filter(
user=self,
content_type=ContentType.objects.get_for_model(sender)))
if issubclass(sender, MyAbstractClass):
method_name = 'tagged_{model}_set'.format(model=sender.__name__.lower())
User.add_to_class(method_name, property(tagged_FOO_set))
class_prepared.connect(add_to_user)

Django - Model Helper Property for current user

I'm looking for a way to get an object filtered with the current logged in user from a model helper property
Let me give an example
class Exo(models.Model):
"""Exercises"""
text = models.TextField()
class Score(models.Model):
"""Scores of users by exercise"""
exo = models.ForeignKey(Exo)
user = models.ForeignKey(User)
score = models.IntegerField()
class Meta:
unique_together = (('exo', 'user',),)
From the model Exo I'd like to be able to get the score of the logged in user
class Exo(models.Model):
"""Exercises"""
text = models.TextField()
def get_logged_score():
return self.score_set.filter(user=current_logged_user)[0]
From the Exo object, how can I get the score of the current_logged_user ?
Edit: The idea is to use get_logged_score from a template, so I can't pass any parameter
By passing it in.
def get_logged_score(self, user):
...