Django how to use model DecimalField with additional character values? - django

I have an input box that must accept the following parameters:
Empty Value ('')
ZERO (0)
Fail value ('x')
I know that I can create a custom "fail" BooleanField that gets set to True if "x" is typed. However, I would like to know if it is possible add these values inside the DecimalField. Maybe, use CharField with Decimal Validation. However, trying to use it with CharField and Decimal Validation failed. So, I am not sure how else I can achieve this.
Thanks!

Could you do something with validators like:
extended_decimal_field = models.CharField(
max_length=10,
validators=[RegexValidator('^\d{8}[.]{1}\d{2}|['X']{1}$')]
)
I don't think this is exactly right but might be right track?

Related

Checkbox in Django - What is best practice?

I am aware that on djangoproject.com there is a explanation that you should use NullBooleanField for a checkbox in Django, however, I am wondering if it would be better to use something like this?
models.CharField(null=True, choices=(('Y','YES'),))
Then null would just evaluate to not checked and yes would evaluate to checked. This seems to make more sense to me rather than NullBooleanField where you would have essentially
models.CharField(null=True, choices=(('1','UNKNOWN'),('2','YES'),('3','NO'),))
my interpretation of NullBooleanField could be (and probably is) incorrect, but when I render a crispy forms, it gave me a select box, so wouldn't it be represented this way in the db?
If your logic only requires True/False, and not Null, then it would be better to use a BooleanField instead of a NullBooleanField, with default=False.
A NullBooleanField is indeed essentially a field with Yes/No/Unknown choices.
Note that a CharField never saves NULL but always an empty string, so null=True would have no effect on a CharField.

Django check if any field is blank?

I there any way to check if any field Null or Empty without checking each and every field. i have seen this Django check to see if field is blank?. But in this case we have to check each and every field.
if i am wrong please correct me. Thanks for the help!
There's no way around checking all the fields, but you could write some helpers.
any_blank_fields = all((field.blank for field in Model._meta.fields))
Oh, you're talking about Falsy values, not blank=True. In that case, you really have no choice but to do some loops, or a list comprehension.
instance = Model.objects.latest('pk')
all_fields_filled = all((getattr(instance, field.name) for field in
instance._meta.fields))

Django Models - Prepare the data for the database

I have a form that askes for a phone number. I need to make sure that only digits [0-9] get saved in the database.
In the Django documentation it says:
What happens when you save?
3) Prepare the data for the database. Each field is asked to provide its current value in a data type that can be written to the database.
How does this happen? Or more specifically, how can I make sure this is cleaned? I know that I can just override the models save method, but it seems like there is a better way and I'm just not sure how to do it.
I guess I could write a custom field for it, but that seems like overkill here.
Also, I realize that I can put the validation on the form, but it really feels like stripping out the characters belongs on the model.
Your question specifically about point 3 is a little different from "cleaning" in the way django uses the term.
3) Prepare the data for the database. Each field is asked to provide its current value in a data type that can be written to the database.
Point 3 is about converting the python object values to one suitable for a database. Specifically, this is done in Field.get_prep_value and Field.get_db_prep_value
https://docs.djangoproject.com/en/dev/howto/custom-model-fields/#django.db.models.Field.get_prep_value
It's the opposite of to_python which takes a DB value and converts it to a python object.
As for ensuring only digits 0-9 get stored, that would be done in a Fields clean method (subclass IntegerField), form clean method, form clean_FIELDNAME method, or model clean.
You can add a custom Form Cleaning method to your objects model - take a look at this article https://docs.djangoproject.com/en/dev/ref/forms/validation/#form-field-default-cleaning
Look at "Cleaning a specific field attribute"
use django model form + custom form field cleaning
Below is a quick example of what you might be looking for, where MyModel is the model containing the phone number field, which I named it tel here.
import re
class MyForm(ModelForm):
class Meta:
model = MyModel
def clean_tel(self):
tel = self.cleaned_data.get('tel', '') # this is from user input
# use regular expression to check if tel contains only digits; you might wanna enhance the regular expression to restrict the tel number to have certain number of digits.
result = re.match(r'\d+', tel)
if result:
return tel # tel is clean so return it
else:
raise ValidationError("Phone number contains invalid character.")

unixtimestamp input in DataTimeField

Per specification I have date and time input in UnixTimeStamp Also, I need check that I have only digits on input (nor something like this "2011-12-12")
I have forms.DataTimeField and model.DataTimeField now.
I decided to modify this in such way:
Added UnixTimeStampField(forms.RegexField) - here I check with regular expression, that I have only digits.
But I got problem with model, since UnixTimeStampField(forms.RegexField) is based on string and need to be converted to datatime.
I don't like this solution.
How I can create something like UnixTimeStampField(forms.DateTimeField)?
I tried to do this, but then I have "123321" on input I got "Incorrect parameter" from DateTimeField validators.
You don't need a custom model and/or form field for this. Just use the built-in forms.DateTimeField and models.DateTimeField, then add the following settings to your settings.py:
DATETIME_FORMAT = "U"
DATETIME_INPUT_FORMATS = ("%s",)
Read more about this settings here.

django admin saving inline with blank value

I have two models as
class Employer(models.Model):
..
..
class JobTitle(models.Model):
type = models.IntegerField(null=False, choices=JobTitles.CHOICES,blank=True,default=0)
employer = models.OneToOneField(Employer,unique=True,null=False)
I have defined admin for Employer and defined JobTitle as inline class.
However, when I saved an Employer object without selecting JobTitle, it raises the error invalid literal for int() with base 10: '' due to the type field of JobTitle.
I would like to set type to 0, as I defined default=0, if I don't select any jobtitle when employer is saved.
How can I achieve this ?
So, I'm inferring this from the code you posted, but I think that you're mixing strategies here. I assume based on the way you've constructed your question that you want to me able to make a job title with no type. Alternatively, you want one job type to be the default selection. I further infer, although now I'm stretching a bit, that you have a custom "No Type" choice (you didn't show us your JobTitles.CHOICES tuple so I have to guess) that corresponds to the 0 value that you've set as the default.
If you want to have a default job type (even if you're calling it "No Job Type" or something similar), then you should set it using the default keyword argument (as you have done) and you should set null=False and blank=False (alternatively, omit both, as these are the default values).
However, if you want it to be possible that there is a job title with no type, then unless you have some reason in your implementation to do something else, the purest way to represent this in data is to use the null SQL value. If you want to go that route, the correct way to do it is to set blank=True and null=True, and then either set default=None or omit that keyword argument entirely.
That should get you the behavior that you seek.
For Model arguments, default is used when Django save your data to Database...
On the other hand, your error occurs during data parsing. When you submit your form, django parses data to relevant type if needed. When your html form is submitted, django recieves string data like
{'title':'12', 'employer_id':'23'...}
So, django have to parse type into ineger before it save it to the database... Since your forms sends a nullstring '' , int('') simply fails with TypeError.
What you must do is removing blank=True. Or somehow you must override the default behaviour of combobox default value and set it 0 instead of ''.