I started using cfscript in my projects recently. While working with cfscript I used queryExecute() function to run queries. In few situations there was more than one query in the same function. These queries shared some of the same parameters. I was wondering if I can have one structure that will hold all parameters for all queries. This is what I tried:
local.qryParams = structNew();
structAppend(qryParams, {rec_id = {cfsqltype="cf_sql_numeric", value="#arguments.rec_id#"}});
structAppend(qryParams, {position = "#application.position#"});
structAppend(qryParams, {user_id = "#client.userid#"});
structAppend(qryParams, {title = {cfsqltype="cf_sql_varchar", value="#arguments.title#", maxlength: 50}});
structAppend(qryParams, {description = {cfsqltype="cf_sql_varchar", value="#arguments.description#", maxlength: 1000}});
Then I have two variables with SQL:
local.insertSQL = "
INSERT INTO notes(rec_id, title, description, user_id, last_update)
VALUES (:rec_id, :title, :description, :user_id, getDate())
";
local.updateSQL = "
UPDATE profile
SET last_update = getDate(),
user_id = :user_id
WHERE rec_id = :rec_id
AND position = :position
";
Then on the very end I have two execute functions:
queryExecute(insertSQL, qryParams , {datasource="#application.datasource#", result: "insertResult"});
queryExecute(updateSQL, qryParams , {datasource="#application.datasource#", result: "updateResult"});
Both functions executed successfully and record was inserted/updated. My questions are:
Is this a good approach to store all query parameters in one structure?
Is there any potential problem or security issue doing it that way?
Any suggestions/comments?
Thank you!
This is kind of an open ended question, but here goes
Q1: Is this a good approach to store all query parameters in one structure?
A1: Yes, but you may want to consider using entities if you like this.
Q2: Is there any potential problem or security issue doing it that way?
A2: None that I know of
Q3: Any suggestions/comments?
A3:
If your datasource is in application.cfc, you don't need to explicity state it.
You are getting the result the hard way. Consider myResult=QueryExecute(...)
You can build the struct in one shot. You don't need all these structAppend()s. structNew() is way too much typing. Consider {}.
user_id = "#client.userid#" is way too much typing... Just user_id = client.userid is enough.
You changed styles of building structs {cfsqltype="cf_sql_varchar", value="#arguments.title#", maxlength: 50}. IMHO, use : instead of =
Hope this is helpful
Related
I have a model with three statuses: draft, launching, launched. What I want is to display models in a particular order: first drafts, then launching ones, and then launched ones. I don't want to name my attributes as 0_draft, 1_launching, 2_launched as this will be a problem down the road; i need clear values in my DB.
Is there a way to annotate these values with some integers?
The ideal syntax for this would look like this:
def detect_status_number(campaign):
if campaign.status == 'draft':
return 1
... etc ...
cs = Campaign.objects.annotate(new_arg=lambda campaign: detect_status_number(campaign))
cs = cs.order_by('new_arg').all()
this obviously doesn't work; but is there a way to make this work?
I think this will work
cs = Campaign.objects.extra(
select={"weight_status":"case when campaign.status='draft' then 0 when campain.status = 'launching' then 1 else 2 end"}
).order_by('weight_status')
Although you could certainly make your approach work, let me recommend another approach: using the choices field and "enumeration". Here is an example:
STATUS_TYPE = (
(1, "draft"),
(2, "launching"),
(3, "launched"),
)
And then for your model field:
status = models.IntegerField(choices=STATUS_TYPE)
I realize that this may not be an acceptable answer if your model design is already set, but this is a good design pattern to know.
I've got django 1.8.5 and Python 3.4.3, and trying to create a subquery that constrains my main data set - but the subquery itself (I think) needs a join in it. Or maybe there is a better way to do it.
Here's a trimmed down set of models:
class Lot(models.Model):
lot_id = models.CharField(max_length=200, unique=True)
class Lot_Country(models.Model):
lot = models.ForeignKey(Lot)
country = CountryField()
class Discrete(models.Model):
discrete_id = models.CharField(max_length=200, unique=True)
master_id = models.ForeignKey(Inventory_Master)
location = models.ForeignKey(Location)
lot = models.ForeignKey(Lot)
I am filtering on various attributes of Discrete (which is discrete supply) and I want to go "up" through Lot, over the Lot_Country, meaning "I only want to get rows from Discrete if the Lot associated with that row has an entry in Lot_Country for my appropriate country (let's say US.)
I've tried something like this:
oklots=list(Lot_Country.objects.filter(country='US'))
But, first of all that gives me the str back, which I don't really want (and changed it to be lot_id, but that's a hack.)
What's the best way to constrain Discrete through Lot and over to Lot_Country? In SQL I would just join in the subquery (or even in the main query - maybe that's what I need? I guess I don't know how to join up to a parent then down into that parent's other child...)
Thanks in advance for your help.
I'm not sure what you mean by "it gives me the str back"... Lot_Country.objects.filter(country='US') will return a queryset. Of course if you print it in your console, you will see a string.
I also think your models need refactoring. The way you have currently defined it, you can associate multiple Lot_Countrys with one Lot, and a country can only be associated with one lot.
If I understand your general model correctly that isn't what you want - you want to associate multiple Lots with one Lot_Country. To do that you need to reverse your foreign key relationship (i.e., put it inside the Lot).
Then, for fetching all the Discrete lots that are in a given country, you would do:
discretes_in_us = Discrete.objects.filter(lot__lot_country__country='US')
Which will give you a queryset of all Discretes whose Lot is in the US.
I have been working on the AX Query Service as of late. I have a pretty good understanding of everything but it seems that the QueryDataFieldMetadata object does not like aggregates. When I build a QueryDataFieldMetadata object:
QueryDataFieldMetadata field = new QueryDataFieldMetadata();
field.TableName = "InventSum";
field.FieldName = "AvailPhysical";
field.SelectionField = SelectionField.Database;
And add it to the data source everything is fine. But when I do this:
QueryDataFieldMetadata field = new QueryDataFieldMetadata();
field.TableName = "InventSum";
field.FieldName = "AvailPhysical";
field.SelectionField = SelectionField.Sum;
And add it to the data source the field is not returned at all in the results set. I have checked the datasource itself before executing the query and it is in the fields list but nothing is returned. Does anyone know why this might be happening? Any help would be appreciated.
I just figured this one out. The problem was due to me selecting another field from the table but forgetting to put it in the "Group by" fields. It is strange to me that the query service was returning THAT field with an empty but not returning the aggregate fields at all. Basically I had made a query service query that would be equal to this:
Select wMSLocationId, SUM(AvailPhysical), RecId from InventSum group by ItemId, InventLocationId, wMSlocationId where ItemId == 'some value';
The query was returning:
InventSum.wMSLocationId = 001
InventSum.RecId = 0
The inclusion of the RecId was a mistake, I had forgotten to remove it, but didn't think it would matter as it wasn't in the group by fields and would therefore return null. Removing this selection field did result in the aggregate field returning in the query.
Anyway I hope this helps someone out there as it took me some time to figure out.
again I would like to search for duplicates in my models, but now slightly different case.
Here are my models:
class Concept(models.Model):
main_name = models.ForeignKey(Literal)
...
class Literal(models.Model):
name = models.Charfield(...)
concept = models.ForeignKey(Concept)
...
And now the task I'm trying to achieve:
Select all literals that are NOT main_names, that have the same name for the same concept.
For example if I have literals:
[{id:1, name:'test', concept:1}, {id:2, name:'test', concept:1}]
and concepts:
[{id:1, main_name:1}]
Then in result I should get literal with the ID=2.
It sounds to me as though you want to execute a SQL query something like this:
SELECT l1.* FROM myapp_literal AS l1,
myapp_literal AS l2
WHERE l1.id <> l2.id
AND l1.name = l2.name
AND l1.concept = l2.concept
AND l1.id NOT IN (SELECT main_name FROM myapp_concept)
GROUP BY l1.id
Well, in cases where the query is too complex to easily express in Django's query language, you can always ask Django to do a raw SQL query—and this may be one of those cases.
If I understand your question you want:
All Literal objects that are not ForeignKey'd to Concept.
From that set, select those where the name and the concept is the same.
If so, I think this should work:
For the first part:
q = Literal.objects.exclude(pk__in=Concept.objects.values_list('id', flat=True))
EDIT:
Based on excellent feedback from Jan, I think for #2 you would need to use raw SQL.
Thank to this post I'm able to easily do count and group by queries in a Django view:
Django equivalent for count and group by
What I'm doing in my app is displaying a list of coin types and face values available in my database for a country, so coins from the UK might have a face value of "1 farthing" or "6 pence". The face_value is the 6, the currency_type is the "pence", stored in a related table.
I have the following code in my view that gets me 90% of the way there:
def coins_by_country(request, country_name):
country = Country.objects.get(name=country_name)
coin_values = Collectible.objects.filter(country=country.id, type=1).extra(select={'count': 'count(1)'},
order_by=['-count']).values('count', 'face_value', 'currency_type')
coin_values.query.group_by = ['currency_type_id', 'face_value']
return render_to_response('icollectit/coins_by_country.html', {'coin_values': coin_values, 'country': country } )
The currency_type_id comes across as the number stored in the foreign key field (i.e. 4). What I want to do is retrieve the actual object that it references as part of the query (the Currency model, so I can get the Currency.name field in my template).
What's the best way to do that?
You can't do it with values(). But there's no need to use that - you can just get the actual Collectible objects, and each one will have a currency_type attribute that will be the relevant linked object.
And as justinhamade suggests, using select_related() will help to cut down the number of database queries.
Putting it together, you get:
coin_values = Collectible.objects.filter(country=country.id,
type=1).extra(
select={'count': 'count(1)'},
order_by=['-count']
).select_related()
select_related() got me pretty close, but it wanted me to add every field that I've selected to the group_by clause.
So I tried appending values() after the select_related(). No go. Then I tried various permutations of each in different positions of the query. Close, but not quite.
I ended up "wimping out" and just using raw SQL, since I already knew how to write the SQL query.
def coins_by_country(request, country_name):
country = get_object_or_404(Country, name=country_name)
cursor = connection.cursor()
cursor.execute('SELECT count(*), face_value, collection_currency.name FROM collection_collectible, collection_currency WHERE collection_collectible.currency_type_id = collection_currency.id AND country_id=%s AND type=1 group by face_value, collection_currency.name', [country.id] )
coin_values = cursor.fetchall()
return render_to_response('icollectit/coins_by_country.html', {'coin_values': coin_values, 'country': country } )
If there's a way to phrase that exact query in the Django queryset language I'd be curious to know. I imagine that an SQL join with a count and grouping by two columns isn't super-rare, so I'd be surprised if there wasn't a clean way.
Have you tried select_related() http://docs.djangoproject.com/en/dev/ref/models/querysets/#id4
I use it a lot it seems to work well then you can go coin_values.currency.name.
Also I dont think you need to do country=country.id in your filter, just country=country but I am not sure what difference that makes other than less typing.