Reputation:
I have defined a simple model in Django:
class Student(models.Model):
s_name = models.CharField(max_length=32)
s_gpa = models.FloatField(min=0.0, max=5.0, default=5.0)
s_year = models.IntegerField(min=1, max=10, default=1)
s_registered = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.username
def modify(self, **kwargs):
if valid(self, kwargs):
for k,v in kwargs.iteritems():
setattr(self, k, v)
self.save()
def valid(s, kwargs):
# For all k,v pairs in kwargs
# (1) Checks if k is one of the attributes of s. Returns False if fails.
# (2) Checks if v fits the format defined for attribute k of s.
# Returns False if fails.
# Returns True if reaches this point.
I'm writing the function valid, which I'd like to execute the commands detailed in the comments.
For (1), I use
if k not in s.__dict__: return False
I would need some help with (2).
That is, how can I check if a value fits the format defined for an attribute (Django model field)?
For instance: valid(s_name=True) and valid(s_name=33*'a') should both return False.
Note: I'm trying to solve this validation without using Forms.
Upvotes: 0
Views: 788
Reputation: 13328
Both your valid
and modify
functions should probably be replaced with a clean
method.
Have a look at the docs on model validation
UPDATE 1
You could probably drop the valid method altogether and simply call self.clean_feilds()
instead. That will validate the fields -
def modify(self, **kwargs):
try:
self.clean_fields()
for k,v in kwargs.iteritems():
setattr(self, k, v)
self.save()
except:
pass
UPDATE 2
It sounds from your comments that you don't need to call any validation yourself at all. Just call save
and then catch the ValidationError
thrown if your changes are invalid.
def modify(self, **kwargs):
try:
for k,v in kwargs.iteritems():
setattr(self, k, v)
self.save()
except ValidationError:
#... do something?
It's worth noting that many python programmers prefer the try / except pattern to if valid / then. It's known as the 'better to ask forgiveness than permission' principle (amongst other things it provides protection against race conditions - probably not relevant in this case)
Upvotes: 1
Reputation: 2509
Use s
or self
as needed.
def valid(self, kwargs):
for k, v in kwargs:
old_v = self.__dict__[k]
self.__dict__[k] = v
try:
self.save()
self.__dict__[k] = old_v
self.save()
except:
return False
return True
There is likely a more direct way to perform your test than an actual 'self.save()' failure, but its a good place to begin.
Alternatively:
field_list = ['s_name', 's_gpa', 's_year', 's_registered']
def valid(self, kwargs):
for k, v in kwargs:
exclude_list = [f for f in field_list if f != k]
try:
self.clean_fields(exclude=exclude_list)
except ValidationError:
return False
return True
With list comprehension, eliminate the exclude_list
line and change the self.clean_fields
line to:
self.clean_fields(exclude=[f for f in field_list if f != k])
Upvotes: 0