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
Related
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)
I am creating my first django project and after having created a model A I realize that I want to create other models B, C ... that have certain traits in common with A but which needs to be separat models. Thus I created an abstract class 'InteractableItem' with these traits.
I want users to be able to like interactable items, however I also want to constrain the instantiation of a 'Like' model such that each user only can like a given interactable item once. To solve this I tried creating a models.UniqueConstraint in the like model between the fields 'user' and 'interactableitem'. This gave me the following error
ERRORS:
feed.Like.interactableitem: (fields.E300) Field defines a relation with model 'InteractableItem', which is either not installed, or is abstract.
feed.Like.interactableitem: (fields.E307) The field feed.Like.interactableitem was declared with a lazy reference to 'feed.interactableitem', but app 'feed' doesn't provide model 'interactableitem'.
I realise that my error is the referencing of an abstract class through a ForeignKey, however I dont see a way to constrain the instantiation of the like if the 'user' liking and the 'interactableitem' being like are not both fields in 'like'. This is where I need help.
How do you establish an instantiation constraint on such a 'Like' model?
Here I provide my referenced models:
class InteractableItem(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
date_update = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
class Meta:
abstract = True
class Like(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
interactableitem = models.ForeignKey(InteractableItem, on_delete=models.CASCADE, null=True, blank=True)
class Meta:
constraints = [
models.UniqueConstraint(fields=['user', 'interactableitem'], name='user_unique_like'),
]
After having tested different ways to constrain the instatiation of the 'like' model I realised that there was a way around this.
I let the abstract class 'BaseItem' have a ForeignKey to a regular class 'interactableitem'. 'Like' now has a models.Uniqueconstrait with two ForeignKey fields to regular classes which works. This way I just have to makesure that interactableitem is only created once, I'm sure there are better ways of doing this but this if self.pk should work for all scenarios I can think of, as it checks if the item is in the database before creation.
class InteractableItem(models.Model):
pass
class SomeItem(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
date_update = models.DateTimeField(auto_now=True)
interactableitem = models.ForeignKey(InteractableItem, on_delete=models.CASCADE, null=True, blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
class Meta:
abstract = True
def save(self, *args, **kwargs):
if not self.pk:
self.interactableitem = InteractableItem.objects.create()
super(SomeItem, self).save(*args, **kwargs)
class Like(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
interactableitem = models.ForeignKey(InteractableItem, on_delete=models.CASCADE, null=True, blank=True)
class Meta:
constraints = [
models.UniqueConstraint(fields=['user', 'interactableitem'], name='user_unique_like'),
]
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'))