Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django doesn't call model clean method

Tags:

python

django

I have a view, which creates models from CSV file. I've added clean method to the model class definition, but it isn't called when model is created.

Here is example of models.py:

class Run(models.Model):     name = models.CharField(max_length=120)     tested_build = models.ForeignKey('apps.Build')     timestamp_start = models.DateTimeField()     timestamp_end = models.DateTimeField()  class CommonMeasurement(models.Model):     timestamp = models.DateTimeField()     value = models.FloatField()     run = models.ForeignKey(Run)      def clean(self):         super(CommonMeasurement, self).clean()         print 'here we go'         if self.timestamp < self.run.timestamp_start or self.timestamp > self.run.timestamp_end:             raise django_excetions.ValidationError('Measurement is outside the run')   class ClientMeasurement(CommonMeasurement):     metric = models.ForeignKey(ClientMetric)     account = models.CharField(max_length=120, blank=True) 

Here is my Form View code examples:

class BaseMeasurementsUpload(generic_views.FormView):     template_name = 'upload.html'     models_to_upload = None         def get_success_url(self):         return self.request.get_full_path()      def form_valid(self, form):         uploader = getattr(importers, form.cleaned_data['uploader'])         try:             the_uploader = uploader(form.cleaned_data, self.models_to_upload)             upload_results = the_uploader.get_result_info()         except django_exceptions.ValidationError as e:             custom_errors = e         return render_to_response(self.template_name,                                   {'upload_results': upload_results,                                    'custom_errors': custom_errors},                                   context_instance=RequestContext(self.request))   class ClientMeasurementsUploadView(BaseMeasurementsUpload):     form_class = forms.ClientMeasurementsUploadForm     models_to_upload = models.ClientMeasurement      def get_form(self, form_class):         uploaders = (('MeasurementsSimpleCsv', importers.MeasurementsSimpleCsv.__doc__),                      ('ClientMeasurementsBulkCsv', importers.ClientMeasurementsBulkCsv.__doc__,))         if self.request.POST:             # get bound form             return self.form_class(uploaders,                                    self.request.POST,                                    self.request.FILES)         else:             return forms.ClientMeasurementsUploadForm(uploaders) 

importers perform actual validation and call create method for each model.

like image 805
Nikolai Golub Avatar asked Sep 14 '13 15:09

Nikolai Golub


People also ask

Does Django save call clean?

save() calls the clean. This way the integrity is enforced both from forms and from other calling code, the command line, and tests. Without this, there is (AFAICT) no way to write a test that ensures that a model has a FK relation to a specifically chosen (not default) other model.

Is Clean called before save Django?

Note that full_clean() will NOT be called automatically when you call your model's save() method. You'll need to call it manually if you want to run model validation outside of a ModelForm.

What does Django DB models model clean () do?

This method will validate all fields on your model. The optional exclude argument lets you provide a set of field names to exclude from validation. It will raise a ValidationError if any fields fail validation. The second step full_clean() performs is to call Model.

What is __ str __ in Django?

str function in a django model returns a string that is exactly rendered as the display name of instances for that model.


2 Answers

To call the model clean method we will override save method. Check the link: https://docs.djangoproject.com/en/2.0/ref/models/instances/#django.db.models.Model.clean

class CommonMeasurement(models.Model):     timestamp = models.DateTimeField()     value = models.FloatField()     run = models.ForeignKey(Run)      def clean(self):         if self.timestamp < self.run.timestamp_start or self.timestamp > self.run.timestamp_end:             raise django_excetions.ValidationError('Measurement is outside the run')      def save(self, *args, **kwargs):         self.full_clean()         return super(CommonMeasurement, self).save(*args, **kwargs) 
like image 107
Seenu S Avatar answered Oct 03 '22 21:10

Seenu S


I've found a solution to override method:

class CommonMeasurement(models.Model):     timestamp = models.DateTimeField()     value = models.FloatField()     run = models.ForeignKey(Run)      objects = models.Manager()     analyzes = managers.MeasureStatManager()      def save(self, **kwargs):         self.clean()         return super(CommonMeasurement, self).save(**kwargs)      def clean(self):         super(CommonMeasurement, self).clean()         print 'here we go'         if self.timestamp < self.run.timestamp_start or self.timestamp > self.run.timestamp_end:             raise django_excetions.ValidationError('Measurement is outside the run') 

But I'm not sure that it can be a good decision.

like image 38
Nikolai Golub Avatar answered Oct 03 '22 21:10

Nikolai Golub