When does .save() create an object? - python

I have the code:
name = MakesiteNameForm(datdict)
if name.is_valid:
name.save()
datsite = Makesite.objects.get(sitename=request.POST['sitename'])
datsite.ref_id.add(RefID.objects.create(url=request.POST['url'],description=request.POST['description']))
datsite.save()
So i have this bit of code what I want to use to create and save some manytomany items but when I try using this method is says that Makesite matching query does not exist. which i think means it hasn't saved but then later I call site = Makesite.objects.all() and I can clearly see the value of what request.POST['sitename'] is sitting inside the querydict. So is there anyway to query this better? or is there something about the save() i missing?
Edit: that form saves a value sitename values into the Makesite table

The save() call doesn't create objects, it just saves the object to the database, inserting a new row in case it's a new object, or updating it.
First, form.is_valid() is a method, but you're not calling it, so you're always trying to save name. That may or may not be related to your error, but it's wrong anyway, and maybe that's where the query error is coming from, not the get() call below. Fix it and see what happens.

Related

is there an easier way to either create or re-write exist object? django

I know in django we can create an object model easily by using something like this
AbcModel.objects.create(field1='a', field2='b')
But this would create the object even if it already exists.
I know I can use filter() then use the exist() to check if the object already exist then decide to update or create.
But is there an easier and faster way to do this? Since, there is get_or_create so I am curious if there's something similar.
Thanks in advance
EDIT:
I thought of something like this
new = AbcModel.objects.create(field1='a')
new[0].field2 = 'c'
new[0].save()
There might be more fields and field1 will not always be a would be others like b, c and maybe a again.
Just being curious if there is an easier faster way and not saying get_or_create wouldn't get what I want / need
As you said about get_or_create, you could do:
abc_instance, created = AbcModel.objects.get_or_create(field1='a', field2='b')
That would bring you the existent/created object as the first argument and a boolean as the second argument, that defines if it was got or created.
Additionally, field1 and field2 will be used for the filter, but you can set the defaults attribute, which will update the existing entry or be used for its creation.
abc_instance, created = AbcModel.objects.get_or_create(
field1='a', field2='b',
defaults={'field3': 'c', 'field4': 'd'}
)
You can use update_or_create: https://docs.djangoproject.com/en/2.0/ref/models/querysets/#update-or-create
However if the field you filter by is not unique, you might end up getting a MultipleObjectsReturned exception.
Another way to do this could be:
num_updated = AbcModel.objects.filter(field1='a').update(field2='c')
if num_updated == 0:
model = AbcModel.objects.create(field1='a', field2='c')
In num_updated you will have the number of rows updated in the first line of code.
I hope this helps a bit!

Odoo v9 - Using Onchange, how do you clear what is already entered in a field?

I am extending product.template, and I've added a field called uom_class. When I change this field when editing a product, I'd like to clear what is entered in the Many2One field called "Unit of Measure" (uom_id in product.template). I am doing this because I am also changing the domain for the uom_id, and the existing selection ("Units" by default) will probably not be in that domain.
I've tried the following, as suggested for earlier versions, but it did not work.
#api.onchange('uom_class')
def onchange_uom_class(self):
# [...] not shown: previously set new domain for uom_id
result['value'] ={'uom_id':False}
return result
I've seen other posts suggest I need to add assign it an empty product.uom record, but I have no idea how to do that. Any help would be greatly appreciated.
Well, I figured this one out.
I just declared
uom_id = False
For some reason, returning the domain works, but not returning the value. Either that, or I just have no idea what I'm doing and I'm returning the value wrong... which is entirely possible.

Django method same object not saving

This is something I have been trying to solve for 3 days now and I just can't get my head around it why this is not working.
I have a method that creates a new version of an Object. It used to work, that you would pass in the sou obj. and this would be the source from which a new version is created. You can also pass in a destination, which is not really important in this example. Now I wanted to add locking to this method as we want to add multiple users. So I want to be sure that I always have the most current object from which I create a new one. So I added a line that would just get the newest object. If there is no newer object in the database it would be the same anyway.
def createRevision(request, what, sou, destination=None, ignore = [], **args):
...
if "initial" not in args.keys():
source = get_object_or_404(BaseItem, ppk=sou.ppk, project=sou.project, current=True)
print "------------"
print source == sou
print "------------"
# This outputs True
else:
source = sou
further down in the method I do something like
source.current = False
source.save()
Basically the idea is that I pass in BaseItem and if I don't specify the "initial" keyword then I get the current item from that project with the same ppk (Which is a special random pk in conduction with current). I do this just to be on the save side, that I really have the most current object. And if it is the initial version I just use that one, as there can not be another version.
So now the problem is, that everything works fine if I use sou in this method. I can save it etc .. but as soon as I use source and initial is not in the args it just doesn't save it. The print statement tells me they are the same. Everything I print after the save tells me it has been saved but it just doesn't do it.
source.current = False
source.save()
print "SAVED !!!!"
print source.pk
print source.current
rofl = get_object_or_404(BaseItem, pk=source.pk, project=sou.project)
print rofl.pk
print source.current
outputs the same pk and the same current value but somehow it is not properly saved. As soon as I look into django admin or do a select current = True.
I really don't know what to do anymore.
Why does it work without a problem if I pass in the object into the method but starts to fail when I get the exact same object in the method?
Of course I call the method with the same object:
x = get_object_or_404(BaseItem, ppk=sou.ppk, project=sou.project, current=True)
createRevision(request, "", x)
Thank you pztrick for the hint with the caches. I finally solved it. So the problem was that I was doing:
x = get_object_or_404(BaseItem, ppk=sou.ppk, project=sou.project, current=True)
createRevision(request, "", x)
# .... loads of lines of code
unlock(x)
unlock is a method I wrote that just sets a timestamp so I know no other user is editing it. So now the problem was that I was saving x in createRevision with all the correct data but of course unlock(x) still had a reference to an "old" not updated object and of course was saving it again. Hence it was overwriting my changes in createRevision.
Thank you again to everyone who helped with this.
I think you may be running afoul of model manager caching which is intended to limit database queries. However, by invoking the .all() method on the model manager you force it to hit the databse again.
So, try this: Replace your argument from the BaseItem class to the model manager's .all() QuerySet:
source = get_object_or_404(BaseItem.objects.all(), ppk=sou.ppk, project=sou.project, current=True)
# ...
rofl = get_object_or_404(BaseItem.objects.all(), pk=source.pk, project=sou.project)
get_object_or_404 supports mode classes, model managers, or QuerySets as the first parameter so this is valid.

How to delete rows from a table using an SQLAlchemy query without ORM?

I'm writing a quick and dirty maintenace script to delete some rows and would like to avoid having to bring my ORM classes/mappings over from the main project. I have a query that looks similar to:
address_table = Table('address',metadata,autoload=True)
addresses = session.query(addresses_table).filter(addresses_table.c.retired == 1)
According to everything I've read, if I was using the ORM (not 'just' tables) and passed in something like:
addresses = session.query(Addresses).filter(addresses_table.c.retired == 1)
I could add a .delete() to the query, but when I try to do this using only tables I get a complaint:
File "/usr/local/lib/python2.6/dist-packages/sqlalchemy/orm/query.py", line 2146, in delete
target_cls = self._mapper_zero().class_
AttributeError: 'NoneType' object has no attribute 'class_'
Which makes sense as its a table, not a class. I'm quite green when it comes to SQLAlchemy, how should I be going about this?
Looking through some code where I did something similar, I believe this will do what you want.
d = addresses_table.delete().where(addresses_table.c.retired == 1)
d.execute()
Calling delete() on a table object gives you a sql.expression (if memory serves), that you then execute. I've assumed above that the table is bound to a connection, which means you can just call execute() on it. If not, you can pass the d to execute(d) on a connection.
See docs here.
When you call delete() from a query object, SQLAlchemy performs a bulk deletion. And you need to choose a strategy for the removal of matched objects from the session. See the documentation here.
If you do not choose a strategy for the removal of matched objects from the session, then SQLAlchemy will try to evaluate the query’s criteria in Python straight on the objects in the session. If evaluation of the criteria isn’t implemented, an error is raised.
This is what is happening with your deletion.
If you only want to delete the records and do not care about the records in the session after the deletion, you can choose the strategy that ignores the session synchronization:
address_table = Table('address', metadata, autoload=True)
addresses = session.query(address_table).filter(address_table.c.retired == 1)
addresses.delete(synchronize_session=False)

dreaded "not the same object error" pickling a queryset.query object

I have a queryset that I need to pickle lazily and I am having some serious troubles. cPickle.dumps(queryset.query) throws the following error:
Can't pickle <class 'myproject.myapp.models.myfile.QuerySet'>: it's not the same object as myproject.myapp.models.myfile.QuerySet
Strangely (or perhaps not so strangely), I only get that error when I call cPcikle from another method or a view, but not when I call it from the command line.
I made the method below after reading PicklingError: Can't pickle <class 'decimal.Decimal'>: it's not the same object as decimal.Decimal and Django mod_wsgi PicklingError while saving object:
def dump_queryset(queryset, model):
from segment.segmentengine.models.segment import QuerySet
memo = {}
new_queryset = deepcopy(queryset, memo)
memo = {}
new_query = deepcopy(new_queryset.query, memo)
queryset = QuerySet(model=model, query=new_query)
return cPickle.dumps(queryset.query)
As you can see, I am getting extremely desperate -- that method still yields the same error. Is there a known, non-hacky solution to this problem?
EDIT: Tried using --noreload running on the django development server, but to no avail.
EDIT2: I had a typo in the error I displayed above -- it was models.QuerySet, not models.mymodel.QuerySet that it was complaining about. There is another nuance here, which is that my models file is broken out into multiple modules, so the error is ACTUALLY:
Can't pickle <class 'myproject.myapp.models.myfile.QuerySet'>: it's not the same object as myproject.myapp.models.myfile.QuerySet
Where myfile is one of the modules under models. I have an __ini__.py in models with the following line:
from myfile import *
I wonder if this is contributing to my issue. Is there some way to change my init to protect myself against this? Are there any other tests to try?
EDIT3: Here is a little more background on my use case: I have a model called Context that I use to populate a UI element with instances of mymodel. The user can add/remove/manipulate the objects on the UI side, changing their context, and when they return, they can keep their changes, because the context serialized everything. A context has a generic foreign key to different types of filters/ways the user can manipulate the object, all of which must implement a few methods that the context uses to figure out what it should display. One such filter takes a queryset that can be passed in and displays all of the objects in that queryset. This provides a way to pass in arbitrary querysets that are produced elsewhere and have them displayed in the UI element. The model that uses the Context is hierarchical (using mptt for this), and the UI element makes a request to get children each time the user clicks around, we can then take the children and determine if they should be displayed based on whether or not they are included in the Context. Hope that helps!
EDIT4: I am able to dump an empty queryset, but as soon as I add anything of value, it fails.
EDIT4: I am on Django 1.2.3
This may not be the case for everyone, but I was using Ipython notebook and having a similar issue pickling my own class.
The problem turned out to be from a reload call
from dir.my_module import my_class
reload(dir.my_module)
Removing the reload call and then re-running the import and the cell where the instance of that object was created then allowed it to be pickled.
not so elegant but perhaps it works:
add the directory of the myfile -module to os.sys.path and use only import myfile in each module where you use myfile. (remove any from segment.segmentengine.models.segment import, anywhere in your project)
According to this doc, pickling a QuerySet should be not a problem. Thus, the problem should come from other place.
Since you mentined:
EDIT2: I had a typo in the error I displayed above -- it was models.QuerySet, not models.mymodel.QuerySet that it was complaining about. There is another nuance here, which is that my models file is broken out into multiple modules, so the error is ACTUALLY:
The second error message you provided look like the same as previous one, is that what you mean?
The error message you provided looks weird. Since you are pickling "queryset.query", the error should related to the django.db.models.sql.Query class instead of the QuerySet class.
Some modules or classes may have the same name. They will override each other then cause this kind of issue. To make thing easier, I will recommend you to use "import ooo.xxx" instead of "from ooo import *".
Your could also try
import ooo.xxx as othername

Categories

Resources