I'm using Django 1.8.
The documentation on writing validators has an example of a function-based validator. It also says the following on using a class:
You can also use a class with a
__call__()
method for more complex or configurable validators. RegexValidator, for example, uses this technique. If a class-based validator is used in the validators model field option, you should make sure it is serializable by the migration framework by addingdeconstruct()
and__eq__()
methods.
__call__()
used for, and how is it used?deconstruct()
used for, and how is it used?__eq__()
used for, and how is it used?An example would be helpful. A full answer may also be worth submitting to be in the official documentation.
Thanks!
Asynchronous class-based viewsimport asyncio from django. http import HttpResponse from django. views import View class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform io-blocking view logic using await, sleep for example. await asyncio.
Validator class is a processor that checks an XML document against Schema. A validator object is not thread-safe and not reentrant.
Django provides built-in methods to validate form data automatically. Django forms submit only if it contains CSRF tokens. It uses uses a clean and easy approach to validate data. The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class.
A validator is a callable that takes a value and raises a ValidationError if it doesn't meet some criteria. Validators can be useful for reusing validation logic between different types of fields.
A big advantage of validator functions is that they are really simple. They simply take one value as an argument, check that it's valid, and and raise ValidationError
if it's not. You don't need to worry about deconstruct
and __eq__
methods to make migrations work.
The validate_even
example in the docs is much simpler than a validator class would be.
def validate_even(value):
if value % 2 != 0:
raise ValidationError('%s is not an even number' % value)
If you need to check divisibility by other numbers as well, then it would be worth creating a validator class ValidateDivisibleBy
. Then you could use ValidateDivisibleBy(2)
, ValidateDivisibleBy(3)
and so on. But a lot of the time, a validator function is good enough.
Other than being able to inherit from BaseValidator
, there might not necessarily be a significant pro/con to choosing function vs class-based validators. I prefer class-based because you can keep internal state if necessary without making it visible to the clients (e.g. compiled regexes, pre-computed values in a table, history, etc.)
The __call__
method makes an object callable and allows it to sort of emulate function-like behavior (i.e. the object can be called like a function would), and the object's __call__
override will be invoked. It requires you to implement the special __call__(self, ...)
method in the validator.
class Callable(object):
def __call__(self,*args,**kwargs):
print('Calling', args, kwargs)
>>> c = Callable()
>>> c(2, 3, color='red')
Calling (2, 3) {'color': 'red'}
>>>
The deconstruct
method seems to provide a point where the client (i.e. you) can override serializing behavior by writing custom implementations. For example, see here. This seems similar to the clean
method, where you can implement custom input sanitation for your models and gets called automatically when full_clean
is invoked (e.g. when a form uses is_valid
).
The __eq__
allows you to implement a comparison between 2 objects that are themselves not comparable. For example, if you have a
class Vector2:
def __init__(self, x, y):
self.x = x
self.y = y
your __eq__
implementation could look like this to check for equality between two vector objects:
# ...
def __eq__(self, other):
return self.x == other.x and self.y == other.y
This way, you avoid a shallow comparison of the underlying references.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With