Blank form fields are not accepted - python

Table in PostgreSQL database:
CREATE TABLE pmss_recordmodel
(
id serial NOT NULL,
"Name" character varying(100),
CONSTRAINT pmss_recordmodel_pkey PRIMARY KEY (id)
)
WITH (OIDS=FALSE);
ALTER TABLE pmss_recordmodel OWNER TO postgres;
Model:
class RecordModel(models.Model):
def __unicode__(self):
return self.Name
Name = models.CharField(max_length = 100, unique = False, null = True, blank = True)
When I POST data with blank Name field, form.is_valid() returns False. Why? Am I missing something?
EDIT:
class RecordForm(forms.ModelForm):
class Meta:
model = RecordModel
Name = forms.CharField(label = "Имя ", widget = forms.TextInput(attrs = {'size': 15}))

Django forms documentation:
By default, each Field class assumes the value is required
Set the "required" argument to False as such:
Name = forms.CharField(required = False, label = "Имя ", widget = forms.TextInput(attrs = {'size': 15}))

You could be having problems with how the field is defined in your database.
This seems like it could be the common situation of doing syncdb with the field initially not having blank=True null=True and then adding those terms later (after initial syncdb) to make the field not required. These settings will not be applied by simply running syncdb again. It requires a database migration or a database flush (will clear existing data, which isn't necessarily bad in development).

Related

Django field not passing through serializer

Using the Django REST Framework 2.2, I have a Person model as follows in models.py::
class Person(models.Model):
id = models.CharField(max_length = 20, primary_key = True, blank = True)
name = Models.CharField(max_length = 1024, blank = True)
values = {}
#staticmethod
def create_person(personData):
person = Person(
name = personData.get("name", "Unknown"),
values = personData.get("values", {}),
)
return person
All data is stored in a Firestore database for saving and retrieving data via the REST API. Before new entries are made into the database, a serializer is used to validate incoming POST data.
The route /person takes POST request data and runs it by the PersonCreateSerializer in
views.py:
def create_person(request):
"""
Route: /person
Method: POST
"""
try:
print(request.data)
# Above print outputs:
# <QueryDict: {'name': ['John Doe'], 'values': ['{ "height": 180 }']}>
serializer = PersonCreateSerializer(data = request.data)
serializer.is_valid(raise_exception = True)
person = Person.create_person(request.data)
...
except APIException as exception:
return JsonResponse(exception.APIError, status = exception.status)
serializers.py:
class PersonCreateSerializer(CreateModelSerializer):
class Meta:
model = Person
fields = "__all__"
def validate(self, data):
print(data)
# Above print outputs:
# OrderedDict([('name', 'John Doe')])
# Notice missing 'values' field.
if not data.get("values"): # Ensure we have a values field within the data.
raise APIException("ERROR_MISSING_FIELD", "Missing required field 'values'.", 400)
return data
The problem is however any value provided for the values dictionary is discarded when the serializer validate() function receives it.
POST Payload:
My question is why is the dictionary received from the POST request not received by the serializer so it can be parsed? What is the correcy way to create dictionary fields in Django?
Sent to Serializer:
<QueryDict: {'name': ['John Doe'], 'values': ['{ "height": 180 }']}>
Received by Serializer:
OrderedDict([('name', 'John Doe')])
The problem with JSONField and HStoreField
I have looked at alternatives mentioned such as HStoreField and JSONField however this data is being stored in a Firestore database and the key-value association needs to be retained rather than it being stored as a plain JSON string.
Because the data is being stored in Firestore, the structure of the dictionary array needs to be retained as a map in the database, this allows it to be indexed and queried with Firestore queries.
If we use JSONField, this simply converts the value to a string and removes this functionality.
I believe it is because values is not a field. It is just a class variable.
Serializer filters the data by fields you have pointed to. And you pointed to __all__ which means all fields in model.
You can try:
fields = ['name', 'values']
And if it didn't work, make a function and pass it "as a field":
# models.py
class Person(models.Model):
id = models.CharField(max_length = 20, primary_key = True, blank = True)
name = Models.CharField(max_length = 1024, blank = True)
values = {}
def get_values(self):
return self.values
# serializers.py
class PersonCreateSerializer(CreateModelSerializer):
class Meta:
model = Person
fields = ['name', 'get_values']
The solution I found was to make use of the django-dictionaryfield module, this provides a Dictionary field type that can be used for converting to and from all array types, such as dictionaries and lists.
Without a field declared in the model.py, the serializer ignores it since it isn't considered part of the model itself, therefore using a custom DictionaryField model allows it to be stored as a Django model field.
Django DictionaryField Setup
Install the module into your project:
$ pip install django-dictionaryfield
Add dictionaryfield into your INSTALLED_APPS in the Django configuration file:
INSTALLED_APPS = (
...
"dictionaryfield",
)
Model Class
Use the DictionaryField for fields that should be arrays.
from django.db import models
from dictionaryfield import DictionaryField
class Person(models.Model):
id = models.CharField(max_length = 20, primary_key = True, blank = True)
name = Models.CharField(max_length = 1024, blank = True)
values = DictionaryField(default = {})
#staticmethod
def create_person(personData):
person = Person(
name = personData.get("name", "Unknown"),
values = personData.get("values", {}),
)
return person

Can unique_together avoid nulls in Django

I am using django and Sql server as a database.
I have a table with a multiple primary key using the unique_together
class Attribute_tmp(models.Model):
useridtmp = models.ForeignKey(User_tmp, on_delete=models.CASCADE, blank =True, null = True)
userid = models.ForeignKey(User, on_delete=models.CASCADE, blank =True, null = True)
fk_str = models.ForeignKey(Stream, on_delete=models.CASCADE)
class Meta:
unique_together = (('userid', 'fk_str'),('useridtmp', 'fk_str'))
So when i add objects of this table when the useridtmp is null, it doesn't work because i will have a duplicated key.
My Question is how can i avoid the null values.
Thank you
Did you tried this?
class Meta:
constraints = [
models.UniqueConstraint(fields=['userid', 'fk_str'], name='name of constraint'),
models.UniqueConstraint(fields=['useridtmp', 'fk_str'], name='another name of constraint')
]
Since you have null=True and blank=True in your ForeignKey field, it is reasonable for db to store null values.
If in any case, the two ForeignKeys shouldn't be null, you can mark null and blank as false. Simply removing them from field settings will do the trick as they are set to false by default. You probably need to recreate the database to make the new settings working.
Then, the unique_together will not have an issue with null values.

What is the default type for a user in Django?

I have a MySQL database object that stores concerts that a User plans to attend on a certain date. Since each concert entry needs to be associated with a User, I added a foreign key field for User as an attribute of the Concert model. Here is the complete model:
class Concert(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE)
concert_name = models.CharField(max_length = 120, blank = True, null = True)
venue = models.CharField(max_length = 120, blank = True, null = True)
city = models.CharField(max_length = 120, blank = True, null = True)
state = models.CharField(max_length = 120, blank = True, null = True)
country = models.CharField(max_length = 120, blank = True, null = True)
timestamp = models.DateTimeField(auto_now_add = True, auto_now = False)
updated = models.DateTimeField(auto_now_add = False, auto_now = True)
When I try to make migrations to the DB, I get a message saying: You are trying to add a non-nullable field 'user' to concert with out a default; s essentially saying that the already populated rows need to have a value. I found this SO post which seemed to be addressing a similar issue, but the default value suggested in the solution is for a charfield and I don't think that would really apply in this situation. How should I go about setting the default value of the User object?
You can use null=True:
user = models.ForeignKey(User, null=True)
Although if you look at your db actual model, you cannot see an actual Foreign Key, when you put models.ForeignKey(User) in your model you can see in your db a user_id with references, but the relation needed exists so you can make it's null=True as a default.

django, table inheritance: insert data

I have these tables:
class OpeDatos(models.Model):
id_dato = models.IntegerField(primary_key=True)
id_usuario = models.ForeignKey(SisUsuarios, db_column='id_usuario')
id_region = models.ForeignKey(SisRegiones, db_column='id_region')
titulo = models.CharField(max_length=70, blank=True)
class Meta:
managed = False
db_table = 'ope_datos'
class OpeProductos(OpeDatos):
id_producto = models.IntegerField(primary_key=True)
iddato = models.OneToOneField(OpeDatos, primary_key=True, db_column="id_dato", parent_link=True)
id_producto_tipo = models.ForeignKey(DefProductosTipos, db_column='id_producto_tipo')
class Meta:
managed = False
db_table = 'ope_productos'
I want to insert data :
from apps.inicio.models import SisUsuarios, SisRegiones, OpeDatos
usuario = SisUsuarios.objects.get(pk=1)
region = SisRegiones.objects.get(pk=1)
datos = OpeDatos()
datos.id_usuario = usuario
datos.id_region = region
datos.save()
producto = OpeProductos()
producto.iddato = datos.id_dato
producto.save()
displays this message:
ValueError at /productos/add/
Cannot assign None: "OpeProductos.iddato" does not allow null values.
can you help me, please.
When creating an id manually you should use AutoField instead of IntegerField
id_dato = models.AutoField(primary_key=True)
https://docs.djangoproject.com/en/1.6/ref/models/fields/#autofield
What is happening is that since you are not explicitly defining the 'datos' object's id it doesnt have one, and then producto complains because the key can't have an empty value.
AutoField should fix this
I am surprised it doesn't fail at the earlier line: datos.save() because you have not supplied a value for the primary key datos.id_dato
Normally in Django you would need to use an AutoField to get an auto-incrementing primary key.
Also you should not be specifying primary_key=True on the OpeProductos.iddato field, you can only have one primary key per model.
Then the error you are seeing is due to the fact that datos.id_dato is None since you did not provide any value for it before saving the datos instance.

Django; requirement dependencies on sets of fields

How could I add rules to a Django Model making certain fields that aren't required by default, required if another field is set. Or even the other way around
Let's say I have this Model:
class Item(models.Model):
name = models.CharField(max_length = 75)
cant_be_sold = models.BooleanField()
flat_price = models.IntegerField(blank = True, null = True, default = None, validators = [MinValueValidator(0)])
defense = models.IntegerField(blank = True, null = True, default = None, validators = [MinValueValidator(0)])
required_classes = models.ManyToManyField('otherappname.Class', related_name = 'Requires_Classes', blank = True, null = True, default = None)
Let's say there can be 2 situations here;
I mark cant_be_sold as True; now flat_price can only be None (NULL)
I fill in defense; now it IS required to select one or more required_classes
I wonder what the nice way to do this in Django is. Would help me a bunch to prevent wrongfully entries, as my Item model has over 70 property fields, due to the great extend of Item Variances in my system.
Write a clean method for your model. In it, you can change field values, and raise validation errors. The following example should get you started.
def clean(self):
if self.cant_be_sold and self.flat_price is not None:
raise ValidationError("flat_price must be None when cant_be_sold is True")

Categories