How to create constraint (on database to keep integrity) base on columns from child and parent table?
Model:
class DBMaster(models.Model):
col1 = models.CharField()
class DBOne(DBMaster):
col_own....
col1 - should be this same how in DBMaster
class Meta:
constraints = [
models.UniqueConstraint(fields=['col_own', 'col1'], name='CON_UNIQUE_1')
]
We can use materialized view but we wont.
Any sugestions?
I think you should use unique_together in your model and your base model should be abstract
class BaseDBMaster(models.Model):
col1 = models.CharField()
class Meta:
abstract = True
class DBMaster(BaseDBMaster):
pass
class DBOne(BaseDBMaster):
col_own....
col1 - should be this same how in DBMaster
class Meta:
unique_together = ('col1', 'col_own')
Related
I have some models, 1 abstract, and 2 that inherit from the abstract model with a ManyToMany relationship. One model gets its members from the other model. I want to implement a constraint on this model so that its members can't be more than the Sum of the remaining_members on the original groups. I created a Q expression that expresses what I want to achieve, but I know it's not the right way to do it. How can I create the constraint with models that are related by a ManyToMany field?
class AbstractGroup(models.Model):
members = models.IntegerField()
class Meta:
abstract=True
class OriginalGroup(AbstractGroup):
remaining_members = models.IntegerField()
new_group_members = ManyToManyField(NewGroup, related_name=new_group, related_query_name=new_group)
class NewGroup(AbstractGroup):
name = models.CharField()
class Meta:
constraints = [
models.CheckConstraint( Q(members__lte=original_groups__sum__remaining_members, name='%(app_label)s_%(class)s_available_members' ) )
]
In Django I have 2 models that are inherited from an abstract base class. The base class has an IntegerField that I want to rename and change to DecimalField for some instances. There is a ForeignKey linking the 2 child models. I've read about model inheritance in docs, but there seems to be some constraints. What's the best way to change the IntegerField to DecimalField?
class Parent(models.Model):
intfield = models.IntegerField()
class Meta:
abstract=True
class Child1(Parent):
addedfield = models.CharField(max_length=20)
class Child2(Parent):
addedfield2 = models.DecimalField(max_digits=10, decimal_places=2)
linked = models.ForeignKey(Child1, on_delete=models.CASCADE)
class GrandChild1(Child1):
# change intfield to decimal
class GrandChild2(Child2):
# change intfield to decimal
# linked to GrandChild1 instead of Child1
You can use extra abstract models to alter the fields in the hierarchy:
class Parent(models.Model):
intfield = models.IntegerField()
class Meta:
abstract = True
class DescendantType1(Parent):
"""This is an abstract model that inherits from the Parent model, with the "type 1"
attributes.
"""
addedfield = models.CharField(max_length=20)
class Meta:
abstract = True
class DescendantType2(Parent):
"""This is an abstract model that inherits from the Parent model, with the "type 2"
attributes.
"""
addedfield2 = models.DecimalField(max_digits=10, decimal_places=2)
linked = models.ForeignKey(
"Child1",
on_delete=models.CASCADE,
# This is required on foreign key fields in abstract models.
# See the "Note about foreign key related names" below.
related_name="%(app_label)s_%(class)s_related",
related_query_name="%(app_label)s_%(class)ss",
)
class Meta:
abstract = True
class Child1(DescendantType1):
"""A descendant with "type 1" attributes."""
class Child2(DescendantType2):
"""A descendant with "type 2" attributes."""
class GrandChild1(DescendantType1):
intfield = models.DecimalField(...)
class GrandChild2(DescendantType2):
intfield = models.DecimalField(...)
linked = models.ForeignKey(
"GrandChild1",
on_delete=models.CASCADE,
)
Note about foreign key related names
An abstract model that has a foreign key needs to use a different related_name and related_query_name for each concrete model that inherits from it, otherwise the names for the reverse relationship would be the same for each subclass.
To handle this, django allows you to use template strings with the variables app_label and class so that the names are unique for the child model.
You can find more about this in the documentation.
I have the following models:
class Address(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
....
class Meta:
abstract = True
class BillingAddress(Address):
is_default = models.BooleanField()
...
class Meta:
db_table = 'billing_address'
I'm trying to build a serializer for BillingAddress:
class AddressSerializer(serializers.ModelSerializer):
class Meta:
abstract = True
model = AddressModel
class BillingAddressSerializer(AddressSerializer):
def to_representation(self, obj):
return AddressSerializer(obj, context=self.context).to_representation(obj)
class Meta(AddressSerializer.Meta):
model = UserBillingAddress
fields = (
'id',
'is_default',
)
I keep getting:
ValueError: Cannot use ModelSerializer with Abstract Models.
How can I build my BillingAddressSerializer to reflect both classes?
An abstract model is a base class in which you define fields you want to include in all child models. Django doesn't create any database table for abstract models. A database table is created for each child model, including the fields inherited from the abstract class and the ones defined in the child model.
Since there is no "Address" table, so "AddressSerializer" would be invalid.
Currently, most of my models look like this:
class A(models.Model):
# model attributes
class Meta:
db_table = 'A'
class B(models.Model):
# model attributes
class Meta:
db_table = 'B'
Is there a way to do this automatically? I tried adding the meta class after defining the class, but because of how Django handles Meta classes for models, this doesn't work. Am I just stuck defining the Meta classes by hand?
Not sure why you want to do that but you could do something like:
for model in models:
model._meta.db_table = model.__class__.__name__
I am trying to figure out how to set up my nested serializers.
# models.py
class Product(models.Model):
sku = models.CharField()
product_name = models.CharField()
class Order(models.Model):
name = models.CharField()
address = models.CharField()
class OrderProduct(models.Model):
order = models.ForeignKey( Order )
product = models.ForeignKey( Product )
quantity = models.IntegerField()
So I want to have an api that can create an order in the form of the following:
{
"name" : "James",
"address" : "100 Main St",
"products" : [
{ "sku" : "1234", "quantity" : 1 }
]
}
I understand that I would need nest OrderProductSerializer inside OrderSerializer, but how do I implement it here when the "products" data use the field "sku" which is not found in the OrderProduct model. Do I do double-nesting? How does that look like?
# serializers.py
class OrderProductSerializer( serializers.ModelSerializer):
class Meta:
model = OrderProduct
exclude = ()
class OrderSerializer(serializers.ModelSerializer):
products = OrderProductsSerializer(many=True)
class Meta:
model = Order
exclude = ()
You are trying to implement Nested Serialize on reverse relationship. So, you have to explicitly provide the relationship name as the parameter to the serializer via source argument.
Try this
class OrderProductSerializer(serializers.ModelSerializer):
class Meta:
model = OrderProduct
fields = '__all__'
class OrderSerializer(serializers.ModelSerializer):
product = OrderProductSerializer(many=True, source='product_set')
class Meta:
model = Order
fields = '__all__'
For more info reffere these docs
1. DRF Nested Relationship
2. DRF-Reverse Realation
3. What is reverse-relationship in Django