Get data from django database model - python

I have a django model, PhoneNumberVerification.
It has two columns: phone number, and code.
I want to be able to get the code if I am given a phone number. Essentially, search the table for which row has the phone number as my phone number, and fetch the code for that given row.
I could write SQL for this, but I do not know how to execute that to fetch data in django models, and I was wondering if there was a better non-sql way to do this.
My model:
class PhoneNumberVerification(models.Model):
phone_number = models.TextField(max_length = 20, blank = False, unique = True)
code = models.CharField(max_length = 8, blank = False)
What I want:
from .models import PhoneNumberVerification
def get_code(phone_number):
# do some stuff
return code

def get_code(phone_number):
verification = PhoneNumberVerification.objects.get(phone_number=phone_number)
return verification.code
Django's documentation has great tutorial for beginners.
Writing your first Django app, part 2

to get the object, you can simply use:
def get_code(phone_number):
try:
phone_number_verification = PhoneNumberVerification.objects.get(phone_numer=phone_number)
code = phone_number_verification.code
return code
except PhoneNumberVerification.DoesNotExist:
pass # django will raise exception in case if number does not exist
if you know there is only one object that matches your query, you can use the get(), which will return the object directly.
Otherwise, you can use filter(), more on that here

Related

Django fake model instanciation - No testunit [duplicate]

This question already has an answer here:
How can I create a django model instance with deferred fields without hitting the database?
(1 answer)
Closed 8 months ago.
I want to know if I can instanciate an empty fake model just with id of database record.
I found way to create mockup model, but I want a production-friendly solution.
Explanation of my issue :
I want to list users settings for users who choose to be displayed on public mode :
user_displayed_list = UserPublicProfile.objects.filter(
displayed = True,
).only(
'user_id',
'is_premium',
)
user_settings_list = []
for user_displayed in user_displayed_list:
# I have to send user Instance to the next method :
user_settings = self.get_user_settings(user_displayed.user)
user_settings_list.append(user_settings)
# But ’user_displayed.user’ run an new SQL query
I know I can improve my queryset as :
user_displayed_list = UserPublicProfile.objects.filter(
displayed = True,
).select_related(
'user'
).only(
'user',
'is_premium',
)
But It makes an useless join because I need only the user id field in get_user_settings():
The get_user_settings() method (it could help to understand context):
def get_user_settings(self, user)
user_settings = UserSettings.objects.get(user = user)
return user_settings
In real project, this method run more business feature
Is there a way to instanciate a User model instance with only id field filled ?
I don't want to use a custom empty class coded for this purpose. I really want an object User.
I didn't find anything for that. If it's possible, I could use it by this way :
for user_displayed in user_displayed_list:
FakeUser = User.objects.create_fake(id = user_displayed.user_id)
# I have to send user Instance to the next method :
user_settings = self.get_user_settings(FakeUser)
Without seeing the complete models, I'm assuming a bit. Assuming that UserSettings has a ForeignKey to User. Same for UserPublicProfile. Or User has ForeignKey to UserSettings. Works as well.
Assuming that, I see two solutions.
Solution #1; use the ORM to full potential
Just saw your comment about the 'legacy method, used many times'.
Django relations are very smart. They accept either the object or the ID of a ForeignKey.
You'd imagine this only works with a User. But if you pass the id, Django ORM will help you out.
def get_user_settings(self, user)
user_settings = UserSettings.objects.get(user = user)
return user_settings
So in reality, these work the same:
UserSettings.objects.get(user=1)
UserSettings.objects.get(user_id=1)
Which means this should work, without a extra query:
user_displayed_list = UserPublicProfile.objects.filter(
displayed = True,
).only(
'user_id',
'is_premium',
)
user_settings_list = []
for user_displayed in user_displayed_list:
# I have to send user Instance to the next method :
user_settings = self.get_user_settings(user_displayed.user_id) # pass the user_id instead of the object.
user_settings_list.append(user_settings)
Solution #2: chain relations
Another solution, again, still assuming quite a bit ;)
It would think you can chain the model together.
Assuming these FK exists: UserPublicProfile -> User -> UserSetting.
You could do this:
user_displayed_list = UserPublicProfile.objects.filter(
displayed = True,
).select_related(
'user', 'user__usersettings', # depends on naming of relations
).only(
'user',
'is_premium',
)
for user_displayed in user_displayed_list:
# I have to send user Instance to the next method :
user_settings = user_displayed.user.usersettings # joined, so should cause no extra queries. Depends on naming of relations.
user_settings_list.append(user_settings)

Django model set lookup very slow

I'm getting a very slow lookup in my Django models.
I have two tables:
class Scan(models.Model):
scan_name = models.CharField(max_length=32, unique=True, validators=[alphanumeric_plus_validator])
class ScanProcessingInfo(models.Model):
scan_name = models.CharField(max_length=32)
processing_name = models.CharField(max_length=64)
in_progress = models.BooleanField(default=False)
When I perform the following operation to get a list of all Scan objects which have a ScanProcessingInfo for a specific processing_name:
scans = models.Scan.objects.all()
scan_set = []
for scan in scans:
if self.set_type_definition.test_scan(scan, self.arg1, self.arg2):
scan_set.append(scan)
(test_scan routes to)
def get_proc_info_been_done(scan, spd_name):
try:
proc_info = models.ScanProcessingInfo.objects.get(scan_name = scan.scan_name)
except models.ScanProcessingInfo.DoesNotExist:
proc_info = None
if proc_info == None:
return False
return not proc_info.in_progress
the request takes about 10 seconds. There are 300 Scans in total and 10 ScanProcessingInfos. The db backend is an RDS MySQL db. I also expect someone will tell me off for using strings for the cross-table identifiers, but I doubt that's the cause here.
I'm sure I'm doing something obvious wrong, but would appreciate a pointer, thank you.
I think what you're asking is how to get all Scans for which a matching ScanProcessingInfo exists.
The first thing to do is to declare the actual relationship. You don't need to change your database (you should, but you don't have to); you can use your existing underlying field, but just tell Django to treat it as a foreign key.
class ScanProcessingInfo(models.Model):
scan = models.ForeignKey('Scan', to_field='scan_name', db_field='scan_name', on_delete=models.DO_NOTHING)
Now you can use this relationship to get all the scans in one go:
scan_set = Scan.objects.exclude(scanprocessinginfo=None)
Edit
To get all matching objects with a specific attribute, use the double-underscore syntax:
scan_set = Scan.objects.filter(scanprocessinginfo__processing_name=spd_name)
Use Many-to-one relationship.
scan_name = ForeignKey(Scan, related_name='processing_infos',on_delete=models.CASCADE)

DJANGO:How to perform AND operation for my query?

There are two models .I want to make query to extract only the app exact app related Adspaces .
models.py
class Appname(models.Model):
user=models.ForeignKey(User,related_name='appname', null=True, default=None,on_delete=models.CASCADE)
name=models.CharField(max_length=150,blank=False,null=False,help_text='Add your new App')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("dashapp:space",kwargs={'pk':self.pk})
class Adspace(models.Model):
user=models.ForeignKey(User,related_name='adspace', null=True, default=None,on_delete=models.CASCADE)
ad_space=models.CharField(max_length=150,blank=False,null=False)
app=models.ForeignKey('Appname', related_name='appnames',default=None, on_delete=models.CASCADE)
PID_TYPE = (
('FN','FORMAT_NATIVE'),
('FNB','FORMAT_NATIVE_BANNER'),
('FI','FORMAT_INTERSTITIAL'),
('FB','FORMAT_BANNER'),
('FMR','FORMAT_MEDIUM,RECT'),
('FRV','FORMAT_REWARDED_VIDEO'),
)
format_type=models.CharField(max_length=3,choices=PID_TYPE,default='FN',blank=False, null=False)
def __str__(self):
return self.ad_space
def get_absolute_url(self):
return reverse("dashapp:create",kwargs={'pk':self.pk})
Views.py
SHowing the one where i need to the query
class spacelist(LoginRequiredMixin,ListView):
model=Adspace
template_name='adspace_list.html'
def get_queryset(self):
query_set=super().get_queryset()
return query_set.filter(user=self.request.user)
Here I need to perform One more query so that EACH APP show their own adspaces when clicked right now every app show every show adspaces.
I have the idea what to do as if i compare app_id then it'll show the exact app related adspaces, but i dont know how to write query for the same as i already have one query present.???
You could try using a Q objects: https://docs.djangoproject.com/en/2.1/topics/db/queries/#complex-lookups-with-q-objects
From what I understand you are trying to filter both on the app_id and the request user at the same time, so you could try look something like this:
from django.db.models import Q
...
def get_queryset(self):
query_set=super().get_queryset()
return query_set.filter(Q(user=self.request.user) & Q(app_id=app_id))
...
This lets you do a single filter with both your requirements at the same time (i.e. retrieve the Adspace instances for a specific user with a specific Appname).
You chain another filter at the end like this:
class spacelist(LoginRequiredMixin,ListView):
model=Adspace
template_name='adspace_list.html'
def get_queryset(self):
query_set = super().get_queryset()
query_set = query_set.filter(user=self.request.user)
app_id = [...]
return query_set.filter(app_id=app_id)
The problem left is to find out what is the app_id coming from. How do you know what is the current app? Several options here.
Option 1: From the request
It can come from the current user: self.request.user.appname.all() but that will give you multiple apps, if the user can only have one app, you should change your model Appname.user to a OneToOneField.
Otherwise, I suggest changing your related_name='appnames' to reflect the multiplicity in the reverse relationship.
Option 2: From the URL
It can come from the URL, your space list view should extract an app_id parameter from the URL where it's defined:
url(r'^(?P<app_id>[0-9]+)/spaces/$', spacelist.as_view(), name='space_list'),
And then in the spacelist view, you would get this parameter like this:
app_id = self.kwargs['app_id']
return query_set.filter(app_id=app_id)
Hope that helps
UPDATE:
Also worth noting that QuerySets are lazy, meaning the result will get evaluated as late as possible by Django. Therefore, when you call:
query_set = query_set.filter(user=self.request.user)
The Django ORM doesn't execute any DB queries yet, and you can chain more filters after that:
query_set = query_set.filter(user=self.request.user)
query_set = query_set.filter(app_id=app_id)
Which behind the scenes is extending the query that will be executed when required. But at this point, no query is actually run. To see the query that will get executed you can print out the query attribute of the QuerySet:
print(query_set.query)
Which should log something like:
SELECT "app_adspace"."user_id" ...
FROM
"app_adspace"
WHERE
"app_adspace"."user_id" = 1234 AND "app_adspace"."app_id" = 5678

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/

Django: Proper Way to Update Models

Suppose I have the following function, which retrieves data from a server in the form of user-defined objects. For example, let's define the objects as PersonalEntry.
def retrieve_people()
// returns a list of all latest people objects, with fields equal to those in PersonEntry
def retrieve_books()
// returns a list of all latest book objects regardless of author, with fields equal to those in BookEntry, contains attribute,
Both user-defined classes has an .as_dict() method which returns all its attributes in a dictionary.
I would like to update the model whenever this function is called (ie. update the fields if the instance of that model already exists, else, define a new instance of the model). This is my current setup.
class PersonEntry(models.Model):
name = models.CharField(max_length = 50)
age = models.IntegerField()
biography = models.CharField(max_length = 200)
def update_persons():
try:
temp = retrieve_person()
for person in temp:
match = PersonEntry.objects.filter(name = person.name(), age = person.age())
match.update(**person.as_dict())
except DoesNotExist:
PersonEntry.create(**person.as_dict())
class BookEntry(models.Model):
author = models.ForeignKey(PersonEntry)
author_name = models.CharField(max_length = 50) //books return redundant info
author_age = models.IntegerField() //books return redundant info
title = models.CharField(max_length = 50)
summary = models.CharField(max_length = 200)
def update_books():
try:
temp = retrieve_books()
for book in temp:
match = BookEntry.objects.filter(title = temp.title())
match.update(**book.as_dict(), associate_person(book.author_age(), book.author_name()))
except DoesNotExist:
BookEntry.create(**book.as_dict(), associate_person(book.author_age(), book.author_name())
def associate_person(age, name):
return PersonEntry.get(name = name, age = age)
I suppose a more general question is, how do I update models with relationships if I have a function which returns data? Do I have a method in the model itself, or do I have it one level up (ie. move update_books to the Person model) I'm new to Django, so not really sure how the organization should be.
I confess I haven't completely grokked your question, but I'll take a punt that you should look into
Managers
Generally, in django, everything is done as lazily as possible - meaning nothing gets updated until you actually try to use it - so you don't update models/relationships as you go, rather you just declare what they are (perhaps with a manager) then it works it out the current value only when asked.
Methods returning a collection (or queryset) of some kind of a model, should be a part of the Managers. So in your case update_books should be in a custom manager for BookEntry and update_persons should be in custom manager for PersonEntry.
Also do not call the function retrieve_* from inside the model or manager. Call it in your application logic and then pass the result to the manager method unless that method itself is part of the manager/model.
You do not need a separate filter and update method. Depending on how you have retrieved the data and it has a pk you can directly do a save. See How Does Django Know when to create or update

Categories