Django models: set value before saving - django

I have a model for which I would be able to set a value automatically before saving it to the database... so far I did override save() in this way:
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
if not self.paramX:
self.paramX = value
super(Post, self).save(force_insert, force_update, using, update_fields)
Anyway, this does not work using bulk_create()... what can I do? (I'm trying using Signals but with no luck)

Extract from the documentation : (https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create)
The model’s save() method will not be called, and the pre_save and post_save signals will not be sent.
It is because the bulk saving method use an other way to save the data. And so a way is to manually do it as you create each entry to insert.

My preference would be the following:
class Instrument(models.Model):
name = models.CharField(max_length=20)
def __init__(self, *args, **kwargs):
super(Instrument, self).__init__(*args, **kwargs)
self.name = "Bass"
Edit:
I just re-read your question. If you're only concerned with whether or not the “paramX” field is set upon saving, couldn't you just add a “default” to the model field? i.e.
class Instrument(models.Model):
name = models.CharField(max_length=20, default="No instrument")

Related

Trying to do a calculation on django models

i have two integer fields that i want to divide to get the value of 3rd field.
#property
def Pallets_Count(self):
return self.CASES/self.CasesPerPallet
but the result in the database always shows null .
#property
def Pallets_Count(self):
return self.CASES/self.CasesPerPallet
#property will not save anything into your model field. It works like a method. You can call in in your template like a model field mypost.Pallets_Count.
If you want to put the result into a database field, you need to override save method. But this might not be necessary. Property most likely is enough.
class MyModel(models.Model):
# your other fields
fieldname = models.FloatField()
def save(self, *args, **kwargs):
self.fieldname = self.CASES/self.CasesPerPallet
super(MyModel, self).save(*args, **kwargs)

How to auto fill SlugField instead of overriding save()?

Hello Awesome People
I wonder if there is a way to generate slug, rather than overriding the save() methods of my models.
Here's how I used to do:
def save(self, *args, **kwargs):
if self.pk is None:
self.slug = create_slug(self)
super(ModelName, self).save(*args, **kwargs)
create_slug is a function that generates the slug with slugify
def create_slug(instance,new_slug=None,field="name"):
''' long stuff to ensure the slug is unique '''
return slug
As django can do in Django Admin by automatically filling the slug field. Possible that we can simply add
an additional argument models.SlugField(field='name'). by adding this argument, django will make sure to take the value of field = name before saving to generate the slug without always overriding the save() method by copy/paste a lot of code to generate a slug for each model that We have.
I'm a little tired of copying this for all models, any hint will help!
Thank you in advance!
No, there is no such argument on model level. You can do it on admin level using prepopulated_fields:
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
On the model level you can write custom mixin class and use it as parent for all models:
class SlugMixin:
def create_slug(instance,new_slug=None,field="name"):
''' long stuff to ensure the slug is unique '''
return slug
def save(self, *args, **kwargs):
if self.pk is None:
self.slug = create_slug(self)
super().save(*args, **kwargs)
class SomeModel(SlugMixin, models.Model):
...
class OtherModel(SlugMixin, models.Model):
...
In this case you don't need to implement create_slug and override save in each models.

Before save model check some field

I need to check if other models already created, have a field filled .
If another model has the field with any value, the current model that attempts to create should not happen. And if possible send an error message.
This is my current code:
class Video(models.Model):
#####
# Fields of model
#####
def save(self, force_insert=False, force_update=False, *args, **kwargs):
some_video = Video.objects.all().filter(field_boolean=True).first()
if not some_video:
# Save current model
super(Video, self).save(force_insert, force_update, *args, **kwargs)
else:
# avoid save method for the current model created and send error message
What am I doing wrong or what I'm missing? What is the correct way to do this?
Firstly, you do not need to use all() and filter() together. Secondly, use exists() instead of first(). It returns True if the QuerySet contains any results, and False if not. This tries to perform the query in the simplest and fastest way possible.
class Video(models.Model):
name = models.CharField(max_length=30)
field_boolean = models.BooleanField()
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if Video.objects.filter(field_boolean=True).exists():
print('Video with field_boolean=True exists')
else:
super(Video, self).save(*args, **kwargs)

Prevent shell from saving attribute in Django

I have an attribute on a model that I don't want another developer to be able to go into the Django shell and change. Anyone know how to do this? I tried overwriting the save method on that model but I can't determine if that attribute has been changed.
Well I figured out how to accomplish this. Another developer could always change the code but this raises an error saying that's not what they're supposed to do.
class myModel(models.Model):
uuid = UUIDField('UUID', primary_key=True, default=uuid4)
model_type = models.ForeignKey(ModelType)
# override the Press model __init__ method to store initial press_type
def __init__(self, *args, **kwargs):
super(myModel, self).__init__(*args, **kwargs)
self.__model_type = self.model_type
# override the save method to prevent updates to press_type
def save(self, *args, **kwargs):
# raise an exception if press_type was changed since initialized
if self.pk and self.__model_type != self.model_type:
raise Exception('The model_type field cannot be changed once set.')
super(myModel, self).save(*args, **kwargs)

Does a model's save() method get called when using loaddata for fixtures?

I'm trying to generate an automatic slug for a model whenever it is empty, from another field. This is the code:
class Position(RichText):
name = models.CharField(max_length=200)
slug = models.SlugField(null=True)
def position_description(self):
return self.content
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super(Position, self).save(*args, **kwargs)
When I load initial fixtures with loaddata, it seems the save() method is never triggered. Is this normal behavior? How can I catch fixtures too?
This is normal behavior, from the documentation:
When fixture files are processed, the data is saved to the database as
is. Model defined save methods and pre_save signals are not called
.