I am trying to create an update Serializer and return a message for Exception IntegrityError.
snippet of the particular lines of codes is below-
instance.username = validated_data.get('username', instance.username)
if User.objects.filter(username__iexact=instance.username).exists():
raise BaseException
How can i return a message which says username already exists without using Try and Except
update-
This is how i fixed this problem-
if User.objects.filter(username__iexact=instance.username).exists():
raise serializers.ValidationError("username already exists")
User.objects.filter(username__iexact=instance.username).exists()
This won't work because the instance is also User object so it will always return True, you need to exclude the current instance first.
Fixed query:
User.objects.exclude(pk=instance.pk).filter(username__iexact=instance.username).exists()
I don't know why you don't want to use try/catch but anyway, here's what you could do while following good patterns:
Django's User model already has the unique=True constraint.
Model instances that violate the UNIQUE constraint already throw an IntegrityError on call to save().
So, in your view you just need to catch for the IntegrityError and then raise serializers.ValidationError.
from rest_framework imports serializers, viewsets
from rest_framework.exceptions ValidationError
class UserProfileUpdateViewSet(viewsets.ModelViewSet):
def perform_update(self, serializer):
"""
Overwriting the method
"""
try:
serializer.save()
except IntegrityError:
raise ValidationError(
f"Username already taken. Please choose another one.",
)
Related
when I try to delete Django model object that is ForeignKey in another model with option on_delete=models.PROTECT, the error returned is the normal Django 500 Exception HTML web page, how to make Django rest frame work return json response with the error, is there a way for DRF to do that by default or it should be customized?
Raising 500 Exception is the expected behavior. You have to customize to have a custom error. You can refer to this similar question
You can catch the error by using ProtectedError expceptions.
Like this-
from django.db.models import ProtectedError
try:
# Write here your code
except ProtectedError:
# Return your customer validation error
To complete MSI Shafik answer, specifically for django-rest-framework, you can override the destroy method to catch the exception and return protected objects in a response to handle an error message in your application.
For example:
from django.db.models.deletion import ProtectedError
def destroy(self, request, *args, **kwargs):
try:
return super().destroy(request, *args, **kwargs)
except ProtectedError as protected_error:
protected_elements = [
{"id": protected_object.pk, "label": str(protected_object)}
for protected_object in protected_error.protected_objects
]
response_data = {"protected_elements": protected_elements}
return Response(data=response_data, status=status.HTTP_400_BAD_REQUEST)
In Django Rest Framework (and Django), traditionally we check fields in validate_<field> method, and make more global checks in validate method.
However, look at this code snippet:
def validate(self, data):
# ....
try:
customer.activate(data['signup_code'], data['raw_password'])
except BadCodeProvided:
raise ValidationError(MSG_WRONG_ACTIVATION_CODE)
except SomeOtherException:
raise ValidationError(SOME_OTHER_MESSAGE)
Here, I'm forced to use validatemethod because I'm using 2 fields for my validation (signup_code and raw_password).
However, if an error occurs in a BadCodeProvided Exception, I know it's related to the signup_code field (and not the raw_password one) because of the exception raised here.
In the snippet code above, thiw will create a "non_field_error".
Question: is there a way in DRF to raise the same error but related to the "signup_code" field? (like it would be done in a validate_signup_code method).
Thanks
you can use serializers.ValidationError in serializer :
raise serializers.ValidationError({"myField": "custom message error 1",
"myField2": "custom message error 1"})
doc here Validator DRF
I have created a custom form and need to override both of the clean_field() method and clean() method. Here is my code:
class MyForm(forms.Form):
username=forms.RegexField(regex=r'^1[34578]\d{9}$')
code = forms.RegexField(regex=r'^\d{4}$')
def clean_username(self):
u = User.objects.filter(username=username)
if u:
raise forms.ValidationError('username already exist')
return username
def clean(self):
cleaned_data = super(MyForm, self).clean()
# How can I raise the field error here?
If I save this form twice, and the username will be already exist in the second time, the clean_username method will raise an error, however, the clean() method still run without interruption.
So my question is, how can I stop calling clean() when error already raise by cleaned_xxx, if that is not possible, then how can I raised the error again which raised by clean_xxxx() in clean() method?
In your clean method, you can check whether username is in the cleaned_data dictionary.
def clean(self):
cleaned_data = super(MyForm, self).clean()
if 'username' in cleaned_data:
# username was valid, safe to continue
...
else:
# raise an exception if you really want to
You probably don't need the else statement. The user will see the error from the clean_username method so you don't need to create another one.
I have a special UpdateView and ModelForm (to front my Stripe integration), and I'm wondering if there's a way to both return the object and show an error on the page in a simple way. My gut tells me no (since exceptions raise exceptions...), but any insight / input would be great.
Here's my custom modelForm's clean method, which is what's tied to the UpdateView.
def clean(self):
if not self.user:
raise forms.ValidationError("User needs to not be null.")
try:
cream = CREAM.create_or_update(self.user, self.stripeToken)
for field in self.Meta.fields:
self.cleaned_data[field] = getattr(cream, field)
return self.cleaned_data
except Exception as e:
raise forms.ValidationError(e.message)
And here's the get_object from our old friend the UpdateView
def get_object(self):
cream = CREAM.objects.filter(client=self.request.user)
if cream.exists():
return cream.get()
else:
return CREAM()
Thanks much!
I have a django charField that is checked via the is_valid() method. The user is supposed to enter a valid logical expression in this field, so I wrote a parsing method that raises an exception if the expression is not correct.
How can I enhance the is_valid() method to cover this exception and display an error message to the user that his query was wrong?
I read this article (https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-a-specific-field-attribute) but still have no idea how to do that.
try:
job = Job(user=request.user) # set the current user
form = JobForm(request.POST, instance=job)
if form.is_valid():
form.save()
job.execute()
messages.success(request, u'A new job with the query "{query}" was created.'.format(query=job.query))
return HttpResponseRedirect(reverse('job-index'))
return self.render_to_response({'job_form': form, 'is_new': True})
except ParseError:
return self.render_to_response({'job_form': form, 'is_new': True})
The try...except-Block should be done within the is_valid() method, that is my intention. Someone got any hints?
You've provided an answer to the question yourself - you create your own form (or model form) and perform custom validation on that form's field using its clean_'fieldname'() method. So for example, say your model is:
class Job(models.Model):
expression_field = models.CharField(...)
...
you create a forms.py:
class JobForm(forms.ModelForm):
pass
class Meta:
model = Job
def clean_expression_field(self):
# You perform your custom validation on this field in here,
# raising any problems
value = self.cleaned_data['expression_field']
if value is 'really_bad':
raise forms.ValidationError("bad bad bad")
return value
then make use of it in your views.py as you already are in your example. Now if the value the user enters doesn't meet your criteria, an exception will be automatically raised