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
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 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)
How to update more than one object of different model types from one end point. I tried it many ways but i still fails.I tried through nested serializer and create method, but it is still not working
class Student(models.Model):
name = models.CharField(max_length=300)
sex = models.CharField(choices=SEX_CHOICES,max_length=255,
null=True)
Category = models.CharField(max_length=100, null=True)
def __str__(self):
return self.name
class Registration(models.Model):
registration_no = models.CharField(max_length=255,
unique=True)
student = models.OneToOneField(Student,
on_delete= models.CASCADE, related_name='registrations')
def __str__(self):
return self.registration_no
class RegistrationSerializer(serializers.ModelSerializer):
class Meta:
model = Registration
fields = '__all__'
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = '__all__'
class StudentDataMigrateSerializer(serializers.Serializer):
student = StudentSerializer()
registation = RegistrationSerializer()
In Django Rest Framework by default the nested serializers are read only. To have a writable nested serializer you need to implement create() and/or update() methods.
Take a look at the official documentation https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers
class StudentDataMigrateSerializer(serializers.Serializer):
student = StudentSerializer()
registation = RegistrationSerializer()
def create(self, validated_data):
# save the data
I have the following two models:
class Timestampable(models.Model):
created_at = models.DateTimeField(null=True, default=None)
updated_at = models.DateTimeField(null=True, default=None)
class Meta:
abstract = True
def save(self, *args, **kwargs):
now = timezone.now()
if not self.created_at:
self.created_at = now
self.updated_at = now
super(Timestampable, self).save(*args, **kwargs)
class Attachment(Timestampable, models.Model):
uuid = models.CharField(max_length=64, unique=True)
customer = models.CharField(max_length=64)
user = models.CharField(max_length=64)
file = models.FileField(upload_to=upload_to)
filename = models.CharField(max_length=255)
mime = models.CharField(max_length=255)
publicly_accessible = models.BooleanField(default=False)
When I try to migrate these models, I get the following error:
django.core.exceptions.FieldError: Local field 'created_at' in class 'Attachment' clashes with field of similar name from base class 'Timestampable'
I read here, here, and here that this should work when the base class is abstract. However, I marked it as abstract it still it doesn't seem to work. What else could be wrong? I am using Django 1.8.14.
I found what was the problem. I used to have the class Timestampable not inherit from models.Model. Therefore, in one of my initial migrations, I had the line:
bases=(at_common.behaviours.Timestampable, models.Model),
I was looking for a way to remove this. Turned out that I just had to delete this line from the initial migration file.
Because your Timestampable model already extends from models.Model. You don't need extend Attachment model.
please use:
class Attachment(Timestampable):
instead of:
class Attachment(Timestampable, models.Model):
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