Django queryset keyword from string - python

This is my model
class Mymodel(models.Model):
title = models.CharField(max_length=150)
author = models.CharField(max_length=150)
I have a json like this stored in db q = {"field_name": "title", "value":"django"} and this is what I am trying to do.
Mymodel.objects.filter(q["field_name"]=q["value"])
It is not working. Getting the error
SyntaxError: keyword can't be an expression
How can i make this working ? I have tried things like
Mymodel.objects.filter(getattr(event_model, q["field_name"])=q["value"])
It is possible to make it work like many if elif conditions like below but the code becomes ugly. Is there any cleaner way to do this ?
if q["field_name"] == "title":
Mymodel.objects.filter(title=q["value"])
elif q["field_name"] == "author":
Mymodel.objects.filter(author=q["value"])

You can use the dictionary unpacking technique as,
q = {"field_name": "title", "value": "django"}
Mymodel.objects.filter(**{q["field_name"]: q["value"]})

Related

Unable to use Case, When, Then in django queryset

my models are as follows
class Loan(models.Model):
loan_value = models.IntegerField()
channel_seller = models.ForeignKey(ChannelSeller, on_delete=models.CASCADE)
class ChannelSeller(models.Model):
LEVEL_CHOICES = (
('1','Business Consultants'),
('2','Unit Managers'),
('3','Account Managers'),
('4','Branch Managers'),
)
level = models.CharField(max_length=2, choices = LEVEL_CHOICES, null = True, blank = True)
pin_no = models.CharField(max_length=255)
unit_manager = models.ForeignKey('self', limit_choices_to = {"level": '2'}, on_delete=models.DO_NOTHING, null = True, blank = True, related_name='unit_manager_2')
Loan can be created by business_consultant or unit_manager. Each business_consultant will have a unit_manager, however, unit_manager will have unit_manager as blank
with that said,
I'm trying to sort my query by unit_manager field using case, when, then as follows
transactions = Loan.objects.annotate(unit_manager_pin = Case(When('channel_seller__level' == '2', then='channel_seller_pin_no'), When('channel_seller__level' == '1', then='channel_seller__unit_manager__pin_no'))).filter(channel_seller__level__in = ['1','2']).order_by('channel_seller__level')
This query however throws me error __init__() takes either a Q object or lookups as keyword arguments
The condition needed to be applied is like a filter and also get the value using F function. Once try this.
transactions = Loan.objects.annotate(unit_manager_pin = Case(When(channel_seller__level='2', then=F('channel_seller__pin_no')), When(channel_seller__level='1', then=F('channel_seller__unit_manager__pin_no')))).filter(channel_seller__level__in = ['1','2']).order_by('channel_seller__level')
You are coding up a query to be executated by the DBM. You can't use Python code in that context ('channel_seller__level' == '2' ). See the doc on conditional expressions.
Please format your code legibly! Use line breaks inside brackets to continue.
In this case, you just change == to =, but it's important to understand why. The argument to When is similar to the argument to .filter. So to test for greater-than, it would be When( field__gt = 2, ...)
You also need to use F to refer to the value in the database. Without F it would (probably, not sure) be an error. (If you wanted a fixed value you would use Value('fixed-value'))
transactions = Loan.objects.annotate(unit_manager_pin =
Case(When('channel_seller__level' = '2',
then=F('channel_seller_pin_no')),
When('channel_seller__level' = '1',
then=F('channel_seller__unit_manager__pin_no'))
)
).filter(
...

Orator ORM model Create method invalid SQL

I have a database I created with a migration. One of my tables looks like this
def create_customer_table(self):
with self.schema.create("customer") as table:
table.char("name",120).unique()
table.integer("transmitting_hours").default(24) #how many hours after transmission vehicle is considered transmitting
table.boolean("is_tpms").default(False)
table.boolean("is_dor").default(False)
table.boolean("is_otr").default(False)
table.boolean("is_track_and_trace").default(False)
table.char("contact_person",25)
table.char("created_by",25)
table.enum("temperature_unit",TEMP_UNITS)
table.enum("pressure_unit",PRESSURE_UNITS)
table.enum("distance_unit",DISTANCE_UNITS)
table.char("time_zone",25)
table.char("language",2)
table.timestamps()
I have a very simplistic ORM model on top
class Customer(Model):
__table__ = "customer"
__timestamps__ = False
__primary_key__ = "name"
__fillable__ = ['*']
I then try to do a basic insert with the following code
def add_sample_customer():
sample_customer = {}
sample_customer["name"] = "customer_2"
sample_customer["contact_person"] = "Abradolf"
sample_customer["created_by"] = "Frodo"
sample_customer["time_zone"] = "GMT-5"
sample_customer["language"] = "EN"
sample_customer["temperature_unit"] = "FAHRENHEIT"
sample_customer["pressure_unit"] = "PSI"
sample_customer["distance_unit"] = "MI"
customer_model = Customer.create(_attributes = sample_customer)
The exception I get from this code looks like
orator.exceptions.query.QueryException: syntax error at or near ")"
LINE 1: INSERT INTO "customer" () VALUES () RETURNING "name"
(SQL: INSERT INTO "customer" () VALUES () RETURNING "name" ([]))
it looks like orator just isn't filling in the cols and vals here. I have also tried it with a few different syntactic ways of dropping the dict in there, using **sample_customer and also just putting the dict in directly and none of them work, all with the same exception. I started debugging by printing stuff out of the orator libraries but haven't gotten anywhere yet.
my inserts work if I do the model attribute assignment individually and use the model.save() method like this
def add_sample_customer():
sample_customer = {}
sample_customer["name"] = "customer_2"
sample_customer["contact_person"] = "Abradolf"
sample_customer["created_by"] = "Frodo"
sample_customer["time_zone"] = "GMT-5"
sample_customer["language"] = "EN"
sample_customer["temperature_unit"] = "FAHRENHEIT"
sample_customer["pressure_unit"] = "PSI"
sample_customer["distance_unit"] = "MI"
customer_model = Customer()
for k,v in sample_customer.items():
setattr(customer_model,k,v)
customer_model.save()
Does anyone understand why the model.create() syntax fails?
I would think the answer would be:
Simply passing the dictionary instead of using keyword notation with attributes:
Customer.create(sample_customer)
or
Customer.create(attribute=value,attribute2=value2,..etc)
Which are the valid notations

Serialize OneToMany relation into array in Django

Suppose I have some django models:
class Restaurant(Model):
name = CharField(max_length=200)
class Food(Model):
restaurant = ForeignKey(Restaurant, on_delete=CASCADE)
name = CharField(max_length=200)
One Restaurant can have multiple foods.
And I want my json to look like this:
[
{
"name": "xxx",
"food": [{"name": "xxx"}, {"name": "xxx"}, ...]
}, ...
]
I can use something like:
restaurants = Restaurant.objects.all().values()
for restaurant in restaurants:
restaurant['food'] = Food.objects.filter(restaurant__id=restaurant['id']).values()
But this loses some optimization in SQL level, as this is using application level loop.
Is there a better way to do this?
check this
restaurant = Restaurant.objects.all()
result = []
for rest in restaurant:
data = {
'name': rest.name,
'food': rest.food_set.all().values('name')
}
result.appen(data)
Try it....
User django rest framework. using serialzers you can do it more effectively
#Nakamura You are correct, query inside the loop is not a good way of coding.
below is one way of solving
restaurants = Restaurant.objects.all().values()
foods = Food.objects.all()
for restaurant in restaurants:
restaurant['food'] = foods.filter(restaurant__id=restaurant['id']).values()
As you gave required JSON format i suggested this answer.

How to use icontains in a key value of a DictField in Django queryset?

Given the following model:
class Team(models.Model):
name = models.CharField(max_length=50)
others = DictField()
And the following code:
bahia = Team()
bahia.name = "E.C. Bahia"
bahia.others = {"title": "Ninguém nos Vence em Vibração!!!"}
bahia.save()
vicetoria = Team()
vicetoria.name = "E.C. Vicetoria"
vicetoria.others = {"title": "Vice de tudo!"}
vicetoria.save()
I want to find the object that have the word vence, (case insensitive) contained in title value of the field others.
I tried something like:
teams = Team.objects.filter(others__title__icontains="vence")
that gives me the following error:
FieldError: Join on field 'others' not permitted. Did you misspell 'title' for the lookup type?
I also already tried:
teams = Team.objects.filter(others__icontains={"title":"vence"})
that returns None and I know there is at least one collection as result.
SOLUTION:
teams = Team.objects.raw_query({"others.title": {"$regex" : "vence", "$options": "i"}})
The i option makes the search insensitive.
I believe (correct me if I'm wrong) that djangotoolbox DictField doesn't support icontain.
To filter the Dict Field you need to do something like:
Team.objects.raw_query({'title': { $regex : /vence/i } })
Check out this answer: How do I filter based on dict contents in a DictField on a model using the Django-MongoDB Engine?
This answer shows how to do case insensitive mongodb queries: How do I make case-insensitive queries on Mongodb?

How to generate json data from a many to many database table?

I am using sqlite db and peewee as the ORM.
My data model is:
class User(UserMixin, db.Model):
nickname = CharField(index=True, unique=True)
class Circle(db.Model):
name = CharField(unique=True)
class UserInCircle(db.Model):
user = ForeignKeyField(User, related_name="in_circles")
circle = ForeignKeyField(Circle, related_name="include_users")
privilege = IntegerField()
What I need is to get a data format like the following:
[{"nickname": "urbainy", "privilege": 7, "in_circles": [{"circle_name": "world"}, {"circle_name": "test"}]}, {"nickname": "ywe", "privilege": 1, "in_circles": [{"circle_name": "family"}], {"nickname": "ymo", "privilege": null, "in_circles": []}]
So this is a nested json object. I tried marshmallow but I failed because of the many to many data structure. I can't get in_circles field all along time. I am beginner of programmer, so maybe this question is low level. But I really don't have idea to solve it. Thank you very much!
Now, I adopt this way to solve the problem:
#login_required
def setting():
users_in_circles = (User.select(User.nickname,
UserInCircle.privilege,
Circle.name.alias("circle_name"))
.join(UserInCircle, JOIN.LEFT_OUTER)
.join(Circle, JOIN.LEFT_OUTER)
.order_by(User.id))
users_in_circles_data = []
user_nickname = ""
user_in_circles = []
for user_in_circle in users_in_circles.naive():
if user_in_circle.nickname != user_nickname:
user_nickname = user_in_circle.nickname
user_in_circles = [dict(circle_name=str(user_in_circle.circle_name), privilege=str(user_in_circle.privilege))]
users_in_circles_data.append(dict(nickname=user_in_circle.nickname, in_circles=user_in_circles))
else:
user_in_circles.append(dict(circle_name=str(user_in_circle.circle_name), privilege=str(user_in_circle.privilege)))
users_in_circles_data[-1].update(nickname=user_in_circle.nickname, in_circles=user_in_circles)
print(users_in_circles_data)
return render_template("admin_setting.html", circles=Circle.select(), users=User.select(), users_in_circles_data=users_in_circles_data)
Somehow I think maybe there is some other neat way to implement this, such as marshmallow or some other tools. If you know a better solution, welcome to reply to my post then.

Categories

Resources