Best place for additional model constraints
I am playing with a Django project which will deal with networking information. I would like to enforce some additional constraints above and beyond what the default Form fields provides. For example, if I have a model to represent a 'subnet' it would have both a network address (which I can save as an IPAddressField) and a netmask which can be an IntegerField. I want to enforce that the host portion of the address field is all zeros. This is pretty easy to calculate given the address and netmask. But where should I put such calcuations? Class Subnet(models.Model): address = models.IPAddressField() netmask = models.IntegerField() In reading the documentation I can find several places where it might fit: 1) define a new custom Field subclass which incorporates both the address and netmask as a single value. This would work, but I think I might end up with a lot of extra new Field types and doesn't really seem to be the right place. 2) override the 'save()' method on my Model subclass, and do the check there. This seems pretty easy, but I'm not sure what to do if I fail the validation. Raise ValidationError? Either way, this is the option I'm leaning towards now. 3) catch the django.db.models.signals.pre_save signal. I haven't played with signals though so I don't know how to set it up. I would still have the question of what to do if I fail the validation. 4) Use the clean_address() method of a custom ModelForm. This is pretty easy, and feels like it's sort of the right place because then I can easily give the user a nice error message. On the other hand, it's not really preventing the creation of invalid Subnet instances via other methods (say via the Admin interface). I'm sure other folks are dealing with the same issue. Where are you doing this type of check? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Re: Best place for additional model constraints
bruno desthuilliers wrote: > I'm afraid that if you want to use the admin app and still have a > robust (and correct) model, you'll have to apply solutions #2 *and* > #4. In order to restrict repetition to a minimum, you should factor > this validation rule in a function (possibly defined in the your > model's module) and call it from both the model's class save method > and the custom form. That's kind of what I was leaning towards, defining it in both places. Putting something in the save() method of the model is what really enforces the particular rule. Having a clean_address() method in a custom form is really just providing a nicer user interface. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---
Possible OneToOneField delete bug?
I'm pretty new to Django, but I found some odd behavior in OneToOneField which I think is a bug. Take the following Models: class Widget(models.Model): name = models.CharField(max_length=10) def __unicode__(self): return u'%s(%s)'%(self.name,self.pk) class Sprocket(models.Model): name = models.CharField(max_length=10) w = models.OneToOneField(Widget, null=True, blank=True) def __unicode__(self): return u'%s(%s)'%(self.name,self.pk) And the following sequence of operations: w=Widget(name="Some Widget") w.save() s=Sprocket(name="Some Sprocket") s.w=w s.save() assert Widget.objects.all().count()==1 assert Sprocket.objects.all().count()==1 #print w.sprocket s.w=None s.save() w.delete() assert Widget.objects.all().count()==0 assert Sprocket.objects.all().count()==1 The assert's pass as long as the print statement is commented out. If I include the print, then my Sprocket s gets deleted along with w despite the fact that I removed the reference between the two. This is problematic because it makes it really hard to override the cascading delete() feature. I tried having a pre_delete() method on my Model which would reset the references, but the mere act of accessing the reverse reference (w.sprocket in the example above) seems to cause the reference to get cached somehow. There are other ways to view similar behavior, but the test case above is about the most succinct. Is there any reason to think this is the correct behavior, or should I open a bug? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~--~~~~--~~--~--~---