How to get object using filter on ManyToManyField - django

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]

Related

how to use delete() query in django?

I am trying to delete one of the items of a field in the table.
For example, I want to remove the 'hadi', shown in the image, from the table.
I make query to filter and exclude instance but in final part, delete() query does not accept input such as id or variable to remove specific thing in one field.
image
models.py
class Expense(models.Model):
expenser = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
debtors = models.ManyToManyField(
CustomUser,
related_name='debtors',
)
amount = models.PositiveIntegerField()
text = models.TextField()
date = models.DateField(null=True)
time = models.TimeField(null=True)
def get_debtors(self):
return ", ".join([str(d) for d in self.debtors.all()])
def who_has_no_paid(self):
return ", ".join([str(d) for d in self.debtors.all() if str(d) != str(self.expenser)])
def debt(self):
return int(float(self.amount/self.debtors.all().count()))
def get_absolute_url(self):
return reverse('expense_detail', args=[self.id])
Now what is the query that should be used in view?
Since it is a many to many field you need to use expense_obj.debtors.remove(hadi_obj) rather than using delete().
Documentation is really good for referencing
your view could be :
def remove_hadi(request):
expense_obj = Expense.objects.get(id=some_id) #get the expense obj from where u want to remove hadi
hadi_obj = User.objects.get(name="hadi") # get user obj u want to remove eg: hadi
# use m2m query
expense_obj.debtors.remove(hadi_obj)
return response

how to build query with several manyTomany relationships - Django

I really don't understand all the ways to build the right query.
I have the following models in the code i'm working on. I can't change models.
models/FollowUp:
class FollowUp(BaseModel):
name = models.CharField(max_length=256)
questions = models.ManyToManyField(Question, blank=True, )
models/Survey:
class Survey(BaseModel):
name = models.CharField(max_length=256)
followup = models.ManyToManyField(
FollowUp, blank=True, help_text='questionnaires')
user = models.ManyToManyField(User, blank=True, through='SurveyStatus')
models/SurveyStatus:
class SurveyStatus(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
survey_status = models.CharField(max_length=10,
blank=True,
null=True,
choices=STATUS_SURVEY_CHOICES,
)
models/UserSurvey:
class UserSurvey(BaseModel):
user = models.ForeignKey(User, null=True, blank=True,
on_delete=models.DO_NOTHING)
followups = models.ManyToManyField(FollowUp, blank=True)
surveys = models.ManyToManyField(Survey, blank=True)
questions = models.ManyToManyField(Question, blank=True)
#classmethod
def create(cls, user_id):
user = User.objects.filter(pk=user_id).first()
cu_quest = cls(user=user)
cu_quest.save()
cu_quest._get_all_active_surveys
cu_quest._get_all_followups()
cu_quest._get_all_questions()
return cu_quest
def _get_all_questions(self):
[[self.questions.add(ques) for ques in qstnr.questions.all()]
for qstnr in self.followups.all()]
return
def _get_all_followups(self):
queryset = FollowUp.objects.filter(survey__user=self.user).filter(survey__user__surveystatus_survey_status='active')
# queryset = self._get_all_active_surveys()
[self.followups.add(quest) for quest in queryset]
return
#property
def _get_all_active_surveys(self):
queryset = Survey.objects.filter(user=self.user,
surveystatus__survey_status='active')
[self.surveys.add(quest) for quest in queryset]
return
Now my questions:
my view sends to the create of the UserSurvey model in order to create a questionary.
I need to get all the questions of the followup of the surveys with a survey_status = 'active' for the user (the one who clicks on a button)...
I tried several things:
I wrote the _get_all_active_surveys() function and there I get all the surveys that are with a survey_status = 'active' and then the _get_all_followups() function needs to call it to use the result to build its own one. I have an issue telling me that
a list is not a callable object.
I tried to write directly the right query in _get_all_followups() with
queryset = FollowUp.objects.filter(survey__user=self.user).filter(survey__user__surveystatus_survey_status='active')
but I don't succeed to manage all the M2M relationships. I wrote the query above but issue also
Related Field got invalid lookup: surveystatus_survey_status
i read that a related_name can help to build reverse query but i don't understand why?
it's the first time i see return empty and what it needs to return above. Why this notation?
If you have clear explanations (more than the doc) I will very appreciate.
thanks
Quite a few things to answer here, I've put them into a list:
Your _get_all_active_surveys has the #property decorator but neither of the other two methods do? It isn't actually a property so I would remove it.
You are using a list comprehension to add your queryset objects to the m2m field, this is unnecessary as you don't actually want a list object and can be rewritten as e.g. self.surveys.add(*queryset)
You can comma-separate filter expressions as .filter(expression1, expression2) rather than .filter(expression1).filter(expression2).
You are missing an underscore in surveystatus_survey_status it should be surveystatus__survey_status.
Related name is just another way of reverse-accessing relationships, it doesn't actually change how the relationship exists - by default Django will do something like ModelA.modelb_set.all() - you can do reverse_name="my_model_bs" and then ModelA.my_model_bs.all()

how to create a SimpleListFilter in django

I don't succeed to write a query filter.
I have 3 models: Patient, Prescription and User
I write you only what is relevant for my question
Patient:
class Patient(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
Prescription:
class Prescription(models.Model):
user = models.ForeignKey(
User,
null=True,
blank=False,
on_delete=models.DO_NOTHING
)
file_extention = models.CharField(
'file extention',
max_length=8,
null=True,
blank=True,
)
So the relation between both of models (Patient and Prescription) are through User.
in the PatientAdmin, I want to filter on the file_extension according pdf or jpg of the prescription uploaded.
I created a SimpleListFilter but impossible to find the right query.
class PrescriptionFileExtensionFilter(SimpleListFilter):
"""This filter is being used in django admin panel in
patient model."""
title = 'Prescription File Ext'
parameter_name = 'file_extention'
def lookups(self, request, model_admin):
return (
('pdf', 'PDF'),
('jpg', 'JPG'),
)
def queryset(self, request, queryset):
for user in queryset:
if self.value() == 'pdf':
return queryset.filter(user=user.user).filter
(prescription__file_extention="pdf")
if self.value() == 'jpg':
return queryset.filter(user=user.user).filter
(prescription__file_extention="jpg")
That's not working...
Do I need the for user in queryset:
need What could be the query to bring me all the users with a prescription with file_extension = "pdf" (or "jpg")
You are trying to get a key from the prescription object in print(mydict['file_extention']) which I believe is causing the issue - you would instead access that property via mydict.file_extention - though I should add that mydict is not an accurate variable name for a model object as it isn't a dictionary. I don't think that for loop is actually doing anything other than printing a particular value so it can be removed altogether.
As an aside, you have two filters on your queryset, this can just be expressed as a single filter, separate by a comma, e.g.
return queryset.filter(user=user.user, prescription__file_extention="pdf")
You are also calling user.user, presumably you just want to get the user model which is kept in request.user - is that what your for loop was trying to do?
Edit
If you want to get all of the users but just filtered by JPG or PDF then you need to remove two things:
The for-loop of for user in queryset
The filter of .filter(user=user.user)
The for loop is unnecessary in the queryset function and the filter is just getting a single user, but you want to get all of them - correct?

Django Query Does not exist

I'm been trying to create an app that allows users to follow each other profile since yesterday and today and I haven't been successful so far.
I'm having trouble creating a following function that allows me to retrieve users from a particular user he follows.
Example . If John follows Diana . I want to able to retrieve the user called Diana and use it with my modules.
I'm really sorry if this doesn't make sense . I'm trying my hardest to explain my situation.
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
class Board(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
Most of these solutions gave me no query
This was one of the solutions I tried.
class UserLink(models.Model):
from_user = models.ForeignKey(User , related_name = "following_set")
to_user = models.ForeignKey(User , related_name = "follower_set")
date_added = models.DateTimeField(default = datetime.now)
def __unicode__(self):
return "%s is following %s" % (self.from_user.username,self.to_user.username)
def save(self,**kwargs):
if self.from_user == self.to_user:
raise ValueError("Cannot follow yourself ")
super(UserLink , self).save(**kwargs)
class Meta:
unique_together = (('to_user','from_user'),)
I tried to retrieve the users that a particular user followed and use it against my modules such as Person but it gave me an error No query exist.
def Follow(request,username=""):
if request.method == "POST":
username = request.POST.get('follow',False)
user = User.objects.get(username=username)
UserLink.objects.create(from_user=request.user,to_user=user)
return HttpResponseRedirect(reverse('world:Profile'))
return HttpResponseRedirect(reverse('world:Profile'))
I also tried this following function but it only followed himself and I changed self to User but it didn't allow me to put the person to follow
class UserProfile(models.Model):
user = models.OneToOneField(User)
follows = models.ManyToManyField('self', related_name='followed_by', symmetrical=False)
>>>from pet.models import *
>>>from django.contrib.auth.models import User
>>>user = User.objects.get(username='Peter')
>>>user1 = User.objects.get(username='Sarah')
>>>p = UserProfile.objects.filter(user=user,follows=user1)
>>>Error no field called follows
How can I create a following class that allows retrieve the people that they followed and use it with my modules such as Person?
Can someone help me . Thannk you community!
If I understand correctly, youu are on the right track with the many to many relationship. What you need is to modify your existing Person class to include this information.
Since information about who someone follows or is following is essentially information about that person and so you shouldn't really need to define a new class to implement that functionality.
I would suggest modifying your Person like so.
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
following = models.ManyToManyField('self', related_name='followers', symmetrical=False, blank=True, null=True)
What this line does is makes a many to many relationship between the class Person and its self.
Many to many relationships work a little different to other relationships and I suggest you read the Django documentation https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/.
But you should now be able to setup and access the relationship like this.
>>>john = Person.objects.get(name="John")
>>>diana = Person.objects.get(name="Diana")
>>>john.following.add(diana)//setup the many to many relationship
>>>john.save()
>>>john.following.all()
//This should return a queryset of Person objects which john is following.
//eg Diana
>>>diana.followers.all()
//This should return a queryset of Person objects which are following Diana.
//eg. John.
Easy, how awesome is Django!

Django Model Manager related filter

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