Tuesday, December 27, 2016

Subclassing Models in non model class

Hi All,

I created a model Address like a normal practice below. Now I need to create a subclass without using models.Model. But its not letting me do because obviously it won't create tables unless I call models.Model in class parameters. 

Idea is to create a model and use that model with non db reference in admin.py. Following is the code:

"class Address(models.Model):
 .......
class ShippingAddress(Address):
    phone_number = PhoneNumberField(
        _("Phone number"), blank=True,
        help_text=_("In case we need to call you about your order"))
    notes = models.TextField(
        blank=True, verbose_name=_('Instructions'),
        help_text=_("Tell us anything we should know when delivering "
                    "your order."))

    class Meta:
        app_label = 'order'
        verbose_name = _("Shipping address")
        verbose_name_plural = _("Shipping addresses")

    @property
    def order(self):
        try:
            return self.order_set.all()[0]
        except IndexError:
            return None


class UserAddress(ShippingAddress):
    user = models.ForeignKey(
        AUTH_USER_MODEL, related_name='addresses', verbose_name=_("User"))
    is_default_for_shipping = models.BooleanField(
        _("Default shipping address?"), default=False)
    is_default_for_billing = models.BooleanField(
        _("Default billing address?"), default=False)
    num_orders = models.PositiveIntegerField(_("Number of Orders"), default=0)
    hash = models.CharField(_("Address Hash"), max_length=255, db_index=True,
                            editable=False)
    date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)

    def save(self, *args, **kwargs):
        self.hash = self.generate_hash()
        self._ensure_defaults_integrity()
        super(UserAddress, self).save(*args, **kwargs)

    def _ensure_defaults_integrity(self):
        if self.is_default_for_shipping:
            self.__class__._default_manager\
                .filter(user=self.user, is_default_for_shipping=True)\
                .update(is_default_for_shipping=False)
        if self.is_default_for_billing:
            self.__class__._default_manager\
                .filter(user=self.user, is_default_for_billing=True)\
                .update(is_default_for_billing=False)

    class Meta:
        app_label = 'address'
        verbose_name = _("User address")
        verbose_name_plural = _("User addresses")
        ordering = ['-num_orders']
        unique_together = ('user', 'hash')

    def validate_unique(self, exclude=None):
        super(Address, self).validate_unique(exclude)
        qs = self.__class__.objects.filter(
            user=self.user,
            hash=self.generate_hash())
        if self.id:
            qs = qs.exclude(id=self.id)
        if qs.exists():
            raise exceptions.ValidationError({
                '__all__': [_("This address is already in your address"
                              " book")]})

......"

I know that I needed to create a parent class without calling models and then I can inherit that class in models.Model.

But is there a way around it or do I need to create abstract models?

Regards,
Mudassar

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CANoUts4wcHLvqF3Q_7cJ%3D3LxTAFM5m-2J7UO%3Dueit1DN4XpF5g%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment