I list the debts of my customers from the "debts" table with the following code.
However, I would like to see the name and surname of the customer with the same ID number from the "Customer" table.
I get the person I specified with the following code but; I cannot print to "Debts.objects.values (" customer ")".
Is there an easy way to do this?
Thanks for your help.
class CustomerDetailDebtListAPIView(ListAPIView):
serializer_class = DebtCreateSerializer
def get(self, request):
# get customer , customerKey
obj_customer = Customer.objects.get(customer=85)
field_object_customer = Customer._meta.get_field('customer')
# field_value_customer = getattr(obj_customer, field_object_customer.attname)
print(obj_customer)
result = Debt.objects.values('customer') \
.annotate(totalDebt=Sum('totalDebt'), receivedAmount=Sum('receivedAmount')) \
.order_by('customer')
return Response(result)
I am supposing that customer is a foreign key. You can access fields of your related tables using __ operators. This is shown in below code
Debt.objects.all().annotate(totalDebt=Sum('totalDebt'), receivedAmount=Sum('receivedAmount')).order_by('customer').values('customer__surname')
or
from django.db.models import F
Debt.objects.all().annotate(totalDebt=Sum('totalDebt'), receivedAmount=Sum('receivedAmount'), surname=F('customer__surname')).order_by('customer').values('surname')
Related
I am trying to get all my data out of the database in a array or list format.
Such that I can make an for loop in the html to loop through all the names in the database.
I tried with:
all_name = name.objects.all()
the output will be shown as
<QuerySet [<allName: name1>, < allName: name2>, < allName: name3>]>
However I want to get something like:
name1;
name2; name3
What I did next is to use the .get function:
all_name = name.objects.get(id=1)
my name model:
class name(models.Model):
firstname = models.CharField(max_length=100)
def __str__(self):
return (self.firstname)
This gives me only one object with the given id.
Is there a way to get what I am looking for and display my array/list with a forloop in a html file?
You can simply try for Name model with consider allName as a attribute/column
list(Name.objects.all().values_list('allName', flat=True))
or
Name.objects.all().values_list('allName')
You can join the strings that originate from the database with:
'; '.join(map(str, name.objects.all()))
Many:
name_list = Name.objects.all().values_list('firstname', flat=True))
One:
query = name.objects.get(id=1)
name = query.firstname
I have query that performs full text search on several columns (including on columns of models related using FK) in Django:
from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank
class TaskManager(models.Manager):
def search_by_text(self, text: str):
search_vector = SearchVector(
"task_type__name",
"order__registration_number",
"order__report_number",
"car_owner_name",
"task_number",
"order__customer_order_number",
"order__customer_owner",
"order__report_type__value",
)
search_query = SearchQuery(text)
return self.get_queryset().annotate(
rank=SearchRank(search_vector, search_query)
).order_by("rank")
How can I get not only found records but also column names where searched value was found for each record? Example:
>>> Entry.objects.search_by_text("some value")[0].columns_matched
["task_type__name", "task_number"]
I'm using Postgresql 10.12 and Django 2.2.10.
Solved this problem by creating migration which creates database view which has search_q column containing concatenated string with values from all searched columns.
CREATE VIEW app_taskdata_search_view
AS
SELECT Row_number()
over(
ORDER BY TASK.task_number) AS id,
Concat(tasktype.name, '|', TASK.description, '|', USER.first_name, '|',
USER.last_name) AS search_q
FROM app_taskdata AS TASK
inner join app_tasktype AS tasktype
ON TASK.task_type_id = tasktype.id
inner join users_user AS USER
ON TASK.user_id = USER.id
ORDER BY TASK.task_number;
Then in models.py:
class TaskDataSearchView(models.Model):
"""
Database view refrenced from.
"""
id = models.BigIntegerField(primary_key=True)
search_q = models.TextField()
class Meta:
db_table= "app_taskdata_search_view"
managed = False
Assuming I know the order of concatenated column values I can make a Python code which loops through result and checks if searched value was found in column:
text = "Some text to search"
records = TaskDataSearchView.objects.filter(search_q__icontains=text)
values = records[0].search_q.split("|")
# check if task_type column contains searched text
if text in values[0]:
field_mapping['task_type'] = True
P.S: Useful link
I'm fairly new to peewee, but have some strong background on SQLAlchemy (and all the vices that come with it). I'm trying to create a custom hybrid expression that correlates to a third (or even N) table. I'll try to demonstrate in an example (non-tested) code:
class BaseModel(Model):
class Meta:
database = database
class Person(BaseModel):
id = PrimaryKeyField(column_name="person_id")
name = CharField(max_length=255, column_name="person_name")
username = CharField(max_length=255, column_name="person_username")
class PersonTree(BaseModel):
id = PrimaryKeyField(column_name="person_tree_id")
name = CharField(max_length=255, column_name="person_tree_name")
code = CharField(max_length=255, column_name="person_tree_code")
person = ForeignKeyField(
column_name="person_id",
model=Person,
field="id",
backref="tree",
)
class Article(BaseModel):
id = PrimaryKeyField(column_name="article_id")
name = CharField(max_length=255, column_name="article_name")
branch = ForeignKeyField(
column_name="person_tree_id",
model=PersonTree,
field="id",
backref="articles",
)
#hybrid_property
def username(self):
"""
This gives me the possibility to grab the direct username of an article
"""
return self.branch.person.username
#username.expression
def username(cls):
"""
What if I wanted to do: Article.query().where(Article.username == "john_doe") ?
"""
pass
With the username hybrid_property on Article, I can get the username of the Person related to an Article using the PersonTree as a correlation, so far so good, but ... What if I wanted to "create a shortcut" to query all Articles created by the "john_doe" Person username, without declaring the JOINs every time I make the query and without relying on .filter(branch__person__username="john_doe")? I know it's possible with SA (to a great extent), but I'm finding this hard to accomplish with peewee.
Just for clarification, here's the SQL I hope to be able to construct:
SELECT
*
FROM
article a
JOIN person_tree pt ON a.person_tree_id = pt.person_tree_id
JOIN person p ON pt.person_id = p.person_id
WHERE
p.username = 'john_doe';
Thanks a lot in advance!
Hybrid properties can be used to allow an attribute to be expressed as a property of a model instance or as a scalar computation in a SQL query.
What you're trying to do, which is add multiple joins and stuff via the property, is not possible using hybrid properties.
What if I wanted to "create a shortcut" to query all Articles created by the "john_doe" Person username
Just add a normal method:
#classmethod
def by_username(cls, username):
return (Article
.select(Article, PersonTree, Person)
.join(PersonTree)
.join(Person)
.where(Person.name == username))
Let's say I have this model:
class Contact(BaseModel):
order = models.ForeignKey(Order, related_name='contacts', blank=True, null=True)
type = models.CharField(max_length=15, choices=TYPES, blank=True))
I want to find all orders where order and type are not unique together.
For example, there is order A and there are related contacts:
Contact(order=orderA, type='broker')
Contact(order=orderA, type='broker')
Contact(order=orderA, type='delivery')
I want to find this orderA because this order and type='broker' are not unique together in Contact model.
And then there is orderB and these related contacts:
Contact(order=orderB, type='broker')
Contact(order=orderB, type='delivery')
I don't want this orderB because it and the field type are unique in Contact model.
I tried using annonate() of Django but failed to relate these two fields.
Is it possible to do this with Django queries?
If not, a slight hint of how I could do it in SQL would be greatly appreciated.
Thank you very much.
You could use a SQL query like:
select distinct order_id
from (
select order_id, type
from Contact
group by order_id, type
having count(*) > 1);
The "order" column is shown as "order_id" because that's the way Django names columns.
This should do the trick
qs = (Contact.objects.values('order','type')
.annotate(cnt=models.Count('pk'))
.filter(cnt__gt=1))
You could write a couple methods to solve this problem. I might have gone over board writing these methods for you but regardless heres an explaination.
def equal_to takes self and some other contact, returns true if that contact is the same order and type else false. def all_not_unique returns a list of all not unique contact objects with no duplicates. And should be called like, not_unique = Contact.all_not_unique().
def equal_to(self, other):
assert(self.id != other.id)
if self.order.id == other.order.id:
if self.type == other.type:
return True
return false
#classmethod
def all_not_unique(cls):
query_set = cls.objects.all()
not_unique_query_set = []
for contact_one in query_set:
found = False
for contact_two in query_set:
if not found:
if contact_one.id != contact_two.id:
if contact_one.equal_to(contact_two):
not_unique_query_set.append(contact_one)
found = True
I have a model:
class Distributor(models.Model):
...
#property
def full_name(self):
return self.name + self.surname
class UserProfile(AbstractUser):
links = models.ManyToManyField(
Link, blank=True, related_name='links_by_user')
distributors = models.ManyToManyField(
Distributor, blank=True, related_name='distributors_of_user')
Now I want to make a query like this:
dist_list=request.user.distributors.all().filter(full_name__icontains='')
But this isn't working.
How to make such a query?
Django filters run at the database level. So it isn't possible to what you would like.
Keep in mind that you can always fall back to SQL if you'd like. No need to spend a ton of time figuring out how to make the Django ORM do this when it is a trivial SQL query:
query = """
SELECT *
FROM distributor_distributor d
INNER JOIN user_user_profile up ON up.id = %(user_id)s
INNER JOIN user_user_distributors_of_user udu ON udu.user_profile_id = %(user_id)s
AND udu.distributor_id = d.id
WHERE d.name || d.surname = %(query)s;
"""
dist_list = Distributor.objects.raw(query, {'user_id': request.user.pk, 'query': 'hello world'})
Wrap that in a function, put it in a utils.py module or something, baby you've got a stew going!
What you want to do is not possible. If you want to do that, you would have to do the filtering in python (with something like a list comprehension), like this:
[d for d in request.user.distributors.all() if ''.lower() in d.full_name().lower()]
Doing this would almost definitely be slower than querying the database, however, if request.user.distributors.all() has very many entries.
However, in this specific case, you could probably split up the string you want to query with into first and last name and query each separately? Maybe something like:
request.user.distributors.all().filter(name__icontains=name | surname__icontains=surname)