Django prefetch_select and reverse join issue - python

I am working on multiple join with Django.
questions = Question.objects.select_related(
'publishedquestionmapping__library_question'
).prefetch_related(
'publishedquestionmapping__library_question__contributor_set__user',
).filter(
hide=False).order_by('-pub_date')[:count]
for question in questions:
contributers = question.publishedquestionmapping.library_question.contributor_set.all()
for contributer in contributers:
print contributer.user
The Error is RelatedObjectDoesNotExist: Contributor has no user.
The problem is that I can use prefetch_related
...contributor_set__user, but I can't use contributer.user?
btw, print contributer.user_id is ok.
This Model Contributer
class Contributor(models.Model):
user = models.ForeignKey(User)
question = models.ForeignKey(Question)
I want to do like contributer.user.username. How should I do that?!
Thanks!

Related

django sql .raw filtering on a string not working

I am trying to filter on a foreign key but getting an error.
Current code is:
views.py
def kingmailboxcodesshow(request):
lname = "King"
lockbox_list = MailBoxCodes.objects.raw('SELECT * FROM mailboxcodes WHERE Address_id__contains %s',[lname])
return render(request,"users/mailboxcodesshow.html",{'MailBoxCodes':lockbox_list})
models.py
from django.db import models
from properties.models import Properties, Building_Name
from django.db.models import Q
# Create your models here.
class MailBoxCodes(models.Model):
id = models.AutoField(primary_key=True)
Address = models.ForeignKey(Properties, max_length=10, on_delete=models.CASCADE, default='Unknown',limit_choices_to=Q(StudentRental=True)| Q(Active=True))
MailBoxCode = models.CharField(max_length=10, null=False,default='000')
Active = models.BooleanField(default=True)
class Meta:
db_table = "mailboxcodes"
def __str__(self):
return str(self.Address)
receiving this error:
django.db.utils.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''King'' at line 1")
I am still really new to django and python, looking at the error I am thinking i need a few less ' around the King, but I am not sure how to make that happen.
I have a bunch of addresses in the Address_id and I just want to retrieve all the address with the work King in their street address.
The great thing with Django is that you don't need raw SQL queries, unless you really really know what you're doing. Please follow the official tutorial as it explains the fundamentals of Django and will guide you through this over here: Django tutorial
To help you out with this particular issue:
def kingmailboxcodesshow(request):
lname = "King"
lockbox_list = MailBoxCodes.objects.filter(address__name__contains=lname)
return render(request,"users/mailboxcodesshow.html",{'MailBoxCodes':lockbox_list})
Well there is no such thing as a __contains in SQL, that is just some Django logic that transforms it to a query, you can work with:
def kingmailboxcodesshow(request):
lname = 'King'
lockbox_list = MailBoxCodes.objects.raw(
'SELECT * FROM mailboxcodes WHERE Address_id LIKE %%%s%%', (lname,)
)
return render(
request, 'users/mailboxcodesshow.html', {'MailBoxCodes': lockbox_list}
)
That being said, using raw queries should be a last resort: the entire idea of Django's ORM is, as you actually found out with this question to make abstraction of query logic. You can run this with:
def kingmailboxcodesshow(request):
lname = 'King'
lockbox_list = MailBoxCodes.objects.filter(Address_id__contains=lname)
return render(
request, 'users/mailboxcodesshow.html', {'MailBoxCodes': lockbox_list}
)
Please share your MailBoxCodes model, and also tell what is this Address_id as you mentioned it is a foreign key in one of the comments above.
Try this:
def kingmailboxcodesshow(request):
lname = 'King'
lockbox_list = MailBoxCodes.objects.filter(Address__name__contains=lname)
return render(
request, 'users/mailboxcodesshow.html', {'MailBoxCodes': lockbox_list}
)
Or this:
MailBoxCodes.objects.filter(Address__contains=lname)
You can also use __icontains lookup for case-insensitive filtering.

Retrieve data if a choice in Django models.TextChoices is met

Program versions:
Django 3.1.13
Python 3.8.10
My models.py:
# Create your models here.
class Odorant(models.Model):
Pubchem_ID = models.IntegerField(primary_key = True)
Name = models.CharField(max_length =50)
Ruletype = models.TextChoices ('Ruletype', 'Satisfied Unsatisfied')
Rule_of_Five = models.CharField(max_length = 20, choices = Ruletype.choices)
Rule_of_Three = models.CharField(max_length = 20, choices = Ruletype.choices)
Ghose_Filter = models.CharField(max_length = 20, choices = Ruletype.choices)
I would love to retrieve all the odourants that satisfies one of the rules and also the ones that satisfy all the rules at the same time and show them in html page.
I have already configured urls.py and views.py but I miss the correct function to query the database.
If more code is needed, feel free to ask.
Any suggestion?
Thank you all.
This is something that's answered in Django's queryset documentation. One way to accomplish this is by chaining exclude functions.
It doesn't make sense to also save conditions that satisfy all of your rules in the same queryset, so save that separately. If you have any questions about filtering out empty values, there's a very good answer found in this post.
satisfy_one_or_more_rules = Odorant.objects\
.exclude(Rule_of_Five='')\
.exclude(Rule_of_Three='')\
.distinct()
satisfy_all_rules = Odorant.objects\
.exclude(Rule_of_Five='', Rule_of_Three='')

join queryset in django

i have a models
class FriendsWith(models.Model):
username = models.ForeignKey(User,on_delete=models.CASCADE)
fusername =models.ForeignKey(User,on_delete=models.CASCADE,related_name='fusername')
time = models.DateTimeField(auto_now_add=True)
confirm_request = models.SmallIntegerField(default=1)
blocked_status = models.IntegerField(default=0)
i wanted to search all the friends of currently logged in user.So,i am doing like this
obj1=FriendsWith.objects.filter(username=request.user).select_related('fusername')
obj2=FriendsWith.objects.filter(fusername=request.user).values('username')
obj=obj1 | obj2
friendslist=User.objects.filter(username__in=obj)
Where User is a django User model
I am trying to combine two queryset(obj1 and obj2) set here But it's not working.I can do the same thing in sql by using alias .But here i am not sure what to do.
I am getting this error while performing the above code:
TypeError: Merging 'QuerySet' classes must involve the same values in each case
Please help in achieving this task
I think you should do the 'or' in the filter function:
from django.db.models import Q
friendship = FriendsWith.objects.filter(Q(username=request.user)|Q(fusername=request.user))
friendship is a queryset where the current user can be a username or a fusername. You can use that set to get the alternative user that should be their friend.
Another solution is to use django-friendship. It is a good django library for handling friendship and friend requests between users and so on.

How to optimize a DB call existing under a FOR loop (platform: Django, Python, Postgres) [duplicate]

This question already has an answer here:
Rewriting this database access query to circumvent 'DISTINCT ON' error, in Django
(1 answer)
Closed 7 years ago.
I'm optimizing a Django website I maintain, for performance. Among other things, I've made the mistake of including non-trivial db calls under a FOR loop. Much better practice would be to make the DB call once, and then loop over the data as much as I want. How can I accomplish that in the following piece of code? Need a protip here!
link_ids = [link.id for link in context["object_list"]]
seen_replies = Publicreply.objects.filter(answer_to_id__in=link_ids,publicreply_seen_related__seen_user = user)
for link in context["object_list"]:
try:
latest_reply = link.publicreply_set.latest('submitted_on')
if latest_reply in seen_replies:
#do something
except:
pass
Essentially, profiling tells me that the line latest_reply = link.publicreply_set.latest('submitted_on') is adding significant overhead because it's doing a ton of DB queries (being under the FOR loop and all).
I can't seem to figure out a nice, clean way to move the call to outside the loop, and then process it's constituents within it. Anyone got any ideas?
Note: link.publicreply_set.latest('submitted_on') may yield DoesNotExist. I am on Postgres in production, but SQLite locally.
Models are:
class Link(models.Model):
description = models.TextField(validators=[MaxLengthValidator(500)])
submitter = models.ForeignKey(User)
submitted_on = models.DateTimeField(auto_now_add=True)
class Publicreply(models.Model):
submitted_by = models.ForeignKey(User)
answer_to = models.ForeignKey(Link)
submitted_on = models.DateTimeField(auto_now_add=True)
description = models.TextField(validators=[MaxLengthValidator(250)])
class Seen(models.Model):
seen_status = models.BooleanField(default=False)
seen_user = models.ForeignKey(User)
seen_at = models.DateTimeField(auto_now_add=True)
which_reply = models.ForeignKey(Publicreply, related_name="publicreply_seen_related")
You can take advantage of postgresql window function first_value. This is an approach how you can improve performance:
link_ids = [link.id for link in context["object_list"]]
seen_replies = ( Publicreply
.objects
.filter(answer_to_id__in=link_ids,
publicreply_seen_related__seen_user = user)
)
latest_replies = dict ( seen_replies
.extra(
select={
"id_latest_reply":
"""first_value(id) over
(partition by answer_to_id
order by submitted_on desc)
""" } )
.order_by()
.values_list( 'answer_to_id', 'id' )
.distinct()
)
for link in context["object_list"]:
try:
if link.id in latest_replies:
last_replie= (Publicreply
.objects
.get(id=latest_reply[link.id])
)
#do something
except:
pass

Django. Python. How to get current user's activity log?

I need to pass the current user's entire activity log to an html page, but it seems I cannot find any helpful solution regarding the same.
Is it possible? If yes, please direct me in the right way?
Thanks in advance!
Update:
I found a solution making use of a get() call to django's LogEntry model, but I am clueless as to what shall be the appropriate parameters for doing the same.
Yet another UPDATE:
I am looking for a way to access the activity log of a particular user from the django's log entries WITHOUT saving it to any database
Take a look below listed.....Hope it will help::
lets example::
Create Two Field in Models:
last_activity_ip = models.IPAddressField()
last_activity_date = models.DateTimeField(default = datetime(1960, 1, 1))
user = models.OneToOneField(User, primary_key=True)
Since the User and UserActivity models are now related one-to-one we can now type:
Run the Query Like this:
a = User.objects.get(username__exact='mpcabd')
print a.useractivity.last_activity_ip
b = UserActivity.objects.get(user=a)
print b.user.username
** To track the activity use this **
activity = None
try:
activity = request.user.useractivity
except:
activity = UserActivity()
activity.user = request.user
activity.last_activity_date = datetime.now()
activity.last_activity_ip = request.META['REMOTE_ADDR']
activity.save()
return
activity.last_activity_date = datetime.now()
activity.last_activity_ip = request.META['REMOTE_ADDR']
activity.save()
This question don't has a short answer, you can use sentry project by side of main django project. below link can helping you:
https://sentry.readthedocs.org/en/latest/

Categories