Does 'default=...' in Django model fields set 'blank=True' by default? - python

I have a question for the Django model field when applying the default setting. My problem is as follows:
# Model description
class aa(models.Model):
a = models.FloatField(default=1)
b = models.FloatField()
When inserting an entry into the database, I apply the following functions to do the validation without any error:
data = {'b': 1.1} # Just for demo...
p = aa(**data)
p.full_clean()
p.save()
Here is the problem, is the case that when I set the default value for a field, the blank is automatically set to True?
P.S. I know what are the differences between null and blank, I just want to figure out the issues related to the default.

If you put default on a model field, actually it is not setting blank = True . When you initialize a Model like
instance = ModelClass(**field_data)
django will check for all fields and if the field value is not there, then it will try checkin default value by calling get_default() method (look for default value) on Field class.

Django model fields default to required unless you specify blank=True and/or null=True. In your example, the model validates because you have defaulted a to 1 and set b to 1.1. Neither field is blank, so you're not encountering a situation that hits the question you're asking.
Try changing data = {'b': 1.1} to data = {'a': 1.1} and see what happens - you should get a field validation error.

Yes. Django always do that. If you don't need that feature simple make it set blank = False

Related

How to set default values into an Array Field Django?

I would like to know how to set default values into a Django Array Field Model.
I have a TextChoices model named "GameType" :
class GameType(models.TextChoices):
'''
Enumeration of all different game types
'''
EVIL = 'evil', 'evil'
SOLOCOOP = 'solo', 'solo'
MULTI = 'multi', 'multi'
And in my Item model, I can choose in each mode my item is available. Then I have these lines :
game_types = ArrayField(
models.CharField(
default=GameType.SOLOCOOP,
max_length=40,
choices=GameType.choices
), default=default_item_game_types, null=False, blank=False)
Two things :
The first default key "GameType.SOLOCOOP" doesn't work
The default list doesn't work too
Here is my "default_item_game_types" function :
def default_item_game_types():
'''Default callable to avoid errors
'''
return list(GameType)
And in my CMS, I don't have my default values :
Screenshot of my Game types field
I tried many things and searched many solutions but nothing matched in my case.
Is there any response to fix my issues ?
Thanks for your time
Regards,
Steven
1: You need to set it like
self.SOLOCOOP = 'solo'
Can do this in a custom method or init if you know the defaults for it, that would be much easier than calling the custom method.
2:The default values are based on the Charfield as it is an Array of fields in some sense.
EDITED:
Just do the str_value then or better just do the key value for solar as you're already using it as choices in the parameter below.

Update a field of a Django Object

I'm trying to update an object field in django. Usually I would do something like this:
# MODEL ---
class MyObj(models.model):
name: models.CharField(max_length=10)
surname: models.CharField(max_length=10)
# VIEW ---
# [...]
myObj = MyObj.objects.get(pk=1)
myObj.name = 'John'
myObj.save()
The problem is that the field to modify (in the example above: "name") is not known and passed as an argument to the post request. So I would have something like this:
# VIEW ---
# [...]
field = self.request.query_params['field_to_modify']
myObj = MyObj.objects.get(pk=1)
myObj[field] = 'John'
myObj.save()
now this triggers the error:
myObj[field] = 'John'
TypeError: 'MyObj' object does not support item assignment
What is the correct way to update an "unknown" field of a django object?
UPDATE
Thank you for your answers so far! OK so the way to go is apparently using setattr (as per the answers). Now the problem is that it does not allow me to save the modified object without checking if it is valid.
So I tried using the Serializer to check the object validity but is not working:
field = self.request.query_params['field_to_modify']
myObj = MyObj.objects.get(pk=1)
setattr(myObj, field, 'John')
serial = MyObjSerializer(myObj)
serial.is_valid(raise_exception=True)
serial.save()
error:
AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance.
You're looking for setattr to set an attribute by name.
field = self.request.query_params['field_to_modify']
# TODO: add validation for `field`
myObj = MyObj.objects.get(pk=1)
setattr(myObj, field, 'John')
myObj.save(update_fields=[field]) # no need to update anything but the single field
Of course, this won't let you automatically attach any arbitrary data to models and expect it to be saved; if you need something like that, maybe use a JSON field.
EDIT:
For using a Django REST Framework serializer (which, cough, wasn't part of the original question or tags, but could be inferred from query_params), one could do
field = self.request.query_params['field_to_modify']
myObj = MyObj.objects.get(pk=1)
serial = MyObjSerializer(instance=myObj, data={field: 'John'})
serial.is_valid(raise_exception=True)
serial.save()
Yeah it looks like Django model instances do not support that operation. It looks like you can use setattr though from looking at this previous question / answer. Update model instance with dynamic field names

Django Forms self.fields for Foreign Keys and Session Values?

I have a form where I'm trying to add initial value to hidden filed from a session.
When I use
self.fields['myfield'] = forms.CharField(initial=request.session['value'])
the session value is correctly rendered but I do get error:
Cannot assign "u'123'": "Model.filed" must be a "Model" instance.
I know the error is because it is a foreign key field.
When I do
myfield = forms.CharField(initial=request.session['value'])
the form is working without errors but the request.session['value'] is not rendered and the initial value is empty.
Suggestions?
First make sure the 123 (or whatever) is a valid primary key for your model referenced in the ForeignKey field.
You could prevent that in the place where you're adding the value item to the session dict.
Now, the initial argument is looking for a valid object, so just give it that.
self.fields['myfield'] = forms.CharField(
initial=MyOtherModel.objects.get(pk=request.session['value'])
)
Note: I'm supposing MyOtherModel is the ForeignKey.

django make ModelChoiceField non-editable

I have a ModelForm with ModelChoiceField on it, and I need to make sure, that the initial value should stay fixed and we can't select any other one. It means, make this field non-editable, preserved, or smth like that. Making it CharField or just Field will not help here, I think, because I need an object from this field later for validation and processing.
Can someone, please, help?
self.fields['field_name'].widget.attrs['readonly'] = True
Turned out, I needed here the following code:
self.fields['field_name'].widget.attrs['disabled'] = 'disabled'
This option will remove the instance from the form fields when you submit the form.
self.fields['field_name'].widget.attrs['disabled'] = 'disabled'
Using this option you will disable de field to be edited and you can converse the init instance to be saved into the database.
algorithm = forms.ModelChoiceField(label='Algoritmo',queryset=Algorithm.objects.all(),to_field_name="name",widget=forms.TextInput(attrs={'readonly':'readonly'}))

Help with validation in Models and Forms

I have a few questions about validation in Models and Forms. Could you help me out with these:
Where should validation be done? Should it be in the Model or the Form? Is the right way to go about this is to have validators in the form and constraints in the mode?
What is the difference between writing a 'clean_' method in the form and writing a validator? I've seen that people often put validation checks in the 'clean_' method.
In the request that I'm handling, I have a param in the URL string called 'alive'. This is generally 1 or 0. What would be the correct way of defining this in my form? I need to validate it is a number and can only be 1 or 0. Is this the right way?
alive = models.IntegerField(null=False, max_value=1, min_value=0)
How do I define a default value for this field i.e. if this parameter isn't passed, I default to 0 (False).
I don't have a form on the client side. I'm using the Django form the validate my JS POST request.
In one of model fields I need to store screen resolution in the format 1234x4321. Should I declare this as a CharField add some regular expression validation in both the Model and the Form? Any examples of regular expression validations would be helpful.
Thanks.
The validation should be done on the form, not the model. However, if you are using ModelForms, which is usually makes a lot of sense, it will inherit some of the validation rules from the models themselves (those specific to the database, like maximum_field length, database field type, but also if they can be left blank).
The default value of a field should be passed with its constructor:
form = SomeForm(initial={'alive' : 0})
Although in your case, it appears that if the values that can be obtained are only zero and one, it would be make sense to use a BooleanField instead(tand in that case it would default to false).
In the case of resolutions I would create a mapping between the possible resolution and some arbitrary value.
RESOLUTIONS = (
("1","800x600"),
("2","1024x768"),
.....
)
and then pass it to the model:
resolutions = models.CharField(RESOLUTIONS, max_length=1)
So that the user gets a select field with the corresponding options and values.
On the other hand, if you need the user to insert it him/herself, using two fields (one for width, another for height) would be much easier than validating the user input.
So you can define a method for the model:
def get_resolution(self):
return "%sx%s" % (self.width, self.height)

Categories