How can I covert sqlachemy query into list object? [duplicate] - flask

This question already has answers here:
How to serialize SqlAlchemy result to JSON?
(37 answers)
Closed 1 year ago.
hi guys I am trying to convert my query into object but I am getting this error " 'User' object is not iterable"
Below are my codes.
#app.route('/users')
def users():
rows = db.session.query(User).first();
for row in rows:
data.append(list(row))# data.append([x for x in row])
return jsonify(data)

The code you have for querying
rows = db.session.query(User).first();
selects the first object found and returns it, else returns None as per docs
if there are multiple rows you are trying to query, use the .all() function as per docs
data = []
rows = db.session.query(User).all();
for row in rows:
data.append(row)
return jsonify(data)
this will fetch all the users and add it to the list

I was able to do this buy using flask mashmallow
ma = Marshmallow(app)
enter code here
class User(db.Model):
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(200),nullable=False)
email = db.Column(db.String(200),nullable=False)
password = db.Column(db.String(200),nullable=False)
class UserSchema(ma.Schema):
class Meta:
# Fields to expose
fields = ("email", "password","name")
# Smart hyperlinking
user_schema = UserSchema()
users_schema = UserSchema(many=True)
#app.route("/users/")
def users():
#row= db.session.query(User)
all_users = User.query.all()
results = users_schema.dump(all_users)
return jsonify(results)
#app.route("/users/<id>")
def user_detail(id):
user = User.query.get(id)
results = user_schema.dump(user)
return jsonify(results)

Related

how to execute filter or aggregate or annotate on foreign key model in django

i have user model
class User(models.Model):
first_name = models.CharField(max_length=30)
and order model
class Order(models.Model):
user = models.ForgienKey(User)
product_name = models.CharField(max_length=30)
creating 2 user
hi = User.objects.create(firs_name = 'hi')
bye = User.objects.create(firs_name = 'bye')
i created 3 orders
Order.objects.create(product_name='nokia',user=hi)
Order.objects.create(product_name='samsung',user=hi)
Order.objects.create(product_name='nokia',user=bye)
so how to count nokia has 2 users and samsung has 1 user in django using filter or aggregate or annotate? and ouput something like this(should in orderby count value)
{
"nokia":"2",
"samsung":"1"
}
Django 1.8
try this you will get your output in json format
from django.db.models import Count
Order.objects.values('product_name')
.annotate(usercount=Count('user'))
objects.create(first_name = 'hi')
hi.save()
bye = User.objects.create(first_name = 'bye')
bye.save()
Here first_name should be same as field name in models.
l=[]
for o in Order.objects.all():
l.append(str(o.product_name))
l is list which contains all products(repeated) in a list
d = {x:l.count(x) for x in l}
print d
d gives data in dictionary format, which is
{'nokia': 2, 'samsung': 1}
you can you default count function to get the count of objects with or without the filter as per your need as following.
data_dict = {}
for cat in Order.objects.all()
data_dict.update({cat.product_name : 0 })
for obj in Order.objects.all():
if obj.product_name in data_dict.keys():
data_dict[obj.product_name] += 1
printing data_dict will give you your expected output
Use following query
orders = Order.objects
.values_list('product_name')
.annotate(usercount=Count('user'))
orders = dict(orders) # This must be of your json key values.
OR
orders = dict(orders.iterlists()) # This must be of your json key values.

Django - Do different queries depending on value of field

I'm stuck on a seemingly simple issue. I want to do a different queryset if sold_data is empty. Is there an effective way to do this? Or do I need to use a for loop and loop over all the listing objects and check each one?
class Listing(models.Model):
list_price = models.IntegerField()
sold_price = models.IntegerField(null=True, blank=True)
... other fields
data = Listing.objects.filter(...) # Note: I had already made other queries
if sold_price == None:
data = data.filter(list_price__gte=1)
else:
data = data.filter(sold_price__gte=1)
You can do it using Q object.
from django.db.models import Q
# your filtered queryset is in 'data' varibale
data.filter(Q(sold_price__isnull=False, sold_price__gte=1) | Q(sold_price__isnull=True, list_price__gte=1))
if you wanna check if an object is None use the is operator
I'm not sure if I did understand your question here is what I get : you wanna filter list_price if the data contains an object with empty value else filter sold_price
You can try this
if data.filter(sold_price__isnull=True).exists():
data = data.filter(list_price__gte=1)
else:
data = data.filter(sold_price__gte=1)

Django : get() returned more than one

I have trouble to get my data from DB.
Basically one teacher can create more no of class_room each class_room contains a title and it has more number of students.
models.py
class class_room(models.model):
user = models.ForeignKey(User,related_name = 'classroom')
title = models.charField(max_length=50)
students = models.ManyToManyField(User,related_name= 'commits',symmetrical=FAlSE)
views.py
def index(request):
user = request.user
Total_class = class_room.objects.get(user = user)
students_list = Total_class.students.all()
class_name = Total_class.title.all()
return render(request,'trial/index.html,{'Total':Total_class ,'no':students_list, 'class_name ':class_name )
When i try to execute this code. i get this error get() returned more than one
Then i removed get() bcoz the user has more number of class_room so i put filter() After that i get 'QuerySet'object has no attribute 'students'
Any help appreciated :(
You have multiple objects for model class_room in the database, with the same user. Either you need to enforce the uniqueness to the user attribute in the models.
Or, you can get the students attribute of the first object in the query like,
Total_class = class_room.objects.filter(user = user).first()
students_list = Total_class.students.all()
or using index,
Total_class = class_room.objects.filter(user = user)[2]
#any element.
EDIT
As per the request of OP, I think the required queryset would be,
student_list = User.objects.filter(class_room__user=request.user)

How to write python-django queries which is ultimately going to call these queries from django

I want to write all types of complex queries,
for example :
If someone wants information "Fruit" is "Guava" in "Pune District" then they will get data for guava in pune district.
htt//api/?fruit=Guava&?district=Pune
If someone wants information "Fruit" is "Guava" in "Girnare Taluka" then they will get data for guava in girnare taluka.
htt://api/?fruit=Guava&?taluka=Girnare
If someone wants information for "Fruit" is "Guava" and "Banana" then they will get all data only for this two fruits, like wise
htt://api/?fruit=Guava&?Banana
But, when I run server then I cant get correct output
If i use http://api/?fruit=Banana then I get all data for fruit which is banana, pomegranate, guava instead of get data for fruit is only banana. So I am confuse what happen here.
can you please check my code, where I made mistake?
*Here is my all files
models.py
class Wbcis(models.Model):
Fruit = models.CharField(max_length=50)
District = models.CharField(max_length=50)
Taluka = models.CharField(max_length=50)
Revenue_circle = models.CharField(max_length=50)
Sum_Insured = models.FloatField()
Area = models.FloatField()
Farmer = models.IntegerField()
def get_wbcis(fruit=None, district=None, talkua=None, revenue_circle=None, sum_insured=None, area=None,min_farmer=None, max_farmer=None, limit=100):
query = Wbcis.objects.all()
if fuit is not None:
query = query.filter(Fruit=fruit)
if district is not None:
query = query.filter(District=district)
if taluka is not None:
query = query.filter(Taluka=taluka)
if revenue_circle is not None:
query = query.filter(Revenue_circle= revenue_circle)
if sum_insured is not None:
query = query.filter(Sum_Insured=sum_Insured)
if area is not None:
query = query.filter(Area=area)
if min_farmer is not None:
query = query.filter(Farmer__gte=min_farmer)
if max_farmer is not None:
query = query.filter(Farmer__lt=max_farmer)
return query[:limit]
Views.py
class WbcisViewSet(ModelViewSet):
queryset = Wbcis.objects.all()
serializer_class = WbcisSerializer
def wbcis_view(request):
fruit = request.GET.get("fruit")
district = request.GET.get("district")
taluka = request.GET.get("taluka")
revenue_circle = request.GET.get("revenue_circle")
sum_insured = request.GET.get("sum_insured")
area = request.GET.get("area")
min_farmer = request.GET.get("min_farmer")
max_farmer = request.GET.get("max_farmer")
wbcis = get_wbcis(fruit, district, taluka,revenue_circle,sum_insured,area, min_farmer, max_farmer)
#convert them to JSON:
dicts = []
for wbci in wbcis:
dicts.append(model_to_dict(wbci))
return JsonResponse(dicts)
Serializers.py
from rest_framework.serializers import ModelSerializer
from WBCIS.models import Wbcis
class WbcisSerializer(ModelSerializer):
class Meta:
model = Wbcis
fields=('id','Fruit','District','Sum_Insured','Area','Farmer','Taluka','Revenue_circle',)
whats need changes in this code for call these queries to get exact output?
I don't think that you're actually calling that view, judging by your usage I presume you're calling the viewset itself and then ignoring the query params.
You should follow the drf docs for filtering but essentially, provide the get queryset method to your viewset and include the code you currently have in your view in that
class WbcisViewSet(ModelViewSet):
queryset = Wbcis.objects.all() # Shouldn't need this anymore
serializer_class = WbcisSerializer
def get_queryset(self):
fruit = self.request.query_params.get("fruit")
....
return get_wbscis(...)

AND search with reverse relations

I'm working on a django project with the following models.
class User(models.Model):
pass
class Item(models.Model):
user = models.ForeignKey(User)
item_id = models.IntegerField()
There are about 10 million items and 100 thousand users.
My goal is to override the default admin search that takes forever and
return all the matching users that own "all" of the specified item ids within a reasonable timeframe.
These are a couple of the tests I use to better illustrate my criteria.
class TestSearch(TestCase):
def search(self, searchterm):
"""A tuple is returned with the first element as the queryset"""
return do_admin_search(User.objects.all())
def test_return_matching_users(self):
user = User.objects.create()
Item.objects.create(item_id=12345, user=user)
Item.objects.create(item_id=67890, user=user)
result = self.search('12345 67890')
assert_equal(1, result[0].count())
assert_equal(user, result[0][0])
def test_exclude_users_that_do_not_match_1(self):
user = User.objects.create()
Item.objects.create(item_id=12345, user=user)
result = self.search('12345 67890')
assert_false(result[0].exists())
def test_exclude_users_that_do_not_match_2(self):
user = User.objects.create()
result = self.search('12345 67890')
assert_false(result[0].exists())
The following snippet is my best attempt using annotate that takes over 50 seconds.
def search_by_item_ids(queryset, item_ids):
params = {}
for i in item_ids:
cond = Case(When(item__item_id=i, then=True), output_field=BooleanField())
params['has_' + str(i)] = cond
queryset = queryset.annotate(**params)
params = {}
for i in item_ids:
params['has_' + str(i)] = True
queryset = queryset.filter(**params)
return queryset
Is there anything I can do to speed it up?
Here's some quick suggestions that should improve performance drastically.
Use prefetch_related` on the initial queryset to get related items
queryset = User.objects.filter(...).prefetch_related('user_set')
Filter with the __in operator instead of looping through a list of IDs
def search_by_item_ids(queryset, item_ids):
return queryset.filter(item__item_id__in=item_ids)
Don't annotate if it's already a condition of the query
Since you know that this queryset only consists of records with ids in the item_ids list, no need to write that per object.
Putting it all together
You can speed up what you are doing drastically just by calling -
queryset = User.objects.filter(
item__item_id__in=item_ids
).prefetch_related('user_set')
with only 2 db hits for the full query.