I am trying to create an object and assigning a foreign-key from an input field but i am getting a bizarre error, i have tried to assign it using the id, the name but nothing seems to work, any help will be much appreciated.
This is the model :
class Node(MPTTModel):
parent = TreeForeignKey('self', on_delete=models.CASCADE, blank=True, null=True, related_name='children')
name = models.TextField(blank=True, null=True)
This is the form field :
<input type="hidden" name="parent" value="{{ current_tree }}" />
This is the view :
get_node_parent = request.POST.get('parent', '').strip()
Node.objects.create(parent=get_node_parent)
Every time i try to create the model i have the message that it must be a Node instance.
Your Node constructor expects a Node object as parent. Since your parent contains the .name field of that Node, you thus first need to fetch that node, like:
parent_name = request.POST.get('parent')
node_parent = None
if parent_name is not None:
node_parent = Node.objects.get(name=parent_name)
Node.objects.create(parent=node_parent)
We thus first retrieve the value for 'parent'. If such value exists, we thus fetch the given Node for that name with Node.objects.get(name=...). Then we can create the new Node with the given name.
Note that you probably want to set a name as well, and make the name field unique=True, since otherwise using a name will not be sufficient to "identify" the Node object.
Related
I have a simple model:
class Item(models.Model):
user = ForeignKey(User, related_name="user_items")
users = ManyToManyField(User, related_name="users_items")
I want it so that when a user creates an Item via ViewSet, that user is automatically assigned to the user and users fields.
I typically do this for ForeignKey's via the ViewSet's perform_create:
class ItemViewSet(viewsets.ModelViewSet):
...
def perform_create(self, serializer):
if self.request.user.is_authenticated:
serializer.save(user=self.request.user)
else:
serializer.save()
When I try to do it for the ManyToManyField too, I get this error:
{'users': [ErrorDetail(string='This list may not be empty.', code='empty')]}
I've tried the following in perform_create():
# 1
serializer.save(user=self.request.user, users=self.request.user)
# 2
serializer.save(user=self.request.user, users=[self.request.user])
# 2
serializer.save(user=self.request.user, users=[self.request.user.id])
How can I update a ManyToManyField via a ViewSet's perform_create?
Edit:
I guess the following works:
obj = serializer.save(user=self.request.user)
obj.users.add(self.request.user)
Is there no way to have the M2M field when the object is initially created though?
when you want set a list to m2m field one of the things you can do is this:
item_obj.users.set(user_list)
probably you need first get your item_obj.
for this you can get your object id from item_id = serializer.data.get('id') , and then item_obj = Item.objects.get(id = item_id)
I wanted to iterate over all products and calculate list_price from another field.
this is the code that I wrote:
class AedPriceCalculator(models.TransientModel):
_name = "aed.pricecalculator"
_inherit = ['product.template']
aed_current_price = fields.Monetary('current AED price in IRR', required=True, translate=True)
currency_id = fields.Many2one(
'res.currency', 'Currency',default=lambda self: self.env['res.currency'].search([('name', '=', 'AED')]).id,readonly=True)
#api.multi
def price_calculate_ae(self):
products = self.env['product.template'].search(['sale_ok', '=' ,True])
for product in products:
if product.amount_in_aed:
product.list_price = self.aed_current_price * product.amount_in_aed
else:
pass
but when I call the related button.
this error will appear:
The operation cannot be completed:
- Create/update: a mandatory field is not set.
- Delete: another model requires the record being deleted. If possible, archive it instead.
Model: aed.pricecalculator (aed.pricecalculator), Field: Name(name)
aed.pricecalculator model inherit from product.template and the name field is required in product template (copied as-is).
When you click on the button and call price_calculate_ae method, Odoo will try to call the create method without providing a value for name field and that's why you see this error message.
You don't need to inherit product.template to iterate over all products and calculate list_price
I'm trying (and failing) to figure out how to use pyvmomi to retrieve a custom attribute named "owner" for all VMs in a vCenter.
I use code like this to retrieve VM name, power state, and uuid:
summary = vm.summary
print(summary.config.name, " ", summary.runtime.powerState, " summary.config.uuid)
But, I cannot figure out how to retrieve the custom attribute named "owner" for all VMs in a vCenter.
Thanks in advance
CustomAttribute is stored separately in customValue field. Each customValue have its name and key, the "Owner" in your case is the name, you need to get its key first.
here is a sample:
conn=connect.SmartConnect(host='***', user='***', pwd='***', port=443)
content = conn.RetrieveContent()
cfm = content.customFieldsManager
required_field = ["Owner"]
my_customField = {}
for my_field in cfm.field:
if my_field.name in required_field:
my_customField[my_field.key]=my_field.name
The key and its display name is in my_customField dict, you can get customValue by it
for opts in vm.customValue:
if opts.key in my_customField:
output[my_customField[opts.key]]=opts.value
and in output dict you have what you want.
I have the following Model:
class Message(models.Model):
parent = models.ForeignKey('self', related_name='parent_msg', null=True)
(...)
And I do the following to create a new message:
(...)
parent_msg = Message.objects.get(id = message_id)
m = Message(..., parent = parent_msg)
m.save()
But the parent_id field is always being set to NULL on the database.
The documentation says "If True, Django will store empty values as NULL in the database," but I know parent_msg is not empty, so what am I doing wrong?
The problem is not with model definition. But with insertion code.
can you please post complete code so that it can be verified. And what version of django are you using.
I just have a hunch about this. But if feels like I'm doing it the wrong way. What I want to do is to have a db.StringProperty() as a unique identifier. I have a simple db.Model, with property name and file. If I add another entry with the same "name" as one already in the db.Model I want to update this.
As of know I look it up with:
template = Templates.all().filter('name = ', name)
Check if it's one entry already:
if template.count() > 0:
Then add it or update it. But from what I've read .count() is every expensive in CPU usage.
Is there away to set the "name" property to be unique and the datastore will automatic update it or another better way to do this?
..fredrik
You can't make a property unique in the App Engine datastore. What you can do instead is to specify a key name for your model, which is guaranteed to be unique - see the docs for details.
I was having the same problem and came up with the following answer as the simplest one :
class Car(db.Model):
name = db.StringProperty(required=True)
def __init__(self,*args, **kwargs):
super(Car, self).__init__(*args, **kwargs)
loadingAnExistingCar = ("key" in kwargs.keys() or "key_name" in kwargs.keys())
if not loadingAnExistingCar:
self.__makeSureTheCarsNameIsUnique(kwargs['name'])
def __makeSureTheCarsNameIsUnique(self, name):
existingCarWithTheSameName = Car.GetByName(name)
if existingCarWithTheSameName:
raise UniqueConstraintValidationException("Car should be unique by name")
#staticmethod
def GetByName(name):
return Car.all().filter("name", name).get()
It's important to not that I first check if we are loading an existing entity first.
For the complete solution : http://nicholaslemay.blogspot.com/2010/07/app-engine-unique-constraint.html
You can just try to get your entity and edit it, and if not found create a new one:
template = Templates.gql('WHERE name = :1', name)
if template is None:
template = Templates()
# do your thing to set the entity's properties
template.put()
That way it will insert a new entry when it wasn't found, and if it was found it will update the existing entry with the changes you made (see documentation here).
An alternative solution is to create a model to store the unique values, and store it transationally using a combination of Model.property_name.value as key. Only if that value is created you save your actual model. This solution is described (with code) here:
http://squeeville.com/2009/01/30/add-a-unique-constraint-to-google-app-engine/
I agree with Nick. But, if you do ever want to check for model/entity existence based on a property, the get() method is handy:
template = Templates.all().filter('name = ', name).get()
if template is None:
# doesn't exist
else:
# exists
I wrote some code to do this. The idea for it is to be pretty easy to use. So you can do this:
if register_property_value('User', 'username', 'sexy_bbw_vixen'):
return 'Successfully registered sexy_bbw_vixen as your username!'
else:
return 'The username sexy_bbw_vixen is already in use.'
This is the code. There are a lot of comments, but its actually only a few lines:
# This entity type is a registry. It doesn't hold any data, but
# each entity is keyed to an Entity_type-Property_name-Property-value
# this allows for a transaction to 'register' a property value. It returns
# 'False' if the property value is already in use, and thus cannot be used
# again. Or 'True' if the property value was not in use and was successfully
# 'registered'
class M_Property_Value_Register(db.Expando):
pass
# This is the transaction. It returns 'False' if the value is already
# in use, or 'True' if the property value was successfully registered.
def _register_property_value_txn(in_key_name):
entity = M_Property_Value_Register.get_by_key_name(in_key_name)
if entity is not None:
return False
entity = M_Property_Value_Register(key_name=in_key_name)
entity.put()
return True
# This is the function that is called by your code, it constructs a key value
# from your Model-Property-Property-value trio and then runs a transaction
# that attempts to register the new property value. It returns 'True' if the
# value was successfully registered. Or 'False' if the value was already in use.
def register_property_value(model_name, property_name, property_value):
key_name = model_name + '_' + property_name + '_' + property_value
return db.run_in_transaction(_register_property_value_txn, key_name )