On Sat, 2009-02-28 at 15:38 -0500, Vitaly Babiy wrote: > I have a model that I have created a custom consturctor now when I use > it in a test or in loaddata, I get this error:
Your model constructor must still allow the normal way of calling model constructors. That is, you can only extend the allowed parameters, not replace them. Django calls Model.__init__ in two different ways. One is by passing in field values as a list of positional parameters. This is generally only used internally, because it's *very* hard to get things in the right order (you have to allow for hidden fields and related fields, etc), but it's also fast to do, so serializers and the ORM layer use it. Thus, you have to allow *args in your constructor. The other way __init__ is called is with a bunch of key=value pairs, corresponding to initialising the model fields by name. So you also have to allow for **kwargs. Thus, there are two practical ways to create a new constructor in your subclasses. The first approach is to keep the same signature for __init__ and pop any of your extra keyword arguments from the list before calling super().__init__. Thus, if you were wanting to pass in a "foo" parameter, you would do something like this: class MyModel(models.Model): def __init__(self, *args, **kwargs): if "foo" in kwargs: self.foo = kwargs.pop("foo") super(MyModel, self).__init__(*args, **kwargs) It's not really practical to add extra positional arguments, since there's no way to tell if there arguments intended for the Model's __init__ method or your own. The second approach is to call your particular constructor by an entirely different name. Constructors are (more or less) just class methods that return an instance of the class. So you could write: class MyModel(models.Model): @classmethod def my_constructor(cls, foo): obj = cls(....) obj.foo = foo return foo The general rule here, which is always applicable when subclassing anything in Python, is that you should try to obey what's called The Liskov Substitution Principle: the subclass should be able to be used wherever the base class is used. Which means the __init__ method in the subclass has to be able to be called using exactly the same (and only the) parameters used to construct the base class, otherwise it's not substitutable. Regards, Malcolm --~--~---------~--~----~------------~-------~--~----~ 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 django-users+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---