am not entirely sure if what am about to do is programmically possible. Although if this works, It will help me a lot organize my code.
class AuditColumns(models.Model):
created_at=models.DateField("Created at")
created_by=models.ForeignKey(User, db_column="created_by", related_name="%(app_label)s_%(class)s_y+")
updated_at=models.DateTimeField("Updated at")
updated_by=models.ForeignKey(User, db_column="updated_by", null=True, blank=True, related_name="%(app_label)s_%(class)s_y+")
class Meta:
abstract = True
def return_audit_columns(self):
return self.created_at, self.created_by, self.updated_at, self.updated_by
class Choice(models.Model):
choice=models.CharField(max_length=200)
def __init__(self):
self.created_at, self.created_by, self.updated_at, self.updated_by=AuditColumns.return_audit_columns(self)
the code above does not work, it was my attempt or what I wish to do. Basically, I have the class AuditColumns which contain this set of columns and I wish to use them in different models across my projects. I do not want the Choice model to inherit from AuditColumns because am going to use the same technique to include other columns from other sources into my Choice class.
off course what I wrote above is not practical either because I will have to repeat the column names every time I want to include the AuditColumns in one of the models across my project.
Is what I want to do achievable or not?
The usual way to do this is with content types. You create a model similar to AuditColumns, but you also include another field, a GenericForeignKey, which can point to any model within the project's database.
Python will let you do multiple inheritance so you can inherit the attributes of multiple base classes into your Choice class, that may be what you want.
class Choice(AuditColumns,Foo):
choice=models.CharField(max_length=200)
Would give your Choice class the attributes of the AuditColumns class, and the Foo class. You are also misusing self in your example. You are calling the return_audit_columns method of the AuditColumns class that is expecting an instance of that class but passing in an instance of the Choice class which is not what you want.
Related
I have multiple classes for which I have special functions that query ndb in a shorter way, like in this example:
class SomeModel(ndb.Model):
xcode = ndb.StringProperty('c')
descr = ndb.StringProperty('d')
client = ndb.KeyProperty('cl')
order = ndb.IntegerProperty('o')
mod = ndb.DateTimeProperty(auto_now=True)
#classmethod
def q_base(cls, ancestor):
return cls.query(ancestor=ancestor).order(cls.codigo)
The function q_base saves some space and makes the code in the handlers look clearer. But since quite a few models need this exact function, I have to repeat it multiple times, which is a problem.
How can I solve it? Can I just make a BaseClass(ndb.Model), add the functions there and make every other model inherit from it? Or do I have to use PolyModel for that? How would that look? Also, I would appreciate any insight as to what would happen to any existint entities.
I have no experience with GAE but unless they do some very strange things, the canonical solution would be to use either an abstract base class inheriting from ndb.Model - if ndb supports abstract model classes - or a mixin:
class QBaseMixin(object):
#classmethod
def q_base(cls, ancestor):
return cls.query(ancestor=ancestor).order(cls.codigo)
class MyModel(ndb.Model, QBaseMixin):
# model code here
Below are my models and I am using InheritanceManager of django-model-utils. i decided the field user to be in the subclasses because i need to access the Child subclass via the relation like user.child1_set.all().
class Mother(models.Model):
objects = InheritanceManager()
class Child1(Mother):
user = models.ForiegnKey(User)
class Child2(Mother):
user = models.ForiegnKey(User)
the problem is, when i want to query starting from Mother class, there seems to be no query that makes it.
i've tried these codes.
Mother.objects.filter(user=SOMEUSER)
Mother.objects.filter(child1__user=SOMEUSER)
Mother.objects.select_subclasses().filder(user=SOMEUSER)
Mother.objects.select_subclasses().filder(child1__user=SOMEUSER)
any advice would be appreciated.
I have Product as a model.
I am refactoring some code, and there is a recurring query spread all over the code base which needs replacement.
So I'd like to centralize this query, in order to encapsulate its logic.
I'd like something like
<an_object>.get_uncompleted_products(products);
In this case, preserving existing code, products is already a result of a query (products = Products.objects.filter(filter_expression))
This is just a convenience question, I know a possible answer, but where would you put get_uncompleted_products(), what could be a good"django-way" solution?
I was initially wanting to put it on the Product model. But I was thinking Product methods to work directly on a single model reference, thus the signature would need to be:
class Product(models.Model):
#classmethod
get_uncompleted_products(list)
I am not sure why this gives me the feeling to be not so appropriate. A possible alternative would be to put it into a utility module. I could also have it in the view module but it seems it's used profusely in other views as well so I'd prefer somewhere more generic.
I guess the 'django way' would be to define it as a custom manager method, instead of class method, which can be shared between different models with composition instead of inheritance in case of class methods.
from django.db import models
class ProductQuerySet(models.query.QuerySet):
def get_uncompleted_products(self):
...
class ProductManager(models.Manager):
def get_queryset(self):
return ProductQueryset(self.model, using=self._db)
def get_uncompleted_products(self):
# defined twice to resolve queryset chaining issue with custom managers
return self.get_queryset().get_uncompleted_products()
class Product(models.Model):
...
objects = ProductManager()
I'm buildibg some abstract model for about 10 models. I need to make, somehow, that 1 field is not declared in abstract model, but MUST be declared in inheriting models.
How to do that? Is there any way to use NotImplementedError?
I am afraid there isn't an easy way to achieve that, if possible at all, without digging deep into Django.
The main reason is that Field name "hiding" is not permitted in Django. What this means is that if you want to declare an abstract attribute in the base abstract class that is a Field instance, you will not be able to rewrite it in the child classes contrary to the normal Python class inheritance paradigm. To quote from the doc:
In normal Python class inheritance, it is permissible for a child class to override any attribute from the parent class. In Django, this is not permitted for attributes that are Field instances (at least, not at the moment). If a base class has a field called author, you cannot create another model field called author in any class that inherits from that base class.
Overriding fields in a parent model leads to difficulties in areas such as initializing new instances (specifying which field is being initialized in Model.init) and serialization. These are features which normal Python class inheritance doesn't have to deal with in quite the same way, so the difference between Django model inheritance and Python class inheritance isn't arbitrary.
This restriction only applies to attributes which are Field instances. Normal Python attributes can be overridden if you wish. It also only applies to the name of the attribute as Python sees it: if you are manually specifying the database column name, you can have the same column name appearing in both a child and an ancestor model for multi-table inheritance (they are columns in two different database tables).
Django will raise a FieldError if you override any model field in any ancestor model.
However, if the attribute is not a Field instance (very unlikely though), you will be able to achieve exactly what you want by using using #property decorator. Something like this should work:
class Person(models.Model):
def __init__(self, *args, **kwargs):
super(Person, self).__init__(*args, **kwargs)
self.last_name
first_name = models.CharField(max_length=30)
#property
def last_name(self):
raise NotImplementedError
class Meta:
abstract = True
class Student(Person):
home_group = models.CharField(max_length=5)
last_name = "Doe" # "models.CharField()" will not work!
class BadStudent(Person):
home_group = models.CharField(max_length=5)
# "NotImplmentedError" will be raised when instantiating BadStudent()
You may also want to take a look at abc.abstractproperty. I am not sure how it would work with Django's model inheritance though.
Why would you want to do it?? Which are the reasons the common field cannot be declared in the AbstractModel??
If you really want to do it, use the instructions here:
add methods in subclasses within the super class constructor
I have a Django model storing some infrequently changed but often used data. I'm looking for a pattern so that I can refer to them as kind of static class variables, eg, like SomeModel.Bar or SomeModel.Baz.
At the moment I'm using a staticmethod like so:
class SomeModel(models.Model):
name = models.CharField(max_length=100)
#staticmethod
def Baz():
#retrieve from cache or lookup Baz item
return baz
Meaning I refer to the items as SomeModel.Baz() but this just doesn't quite feel right. I just get the impression that I'm doing something wrong. I don't want to make it a property, as I don't want an instance to refer to the item.
Can anyone point me at a pattern or example to show me is I can implement a class level property in this way? Or tell me why I should be doing something totally different? Thanks :).
If you want some logic for model which doesn't belong to particular row, write custom model manager.