Reputation: 5840
So I have a Django model which has few non nullable field with default values.
class Article(models.Model):
id = models.UUIDField(default=uuid4, primary_key=True, editable=False)
code = models.CharField(max_length=200, default=uuid4, unique=True, null=False)
company = models.CharField(max_length=200, default=uuid4, unique=True, null=False)
Now i want to do a
Article.objects.get_or_create(company=company, code=am_row['Article code'])
But here the issue is am_row['Article code']
or company
can be a None
, and in that case i just want a new model to be created using that fields default values.
Currently passing None throws a NOT NULL constraint failed
error. How can i achieve this?
So i think this boils down to achieving
Article.objects.create(company=company, code=am_row['Article code'])
Upvotes: 2
Views: 7385
Reputation: 51988
You can override the get_or_create
method in your model manager, like this:
class CustomManager(models.Manager):
def get_or_create(self, **kwargs):
defaults = kwargs.pop('defaults', {}) # popping defaults from values
for key, value in kwargs.items():
if value == None:
kwargs[key] = defaults.get(key)
return super(CustomManager, self).get_or_create(**kwargs)
class Article(models.Model):
# ...
objects = CustomManager()
Then use it in your view like this:
Article.objects.get_or_create(
company=company,
code=am_row.get('Article code'),
defaults={
'company': uuid.uuid4(),
'code': uuid.uuid4()
}
)
If you want the default functionality of get_or_create
, then use:
objects = Article._base_manager
objects.get_or_create(...)
Upvotes: 2
Reputation: 4146
I'd use or
operator in this case. Look at the example. If x
is None
some default value will be passed:
In [1]: import uuid
In [2]: def some_function(something):
...: print(f'Something is {something}')
...:
In [3]: x = None
In [4]: some_function(x or uuid.uuid4())
Something is 518d7187-f74d-4620-90de-6104698a7d07
In [5]: x = 'Hello, world!'
In [6]: some_function(x or uuid.uuid4())
Something is Hello, world!
Upvotes: 1