How to remove validator on id field in wtforms - validation

I have created sqlalchemy class and wtform Form from class.
from wtforms.ext.sqlalchemy.orm import model_form
class ClientGroup(Base, BaseModel):
__tablename__ = 'client_groups'
id = Column(Integer, primary_key=True)
name = Column(String(255))
sale = Column(Integer)
def __unicode__(self):
return self.name
ClientGroupForm = model_form(ClientGroup, Form, field_args={
'name': {'validators' : [validators.Required(), validators.Length(min=5)]},
})
in app I have following code:
form = ClientGroupForm(request.form)
if form.validate():
.. save data
When i send a new data to app its returns me validation error. ID must be an integer field.
But a new data hasn't any id.
Please, give me advice How can I use wtforms with sqlalchemy?

Make it optional explicitly, by adding the following to the field_args:
'id': {'validators' : [validators.Optional()],
However, I think you should exclude the id field from the form completely:
ClientGroupForm = model_form(ClientGroup, Form, field_args={
'name': {'validators' : [validators.Required(), validators.Length(min=5)]},
exclude=['id'],
})

Related

How to order the id in serializers in Django Rest Framework?

when I try to sort my id in my serializers it gives me an error : AttributeError: 'int' object has no attribute 'all'.
Here is the code of my serializers :
class DatasetPidTrierSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.SerializerMethodField()
class Meta:
model = Dataset
fields = ['id']
def get_id(self, instance):
songs = instance.id.all().order_by('id')
return DatasetPidSerializer(songs, many=True).data
Here is the beginning of it : model Dataset
thank you for your help
First, you don't need to set id field in Dataset model. Django will do that automatically for you. You can define just two fields pid and iddatta_resolution.
class Dataset(models.Model):
pid = models.ManyToManyField(
...
)
iddata_resolution = models.ForeignKey(
...
)
And then in the serializer, you don't need to define id field. Because the default order will be id field automatically by Django.
class DatasetPidTrierSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Dataset
fields = ['id']

drf-spectacular: how to show the primary key in examples section of Swagger

I'm trying to show the primary key in the examples section of Swagger, I'm using drf-spectacular and my code looks like:
Serializers.py
class SerializerExample(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('id','name')
Views.py
class BooksBulkUpdate(APIView):
#extend_schema(
request=SerializerExample(many=True),
responses={200:''},
)
def put(self, request, format=None):
with transaction.atomic():
for data in request.data:
book = Book.objects.get(pk=data['id'])
serializer = SerializerExample(book, data=data, partial=True)
if serializer.is_valid():
serializer.save()
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
return Response()
Only the name field is showing:
The only solution that I found was using an inline serializer which is not the ideal solution because if I update my book serializer I'd have to remember to update also this inline serializer. I wonder if there is a better way of doing this.
AFAIK swagger shows input request schema.
For example, you want to add new person and your model is
class Person(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=30)
So you allowed to set only name parameter
Even if you post
{
"id": "someUUID",
"name": "NAME",
}
id will be ignored and Django create it automatically by own logic (because it is read only)
But you can set id field writeable:
class SerializerExample(serializers.ModelSerializer):
id = serializers.UUIDField(write_only=True)
name = serializers.CharField(write_only=True)
class Meta:
model = Person
fields = ('id','name')
write_only=True means that field will be active when you saving new data and receiving id from request json.
In opposite read_only=True will print id field at response (if you trying get data) but ignore it when you saving new data.
So you try to describe API for data adding, and of course that is not allow to set id field in request json.
Not sure if this theory applicable to your case, but hope that will be helpful.

DRF error messages combine model and custom field error messages in response

I have this model in django:
product_name = models.CharField(max_length=20, blank=False, required = True)
code = models.CharField(max_length = 13, blank = False, required= True)
product_note = models.CharField(max_length = 2000, blank = True, required=False)
There is a custom validator and sanitizor for code which is applied in serializer. Now my issue is if both fields are incorrect (missing product_name and incorrect code), I get reply :"this field is required" for the product name and the code error message is never shown. If product_name is passed according to its model definitions though, the code error message is shown.
Is there a way both the model definition (i.e. required) and custom validation can be processed and returned at once?
from products.models import Product
from rest_framework import serializers
from validations.product_validators import valid_product_code
class NewProductSerializer(serializers.ModelSerializer):
def validate(self, data):
# validate data here
err_msg = {}
code = valid_product_code(data['code'])
if code == '':
err_msg['code']=['The entered product do not follow product code rules and could not be sanitized']
if err_msg:
raise serializers.ValidationError(err_msg)
data['code'] = code
return data
class Meta:
model = Product
fields = ('product_name', 'code','product_note')
if code fields is not empty serializer call validate_code() method.
class NewProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('product_name', 'code','product_note')
def validate_code(self, value):
# validate data here
err_msg = {}
code = valid_product_code(value)
if code == '':
err_msg['code']=['The entered product do not follow product code rules and could not be sanitized']
if err_msg:
raise serializers.ValidationError(err_msg)
return value

Django DRF serializer - inserting data containing foreign key relationships

I have the following models:
class Contact(models.Model):
class Meta:
managed = False
db_table = 'contact'
class ContactPhone(models.Model):
contact = models.ForeignKey(Contact, on_delete = models.CASCADE)
number = models.CharField(max_length = 45)
class Meta:
managed = False
db_table = 'contact_phone'
Also, I have the following serializers:
class ContactSerializer(serializers.ModelSerializer):
server_id = serializers.IntegerField(source='id', read_only=True)
class Meta:
model = Contact
fields = '__all__'
class ContactPhoneSerializer(serializers.ModelSerializer):
class Meta:
model = ContactPhone
fields = '__all__'
Now, I have a view that insert phone numbers for an existing contact.
The input is a json that looks like this:
data = {'contact_id': 12322,
'phones':[{'number': '89120000001'}]}
The view:
def insert_contact_phone(request):
for record in request.data['phones']:
data['contact_id'] = request.data['contact_id']
serializer = ContactPhoneSerializer(data = data)
if serializer.is_valid():
serializer.save()
I end up with the following error:
RelatedObjectDoesNotExist at /contacts/edit ContactPhone has no
contact.
What am I doing wrong?
If you specify __all__ for the fields in your ContactPhoneSerializer, it does not include contact_id.
So the contact_id taken from the json input is not serialized. It is basically ignored and when you try to save and create new ContactPhone - it fails, because it does not have contact's foreign key correctly set.
But simply adding contact_id to the serializer's fields won't solve your problem.
In your view, i recommend you to set the contact instead:
data['contact'] = request.data['contact_id']
and pass this to the ContactPhoneSerializer.

Django Ajax field help

I have a Django application where I'm trying to have a form that populates a drop down dynamically based on a previous dropdown.
simplified Models:
class VehicleMake(models.Model):
make = models.CharField(max_length = 30)
class VehicleModel(models.Model):
model = models.CharField(max_length = 80)
make = models.ForeignKey(VehicleMake)
class Listing(models.Model):
make = models.ForeignKey(VehicleMake)
model = models.ForeignKey(VehicleModel)
Form:
class DynamicChoiceField(ModelChoiceField):
def clean(self, value):
return value
class MyForm(ModelForm):
category = ModelChoiceField(VehicleCategory.objects, widget=forms.Select(attrs={'onchange':'FilterMakes();'}))
make = DynamicChoiceField(VehicleMake.objects,widget=forms.Select(attrs={'disabled':'true','onchange':'FilterModels();'}), empty_label="Select Model")
model = DynamicChoiceField(VehicleModel.objects,widget=forms.Select(attrs={'disabled':'true'}), empty_label="Select Make")
class Meta:
model = Listing
View:
def new_listing(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
form.save()
else:
form = MyForm()
return render_to_response("newlisting.html", {
"form": form,'model_id':model_id,'make_id':make_id
})
I also have some ajax defined for the auto-populate but this is not the problem
When I submit the form I get the following:
Cannot assign "u'2'": "Listing.make" must be a "VehicleMake" instance.
if I try
make=VehicleMake.objects.get(pk=request.POST['make'])
form.fields['make'] = make
then I get
'VehicleMake' object has no attribute 'widget'
After the suggestion of one of the commenter's that the DynamicChoiceField class was the culprit I removed it and set the form objects for ModelChoiceFields with the exact same other parameters. The object appears to pass and validate correctly as well. The extra class existed based on an old tutorial I found. it appears that what the author did there works with the forms.ChoiceField but is not required for using a ModelChoiceField
thanks everyone for the help

Resources