updating records from controller in web2py - mysql

I want to update some field in a record of database form controller given i know which record that is and which field that is.How do i do that?
Eg:In the table 'students' in the database there is field called gender which is either 'male' or 'female'.After adding many records,i add a new field called 'gender_description'.It should be 'girl' when gender is female and 'boy' if gender is male.I want to populate this new field for all the records automatically.How do i achieve this?

In a web2py shell, you can do:
db(db.students.gender == 'male').update(gender_description='boy')
db(db.students.gender == 'female').update(gender_description='girl')
You don't want to do this in the app code, because the above should be run only once. Also, make sure the "gender_description" field has already been added to the model definition and that a migration has been run (this will happen automatically as long as migrations are enabled).
Note, if there is always a one-to-one correspondence between "gender" and "gender_description", this may not be the best database design.
As an alternative, you might consider creating a virtual field in web2py:
db.define_table('students',
Field('gender', ...),
Field.Virtual('gender_description',
lambda r: 'boy' if r.gender == 'male' else 'girl'),
...)

Related

How to edit and save multiple records in database from spring boot

My problem is simple and straight forward. I want to edit multiple records and save them in database. For editing a single record, I have used following statement in JpaRepository
DatabaseEntity findByAbcId(Integer abcId);
Here, I am trying to fetch a record from Mysql database table DatabaseEntity with respect to its column named abcId which is a foreign key of another table named ABC.
In my service class, I get this record, set its attributes and simply save it back in database like:
//Getting an existing record from database:
//Giving hardcoded value just for understanding
DatabaseEntity databaseEntity = databaseEntityRepository.findByAbcId(106);
//Setting edited fields into Model object. Except for its own id and abcId(foreign key)
databaseEntity.setCol1(value);
databaseEntity.setCol2(value);
databaseEntity.setCol3(value);
databaseEntityRepository.save(databaseEntity);
The above code will get a record and save its edited version into the database.
Now lets take a similar scenario but this time, the database is retrieving multiple records. from the database. Suppose multiple records are present against abcId column in my table. The changes in my code will be:
//Storing the result in the list as there are multiple records stored against 106
List<DatabaseEntity> databaseEntity = databaseEntityRepository.findByAbcId(106);
//What should I code here?
Now I am confused how to set values in multiple fields in a single go from spring boot. The values that I need to edit are also in another list and I tried iterating over both lists and change the database records accordingly but my approach is not a good one
//List of those records which I have edited
if(newRecordsList != null) {
//Using atomic Integer because only that can be changed within lambda expression
AtomicInteger outerLoopCounter = new AtomicInteger(0);
List<DatabaseEntity> databaseEntity = databaseEntityRepository.findByAbcId(Abc.getId());
databaseEntity.forEach(obj -> {
AtomicInteger innerLoopCounter = new AtomicInteger(0);
newRecordsList.forEach(newRecordsListObj -> {
//condition so that first record is updated according to the updated first record and other changes are updated accordingly.
if(outerLoopCounter.get() == innerLoopCounter.get()) {
obj.setName(newRecordsListObj.getName());
obj.setCondition(newRecordsListObj.getCondition());
obj.setValue(newRecordsListObj.getValue());
databaseEntityRepository.save(obj);
}
innerLoopCounter.incrementAndGet();
});
outerLoopCounter.incrementAndGet();
});
}
I know this is a very bad approach and I want to update my logic. So please help me to update these multiple records inside database.
Thanks in advance

Laravel Eloquent - auto-numbering on has many relationship

I'm very much a beginner when it comes to database relationships hence what I suspect is a basic question! I have two database tables as follows:
Projects
id
company_id
name
etc...
rfis
id
project_id (foreign key is id on the Projects table above)
Number (this is the column I need help with - more below)
question
The relationships at the Model level for these tables are as follows:
Project
public function rfi()
{
return $this->hasMany('App\Rfi');
}
RFI
public function project()
{
return $this->belongsTo('App\Project');
}
What I'm trying to achieve
In the RFI table I need a system generated number or essentially a count of RFI's. Where I'm finding the difficulty is that I need the RFI number/count to start again for each project. To clarify, please see the RFI table below which I have manually created with the the 'number' how I would like it displayed (notice it resets for each new project and the count starts from there).
Any assistance would be much appreciated!
Todd
So the number field depends on the number of project_id in the RFI table. It is exactly the number of rows with project_id plus one.
So when you want to insert a new row, you calculate number based on project_id and assign it.
RFI::create([
'project_id' => $project_id,
'number' => RFI::where('project_id', $project_id)->count() + 1,
...
]);
What I understood is that you want to set the value of the "number" field to "1" if it's a new project and "increment" if it's an existing project. And you want to automate this without checking for it every time you save a new row for "RFI" table.
What you need is a mutator. It's basically a method that you will write inside the desired Model class and there you will write your own logic for saving data. Laravel will run that function automatically every time you save something. Here you will learn more about mutators.
Use this method inside the "RFI" model class.
public function setNumberAttribute($value)
{
if(this is new project)
$this->attributes['number'] = 1;
else
$this->attributes['number']++;
}
Bonus topic: while talking about mutators, there's also another type of method called accessor. It does the same thing as mutators do, but just the opposite. Mutators get called while saving data, accessors get called while fetching data.

How to update multiple records in same table using .AfterUpdate data macro without error "A data macro resource limit was hit."

I have a table tblItems with a list of inventory items. The table has many columns to describe these items, including columns for SupplierName, SupplierOrderNumber and PredictedArrivalDate.
If I order several new items from a supplier, I will record each item separately in the table with the same supplier name, order number and a predicted arrival date.
I would like to add a data macro, so that if I update the PredictedArrivalDate for one record, the value will be copied to the PredictedArrivalDate column of other records/items with the same SupplierName AND SupplierOrderNumber.
The closest I've got is:
SetLocalVar (MySupplierName, [SupplierName])
SetLocalVar (MySupplierOrderNumber , [SupplierOrderNumber ])
SetLocalVar (MyPredictedArrivalDate, [PredictedArrivalDate])
For Each Record in tblItems
Where Condition = [SupplierOrderNumber] Like [MySupplierOrderNumber] And [SupplierName] Like [MySupplierName] And [PredictedArrivalDate]<>[MyPredictedArrivalDate]
Alias OtherRecords
EditRecord
SetField ([OtherRecords].[PredictedArrivalDate], [MyPredictedArrivalDate])
End EditRecord
However, when I run this, only 5 records update, and the error log reports error -20341:
"A data macro resource limit was hit. This may be caused by a data
macro recursively calling itself. The Updated() function may be
used to detect which field in a record has been updated to help
prevent recursive calls."
How can I get this working?
I'm not one for using macro's to do anything, so I'd use VBA and recordsets/an action query to do the updating.
You can call a user-defined function inside a data macro by setting a local var equal to its result.
Access doesn't like data macros triggering themselves (which you are doing, you're using an on update macro and updating fields in the same table on a different record), because there is a risk of accidentally creating endless loops. Looks like you triggered a measure that's made to prevent this. I'd try to avoid that as much as possible.
Note: using user-defined functions inside data macros can cause problems when you're linking to the table from outside of Access (via ODBC for example).
This isn't a good solution (it's not a data macro), but it does work as a temporary fix.
I created an update query called "updatePredictedArrivalDate":
PARAMETERS
ItemID Long,
MyPredictedArrivalDate DateTime,
MySupplierName Text ( 255 ),
MySupplierOrderNumber Text ( 255 );
UPDATE tblItems
SET tblItems.PredictedArrivalDate = [MyPredictedArrivalDate]
WHERE (((tblItems.SupplierName) = [MySupplierName])
AND ((tblItems.SupplierOrderNumber) = [MySupplierOrderNumber])
AND ((tblItems.ID) <> [ItemID]));
On the PredictedArrivalDate form field .AfterUpdate event, I then added this macro:
IF [PredictedArrivalDate].[OldValue]<>[PredictedArrivalDate] Or [PredictedArrivalDate]<>""
OpenQuery (updatePredictedArrivalDate, Datasheet, Edit, [ID], [PredictedArrivalDate], [SupplierName], [SupplierOrderNumber])
I now have to remember to add this .AfterUpdate event to any other forms I create that amend that particular field.
If anyone has a better solution, please let me know.

how to set a multi-column unique in web2py

In order to make many to many relation ship I make a middle table to combine two tables ,the tables like this:
db.define_table('problem',
Field('task_id','reference task'),
Field('title','string',unique=True,length=255))
db.define_table('task',
Field('title','string',unique=True,length=255),
Field('course_id','reference courses'))
db.define_table('belong',
Field('task_id','reference task'),
Field('problem_id','reference problem')
)
db.belong.task_id.requires=IS_IN_DB(db,'task.id','%(title)s')
db.belong.problem_id.requires=IS_IN_DB(db,'problem.id','%(title)s')
I use SQLFORM to insert into belong table.I want there are no duplicate task and problem. suppose there is a record like (1,task1,problem1)already exist in belong table,then if I choose task1 in SQLFORM,how to make the problem_id dropdown list not to show problem1. I have found similar question here
and do some test like the following in db.py:
test1:
db.belong.problem_id.requires=IS_NOT_IN_DB(db(db.belong.task_id==request.vars.task_id),'belong.problem_id').
test2:
db.belong.problem_id.requires=IS_NOT_IN_DB(db(db.belong.task_id==request.vars.task_id),'problem.id','%(title)s').
test3:
def my_form_processing(form):
a = form.vars.task_id
b=form.vars.problem_id
query=(db.belong.task_id==a)&(db.belong.problem_id==b)
if query :
form.errors.a= 'the record has existed'
def assignproblem():
form=SQLFORM(db.belong)
if form.process(onvalidation=my_form_processing).accepted:
response.flash='form accepted'
elif form.errors:
response.flash='form has errors'
else:
response.flash='please fill out the form'
return dict(form=form)
but it still not been solved.
If you want the choices in the problem_id dropdown to change dynamically based on the task_id selection, then you will need to use JavaScript (and likely make an Ajax request to populate the dropdown). For possible solutions, see this answer.
As for your tests above, test1 should do the proper validation, but only after the form has been submitted (i.e., the form will allow any combination of task_id and problem_id to be selected but will then report an error if a duplicate combination has been submitted).
test3 does not work as is because the query object just specifies the database query without actually doing a select from the database. Instead, you must call the .select() method, or more simply, the .count() method:
if db((db.belong.task_id == a) & (db.belong.problem_id == b)).count():
form.errors.a= 'the record has existed'

Can I specify a set of base parameters for a Linq-to-sql DataContext?

I have a LINQ-to-SQL DataContext that represents a parent-child relationship of Products to Prices. I'm iterating through a list of products and retrieving the prices for each one. The problem is that the tables behind both the Products and Prices contain a list of Products or Prices for multiple environments, determined by a 3 field complex key. I want to retrieve the Products and Prices for only one of those environments.
I can do this be specifying a long where clause in each LINQ query consisting of the product key and the complex environment key, something like this:
var price = ( from condition in conditiontype where condition.MaterialNumber == material && condition.Client == "400" && condition.SalesOrg == "1000" && condition.DistributionChannel == "10" select condition.ConditionDetails[0].ConditionValue );
what I'd like to be able to do is to specify the Client, SalesOrg, and DistributionChannel globally for the DataContext so that all I need to specify in the query itself is the Product ID (MaterialNumber). That way when I starting querying our Production environment a simple change to the DataContext will change what environment I'm querying.
Is this possible? Either a brief code sample or pointers to the background theory would be wonderful!
You could have a pre-written Expression<T> which you then have those values in it:
public Expression<Func<int>> GetPrices = p => // do Lambda here
Alternatively you can put properties into your DataContext (remember, it's a partial class so it's easy to extend) which you set and are then read in by your expression.