Multiple model inheritance with one concrete and one abstract model in django - django

I wanted to inherit the Grandparent abstract model, parent concert model in the child model. How I'll be able to achieve this in django?
There are conflicts in field name as the abstract model is having audit fields. which is common going to be common in both parent and child class. How do I override or remove the common field coming from the parent model?
Below is the models which showcase what I wanted to achieve.
class Audit(models.Model):
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
class Meta:
abstract = True
class User(Audit):
class Meta:
db_table = 'user'
email = models.EmailField(unique=True)
phone = models.CharField(validators=[phone_regex], max_length=50, unique=True)
is_active = models.BooleanField(default=False)
class UserProfile(User, Audit):
class Meta:
db_table = 'user_profile'
address = models.TextField(null=True)
profile_image = models.TextField(null=True)
dob = models.DateField()
.....

Related

How to include ManyToMany Fields in DjangoRestFramework?

class EntityServiceSerializer(serializers.ModelSerializer):
class Meta:
model = Service
fields = '__all__'
class EntityCreateSerializer(serializers.ModelSerializer):
entity_service = EntityServiceSerializerThrough(read_only=True, source='serviceschedule_set', many=True)
class Meta:
model = Entity
fields = '__all__'
Model looks like this
class Entity(models.Model):
entity_service = models.ManyToManyField(Service, through='ServiceSchedule')
class ServiceSchedule(models.Model):
service = models.ForeignKey(Service, on_delete=models.CASCADE)
entity = models.ForeignKey(Entity, on_delete=models.CASCADE)
class Service(models.Model):
service_name = models.CharField(max_length=256, null=True)
slug = models.SlugField(max_length=128, unique=True, null=False, editable=False)
created_at = models.DateTimeField(editable=False, default=timezone.now)
updated_at = models.DateTimeField(default=timezone.now)
animal = models.ForeignKey(Animal, on_delete=models.CASCADE, default=None)
I have these serializers (there are more fields in entity model, but they're irrelevant since the only problem i have is with the Many2Many)
The thing is, when i put in body "entity_service": [1,2] in the response i still get = []. Even though i have in my database Services with pk 1,2,3,4.
Do you know how can i make it work?
Try it without a source as the field name is the same as the model field name
class EntityCreateSerializer(serializers.ModelSerializer):
entity_service = EntityServiceSerializerThrough(read_only=True, many=True)
class Meta:
model = Entity
fields = '__all__'

Serialize and create one-to-one relation with parent_link true in django and django rest framework

How to save the object with one-to-one relation and having parent_link=True using serializer. Below are my models and serializer having some fields from the actual model that I wanted to implement. I am not able to save the 'user' relation in the database. It is throwing the integrity error.
class Audit(models.Model):
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
class Meta:
abstract = True
class User(Audit):
class Meta:
db_table = 'user'
email = models.EmailField(unique=True)
password = models.TextField()
is_active = models.BooleanField(default=False)
class UserProfile(User):
class Meta:
db_table = 'user_profile'
user = models.OneToOneField(User, on_delete=models.CASCADE, parent_link=True,
primary_key=True)
address = models.TextField(null=True)
dob = models.DateField()
language = models.CharField(max_length=50, null=True)
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['user', 'address', 'dob', 'language']
And the requested data looks like this.
{
"email": "abc#pqr.com",
"password": "1234",
"dob": "2021-12-11",
"language" : "English"
}
You can pass user when saving serializer :
serializer.save(user=<USER>)
Note that if you want to create user when creating user profile, you should override create() method in your serializer, first create your user, then create user profile, and pass created user to it

Optional Field on base class but mandatory on child class in Django

i would like to know if its possible to have 2 classes (base=person and a child=user) where i have a property (email) nullable on base but it must be set for child class
class Person(models.Model):
name = models.CharField(max_length=60, )
identification = models.CharField(max_length=20, unique=True)
email = models.CharField(max_length=60, null=True) #<~~~~ Email can be null
def __str__():
return self.name
class User(Person):
email = models.CharField(max_length=60, ) #<~~~~ Email CAN'T be null
If i leave it like this i get this error:
django.core.exceptions.FieldError: Local field 'email' in class 'User' clashes with field of the same name from base class 'Person'.
Thanks.
When you are doing multi model inheritance, then the child creates a OneToOne relation to Parent Model, so in Child Model the fields(in your case email) from Parent does not exist(Database wise). So in this approach, you can't make email field not null.
So its better to declare a base abstract class. Then subclass both Person and User model from there. For example:
class Base(models.Model):
name = models.CharField(max_length=60, )
identification = models.CharField(max_length=20, unique=True)
email = models.CharField(max_length=60, blank=True, null=True, default=None)
class Meta:
abstract = True
class Person(Base):
def __str__(self):
return self.name
class User(Base):
email = models.CharField(max_length=60) # <-- Override the base email field
def __str__(self):
return self.name
You can override field properties.
Keep Person email field as usual.
Change User email field by
email = models.CharField(max_length=60, null=False)
You have to add class Meta: abstract = True (Note: and don't use null in character field, use blank instead.)::
ie:
class Human(models.Model):
name = models.CharField(max_length=60, )
identification = models.CharField(max_length=20, unique=True)
email = models.CharField(max_length=60, blank=True)
class Meta:
abstract = True
class Person(Human):
def __str__():
return self.name
class User(Human):
email = models.CharField(max_length=60 ) #<~~~~ Email CAN'T be null

How do I automatically filter out objects in a query set if a field in an object is set to true in Django?

I have a model like so...
class Driver(SupremeModel):
name = models.TextField(null=False, blank=False)
car = models.ForeignKey('Cars.Car', null=False, blank=False)
This model inherits from this abstract model...
class SupremeModel(models.Model):
creator = models.ForeignKey(User, related_name="%(class)s_creator", null=True, blank=True)
created = models.DateTimeField(null=True, blank=True)
deleted = models.BooleanField(default=False)
modified = models.DateTimeField(null=True,blank=True)
class Meta:
abstract = True
Then I have a ModelForm like so...
class DriverForm(SupremeModelForm):
class Meta(SupremeModelForm.Meta):
model = Driver
DriverForm inherits from this SupremeModelForm...
class SupremeModelForm(ModelForm):
class Meta:
exclude = ['created', 'creator', 'deleted', 'modified']
I want to make it so anytime anything that inherits from SupremeModel is queried for data, it automatically excludes all the data where deleted=True...
In this case, so that when I render the DriverModelForm, deleted entries of car are not displayed...
Is there anyway I can do this?
After some more research I discovered the solution is to override the default model manager of the abstract model... Like so...
class SupremeManager(models.Manager):
def get_queryset(self):
return super(SupremeManager, self).get_queryset().filter(deleted=False)
class SupremeModel(models.Model):
creator = models.ForeignKey(User, related_name="%(class)s_creator", null=True, blank=True)
created = models.DateTimeField(null=True, blank=True)
deleted = models.BooleanField(default=False)
modified = models.DateTimeField(null=True,blank=True)
objects = SupremeManager()
class Meta:
abstract = True

Django inheritence question

some body please explain me the following i have two classes Userprofile and Staff.staff inherits userprofile
My Question is that if any entry has to be made to a staff table .1.It would be mandatory to fill out the details of user profile right?
Please explain this inheritence.Thanks
class Profile(models.Model):
user = models.ForeignKey(User, unique=True)
created_date = models.DateTimeField(auto_now_add=True)
emp_first_name = models.CharField(max_length=255)
emp_last_name = models.CharField(max_length=255)
gender = models.CharField(max_length=2, choices = GENDER_CHOICES, null=False)
date_of_birth = models.DateField(blank=True,null=True)
address1 = models.CharField(max_length=255)
city = models.CharField(max_length=48)
state = models.CharField(max_length=48)
country = models.CharField(max_length=48)
email_id = models.EmailField(blank=True)
class Staff(UserProfile):
role = models.ManyToManyField(Role)
designation = models.CharField(max_length=48, blank=True, null=True)
education = models.CharField(max_length=255, blank=True, null=True)
If you take a look at https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance you'll see that automatic One-to-One mappings are created. Therefore, an entry for UserProfile is saved, and an entry for Staff is saved with a OneToOne field that points to the UserProfile entry.
However, if you want Staff to just inherit all the fields, I'd recommend setting abstract = True in your UserProfile. This means that Staff inherits all those fields, but you can never create a UserProfile by itself (as described at
https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes )
class Meta:
abstract = True