I have some columns that are repeated in multiple models. is there any solution to place them somewhere and use it any model?
You can achieve this by creating base classes and inheriting them in your models.
Example:
class TimestampsModel(models.Model):
#classmethod
def get_fields(cls, fields: tuple):
return fields.__add__(('created_at', 'updated_at'))
created_at = models.DateTimeField(("created_at"), auto_now_add=True)
updated_at = models.DateTimeField(("updated_at"), auto_now=True)
You can also make it abstract and Django won't create migrations for this.
class Meta:
abstract = True
Finally, a model would be:
class Blog(baseModels.TimestampsModel):
class Meta:
db_table = "blog"
title = models.CharField(max_length=100)
Related
I'd like to add foreign keys to virtually every model in my app to allow different Sites. For this I think it would be nice to use decorators, because I will be able to only add those FKs under certain conditions (e.g. if Sites is installed).
Unfortunately my attempt doesn't do anything:
def add_site_fk_field(model_to_annotate: models.Model):
"""Add FK to Site to Model"""
model_to_annotate.site = models.ForeignKey(Site, on_delete=models.CASCADE)
return model_to_annotate
#add_site_fk_field
class Test(models.Model):
...
Is it somehow possible to do this? I prefet not to use abstract classes.
As I know you cant do it with decorator. But you can do that with creating an abstract base model class.
For example:
from django.db import models
class Site(models.Model):
name = models.CharField(max_length=60)
class AddSiteFkField(models.Model):
fk_site = models.ForeignKey(Site, on_delete=models.CASCADE)
class Meta:
abstract = True
class Test(AddSiteFkField):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
I would like to display a model in the django admin but with the logic to choose between 2 models to display.
Current Implementation:
Models
class User(models.Model):
created = models.DateTimeField(auto_now_add=True, null=True)
last_updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=30, blank=True)
class ExpectedNames(User):
class Meta:
proxy=True`
Admin
#admin.register(ExpectedNames)
class ExpectedNamesAdmin(admin.ModelAdmin):
date_hierarchy = 'created'
What I Would like to DO: # something like this
Models
class User(models.Model):
created = models.DateTimeField(auto_now_add=True, null=True)
last_updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=30, blank=True)
class User2(models.Model):
created = models.DateTimeField(auto_now_add=True, null=True)
last_updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=30, blank=True)
class ExpectedNames(User):
class Meta:
proxy=True
if name == "Rick":
return User
else:
return User2
Admin
#admin.register(ExpectedNames)
class ExpectedNamesAdmin(admin.ModelAdmin):
date_hierarchy = 'created'
Any suggestions not sure if this is the correct way to do this.
I think this is not possible as it states in the Django Documentation:
Base class restrictions:
A proxy model must inherit from exactly one non-abstract model class. You can’t inherit from multiple non-abstract models as the proxy model doesn’t provide any connection between the rows in the different database tables. A proxy model can inherit from any number of abstract model classes, providing they do not define any model fields. A proxy model may also inherit from any number of proxy models that share a common non-abstract parent class.
https://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models
I use magic method new in same situation.
I have model Documen with field document_type. If document_type is 'contract' i want ContractProxy, if 'offer' - OfferProxy.
For do this I create new proxy:
class RelatedDocumentProxy(Document):
class Meta:
proxy = True
def __new__(cls, *args, **kwargs):
doc_type = args[1]
if doc_type == 'contract':
return ContractProxy(*args, **kwargs)
return OfferProxy(*args, **kwargs)
document_type is first field and will first arg who pass to method
I have a Django model used extensively in my app. I'd like to create another model that inherits from that one so I can continue using the original model throughout the code, but move a field to the new model
I have:
class MyModel(models.Model):
field1 =...
field2=...
field3=...
I want to move field3 to a new model:
class MyModel2(MyModel):
field3=...
Then I'd like MyModel instances where field3 is not null to become MyModel2 instances.
The code would continue to refer to MyModel, but in some special cases, I'd use MyModel2 instead. Is this possible? Advisable? Is there a better way? I considered making a base abstract model that both could inherit from, but then you can't use the abstract model in forms and things.
Actual model:
class Unit(models.Model):
address = models.ForeignKey(Address)
name = models.CharField(max_length=500, verbose_name="Unit Name")
payments = GenericRelation("Payment", content_type_field='content_type', object_id_field='object_pk')
permissions = GenericRelation("CustomPermission", content_type_field='content_type', object_id_field='object_pk')
association = models.ForeignKey(Association, blank=True, null=True)
def __unicode__(self):
return self.name
"association" is the field I want to move to another model.
I guess you should use abstract = True https://docs.djangoproject.com/en/1.10/topics/db/models/#abstract-base-classes
class MyModel(models.Model):
field1 =...
field2=...
field3=...
class Meta:
abstract = True
class MyModel2(MyModel):
field4=...
class AssociationBase(models.Model):
association = models.ForeignKey(Association, blank=True, null=True)
class Meta:
abstract = True
class Unit(AssociationBase):
address = models.ForeignKey(Address)
name = models.CharField(max_length=500, verbose_name="Unit Name")
payments = GenericRelation("Payment", content_type_field='content_type', object_id_field='object_pk')
permissions = GenericRelation("CustomPermission", content_type_field='content_type', object_id_field='object_pk')
def __unicode__(self):
return self.name
Is there a way to build django models hierarchy like this?
class LikableObjectMixin(models.Model):
# mixin for all likable objects: posts, photos, etc
likers = models.ManyToManyField(Account)
class Meta:
abstract = True
def save():
super(LikableObjectMixin, self).save()
class Post(LikableObjectMixin, models.Model):
message = models.TextField(_('Post'))
author = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='posts', blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
Can south work with this kind of inheritance? Is this an appropriate way to build model hierarchy?
Django=1.5.1
Yes, it's perfectly fine. South will create proper m2m relations for all your models that inherit from your mixin. You don't even have to write save method explicitly. So:
class LikableObjectMixin(models.Model):
likers = models.ManyToManyField(Account)
class Meta:
abstract = True
class Post(LikableObjectMixin):
message = models.TextField(_('Post'))
I've created a mixin and inherited from it in some models. The problem is when I create a schema migration, the mixin's fields are there.
class MyMixin(object):
a_field = models.CharField(max_length=30, blank=True)
another_field = models.DateTimeField(blank=True, null=True)
class Meta:
abstract = True
class MyModel(models.Model, myMixin):
...
Any ideas?
Seem to have got it working using the following
class MyMixin(models.Model):
a_field = models.CharField(max_length=30, blank=True)
another_field = models.DateTimeField(blank=True, null=True)
class Meta:
abstract = True
class MyModel(myMixin, models.Model):
...
The changes are:
MyMixin inherits Model rather than object (despite many discussions around the place saying that mixins for django should inherit object rather than Model)
the order of inheritance for MyModel - the mixin has to come first