I have quite unique problem with django.
Im providing website users interface for editing large data. Each row on this data represents a row in database. Or one object of certain Type.
Users click on cells in the table and form opens where they can edit this fields/column value.
In essence it works like this:
1) based on where user clicks, query is sent to server containting object id and the field that he is editing.
2) based on this information form is created on the fly:
class FieldEditorForm(forms.ModelForm):
class Meta:
model = MyObject
fields = ['id', field ]
Notice the field there is Variable not name of the field.
3) this field passes its own modelform validation and all is fine. in save method Model.save() is enough to update the value.
But now to the problem. Sometimes empty value is sent to server in this form. Empy value such as u'' or almost emtpty like u' '. I want to repace this with None so NULL would be saved to database.
There are two places where i could do that. In field validation modifying the cleaned_data or in form save method.
Both approaches raise unique problem as i dont know how to create variable function names.
def clean_%(field)s():
or in case of form save method
r.%(field)s = None
is what i need, but those methods dont work. So how can i create method name which is variable or set objects variable parameter to something. Is it even possible or do i have to rethink my approach there?
Alan
In the latter case, setattr(r, field + 's', None).
Related
I want to implement this structural model to store my data on Mongodb with MongoEngine on flask:
skills = [{"asm":"Assembly",
"flag":False,
"date": datetime},
{"java":"Java",
"flag":False,
"date": datetime}]
So I don't know how I can declare and update this kind of structure.
For updating one object I used:
User.objects(skills=form.skills.data).update_one()
However, I don't know how to update more fields in one shot.
I tried with the code below but it doesn’t work.
now = datetime.now()
User.objects(skills=form.skills).update_one(set__skills = ({'ruby':'Ruby'}, {'flag':'true'},{'date':now}))
What kind of fields should I declare on forms.py?
For what I understood, you need a a nested document (skills) into another (who refers to User in this case). For doing something like this you don't have to update atomically a field but append values to the subdocument and the save everything.
Tryin' to follow your example, in your case should do something like this:
user = User.objects(email=current_user.email).get()
To get the BaseQuery that refers to user X through a certain query filter, in my example the email of the current logged user
user.kskills.append(SubDocumentClass(skillName="name_of_the_skill", status=True, date=datetime.now()))
For append a collection to the subdocument list. (I've appended your field)
user.save()
To save everything
I have created a module which modifies other one (named base). In the module base there is the res.partner model, and in this model there is the field birthdate:
_columns = {
...
'birthdate': fields.char('Birthdate'),
...
}
What I do in my module is to overwrite this field to make it of type Date:
birthdate = fields.Date('Birthdate')
Everything seems OK, but, after updating the Odoo server, the data introduced in that column dissapears from the view, and when I check the database, I find that the column birthdate is being duplicated with other names like birthdate_moved0, birthdate_moved1, birthdate_moved2, etc... (and half of them are of type char and the other half of type date). The values stored in birthdate are being moved to these other columns (that's the reason bacause I can't see the data in the view, since in the form only birthdate is being shown).
However, I was able to overwrite several fields through Python. But this duplication problem happened me with the field birthdate and the field function of the model res.partner.
I can't come to a conclussion. Can anyone help me here, please? Thank you in advance!
You should name your "new" field 'birth_date' or 'dob' or anything other than 'birthday' just to avoid changing existing field data type. In next step you can copy values from current 'birthday' field to new one (through postgresql).
Finally, a co-worker shown me the solution:
It's not about Odoo, it's due to PostgreSQL. Generally, in PostgreSQL, is not possible to alter the data type of a column (even when this is empty), except for some cases, like for example:
From integer to char: because the casting to char is possible. Therefore, in Odoo, when you change the data type of a field.Date, a field.Integer, a field.Many2one, etc... to a fields.Char, there is no problem. However, if you try to change a fields.Char to fields.Date or fields.Many2one, or whatever, PostgreSQL is going to duplicate the column because is not ready for that type of casting.
That's the reason because I wasn't able to change a field of type Char and transform it in a field of kind Date (my attempt with birthdate) or Many2one (my attempt with function). And on the other hand, I was able to overwrite a Selection field (actually, in PostgreSQL is convert a Char into another Char).
So in conclusion:
If you are going to change the type of data of a field, check if the final kind of data is char (fields.Char, fields.Selection, etc...) or other possible casting. Then you can name the new field with the same name as before. If not, you must name the new field with other name, otherwise PostgreSQL will duplicate the column with name_moved0, name_moved1, etc...
I hope this helps to anyone!!
I want to filter data based on multiple fields in Django python. The scenario is, if a GET request to webserver comes as /searchStudent/?firstName=&lastName=xyzage=23&class=&city= and we dont know what can be the possible parameter in query string, some of them can come with value and some variable doesnot comes with value. The question is, is there any to get the variable which have only value or which dont have values from request. I know we can simply getting value by using request.GET.get('city') but I am finding way for getting the non null variable from query string, is there any way to find the non value variable from query string? In above scenario city, class, and firstName doesn't have values and I dont want to add it on filter. what will be the right approach? please suggest the right way.
To get a dict of non-empty query parameters use this code:
non_empty_params = dict((field, value)
for field, value in request.GET.iteritems() if value)
But do not build queryset this way. You should never ever trust data from the user input. So you have to have a list of fields to search and use this list to filter out incorrect field names:
fields = ('firstName', 'lastName', 'age', 'class', 'city', )
filter_params = dict((field, value)
for field, value in request.GET.iteritems()
if value and field in fields)
students = Student.objects.filter(**filter_params)
I did this way and I get answer for filtering dynamically
filter_args={}
if request.GET.get('firstName') :
filter_args['firstName']=request.GET.get('firstName')
if request.GET.get('lastName') :
filter_args['lastName']=request.GET.get('lastName')
if request.GET.get('city') :
filter_args['city']=request.GET.get('city')
Student.object.filter(**filter_args)
This is know as Dynamic Queries, I was not aware with this. Thanks #catavaran, for suggesting concept. also refered this link Dynamic Django Queries
I have a model based on ndb, while saving it, I stored 'id' field with current logged-in user's user id. (Why I am doing this? Actually this model used to be based on db.Model and key_name has this user's id. Now, I am converting it to ndb)
m= Modelclass(id = str(users.get_current_user().used_id()),
--- Other fields ---
m.put()
This model's edit form sends this 'id' and I wanted to get corresponding 'key' from it. But, I got "Key id number is too long; received 'some big_number'". Tried both ways
Modelclass.get_by_id(<id>).key
OR
ndb.Key('Modelclass', <id>)
This is one case, there may be other cases where user can store some big number in 'id' field. In these scenarios, we can't extract key from 'id'. So, how to solve such a problem.
I am new to ndb. Thanks for any help.
Looks like your value is an int, not a string. But you converted it into a string when creating the entitiy. There's a simple solution:
ndb.Key('Modelclass', str(<id>))
Good luck!
MongoDB is using string(hash) _id field instead of integer; so, how to get classic id primary key? Increment some variable each time I create my class instance?
class Post(Document):
authors_id = ListField(IntField(required=True), required=True)
content = StringField(max_length=100000, required=True)
id = IntField(required=True, primary_key=True)
def __init__(self):
//what next?
Trying to create new user raises exception:
mongoengine.queryset.OperationError: Tried to save duplicate unique keys
(E11000 duplicate key error index: test.user.$_types_1_username_1
dup key: { : "User", : "admin" })
Code:
user = User.create_user(username='admin', email='example#mail.com',
password='pass')
user.is_superuser = True
user.save()
Why?
There is the SequenceField which you could use to provide this. But as stated incrementing id's dont scale well and are they really needed? Can't you use ObjectId or a slug instead?
If you want to use an incrementing integer ID, the method to do it is described here:
http://www.mongodb.org/display/DOCS/How+to+Make+an+Auto+Incrementing+Field
This won't scale for a vary large DB/app but it works well for small or moderate application.
1) If you really want to do it you have to override the mongoengine method saving your documents, to make it look for one document with the highest value for your id and save the document using that id+1. This will create overhead (and one additional read every write), therefore I discourage you to follow this path. You could also have issues of duplicated IDs (if you save two records at the exactly same time, you'll read twice the last id - say 1 and save twice the id 1+1 = 2 => that's really bad - to avoid this issue you'd need to lock the entire collection at every insert, by losing performances).
2) Simply you can't save more than one user with the same username (as the error message is telling you) - and you already have a user called "admin".