Best place for additional model constraints

2008-09-05 Thread TheShark

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

2008-09-08 Thread TheShark



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?

2008-09-10 Thread TheShark

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
-~--~~~~--~~--~--~---