Avoid hardcoding of a model name - django

Django 4.1
class Task(models.Model):
cypher = models.CharField(
max_length=255,
null=False,
default="",
)
class Meta:
db_table = "{}_{}_{}".format(TablePrefixes.FIPI.value,
__package__,
"Task")
Here in db_table I hardcoded "Task". Could you tell me whether it is possible to somehow avoid hardcoding?

Related

Multiple model inheritance with one concrete and one abstract model in 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()
.....

How to get the content type model name using the slug field

I would like to get the model name from the content type.
I have tried this ....
a=Module.objects.filter(slug="sales")
So it return SoftDeletionQueryset
So after that I just done the following
for x in a: print(x.content_type)
So it return "sales analytics". That is the content_type value in the Module.content_type field
I have the content_type values now ..... The content type model having the 3 fields right ? app_label,model,name So I want to get the model name according to the content_type values –
Here is my code
class Module(BaseModel, SoftDeletionModel):
id = models.AutoField(primary_key=True)
name = models.CharField(
_("Module Name"), max_length=50, default=False, unique=True)
slug = models.SlugField(unique=True)
display_name = models.CharField(
_("Display Name"), max_length=50, default=False)
content_type = models.ForeignKey(ContentType,
blank=True, null=True, on_delete=models.CASCADE)
parent_module_id = models.ForeignKey("Module",
blank=True, null=True, on_delete=models.CASCADE)
order = models.IntegerField(_("Order"), default=0, blank=True, null=True)
class Meta:
db_table = 'modules'
def __str__(self):
return "{0}".format(self.display_name)
I don't really understand the question, but I will try to answer
You use print() and it returns __str__ func result.
If you want to get the model name you have to use this code or content_type
modules = Module.objects.filter(slug="sales")
for m in modules:
print(m.name)
print(m.content_type)
If you mean exactly classname
For that use .__class__.__name__ or Module.__name__

How to authenticate an insert or return error

im implementing a simple API CRUD using Django + Django rest and have a doubt.
I have two models:
class Shoe(models.Model):
_id = models.AutoField(primary_key=True)
description = models.CharField(max_length=100, null=False, blank=False)
provider = models.CharField(max_length=100, null=False, blank=False)
type = models.CharField(max_length=2, choices=TIPO_CHOICES, null=False, blank=False)
cost_price = models.DecimalField(
max_digits=6, decimal_places=2, verbose_name = 'Preço de Custo',
null=False, blank=False
)
sale_price = models.DecimalField(
max_digits=6, decimal_places=2, verbose_name = 'Preço de Venda',
null=False, blank=False
)
class Stock(models.Model):
_id = models.AutoField(primary_key=True)
id_shoe = models.ForeignKey(
Shoe, on_delete = models.CASCADE, verbose_name = 'shoe', related_name = 'stock')
size = models.IntegerField(choices=NUMERACAO_CHOICES, null=False, blank=False)
amount = models.IntegerField(null=False, default=0)
What I am wanting is, when someone tries to make an insertion of stock of a size (of a certain shoe) that already exists it returns error. I can not just be 'unique' in the parameters of size. Any suggestions on how to do this?
Since you want only one Stock item for each unique combination of shoe and size, you can use unique_together [Django-doc] here:
class Stock(models.Model):
shoe = models.ForeignKey(Shoe, on_delete=models.CASCADE, verbose_name='shoe', related_name='stock')
size = models.IntegerField(choices=NUMERACAO_CHOICES, null=False, blank=False)
amount = models.IntegerField(null=False, default=0)
class Meta:
unique_together = ('shoe', 'size')
Note the name of a ForeignKey is usually not prefixed or suffixed with id_ or _id, Django automatically creates a "twin" field with the _id suffix that stores the primary key of the referenced value.
Note: If you do not specify a primary key, Django will automatically make one named id, so here it is probably better to let Django implement the logic.
if you are using Django 2.2 you can use UniqueConstraint instead of unique_together like this:
class Meta:
constraints = [
models.UniqueConstraint(fields=['shoe', 'size'], name='give_it_some_name')
]
As the docs state:
Use UniqueConstraint with the constraints option instead.
UniqueConstraint provides more functionality than unique_together. unique_together may be deprecated in the future.

Django rest nested serializer not displaying fields

I have a model Workflow and WorkflowLevel. Each workflow has many WOrkflow levels .Im trying to use nested serializer :
class WorkflowLevelSerializer
(serializers.ModelSerializer):
class Meta:
model = WorkflowLevel
fields = '__all__'
class
WorkflowSerializer
(serializers.ModelSerializer):
levels = WorkflowLevelSerializer(many=True)
class Meta:
model = Workflow
fields = ('id', 'name', 'description',
'tenant', 'levels')
models.py:
class Workflow(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=32, default=None, null=True)
description = models.CharField(max_length=100, default=None, null=True)
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, default=None,
null=False)
class Meta:
unique_together = ('name', 'tenant',)
class WorkflowLevel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE,
default=None, null=False)
level = models.IntegerField(default=None, null=False)
operation = models.CharField(max_length=32, default=None, null=False)
class Meta:
unique_together = ('workflow', 'level',)
The levels field is not displaying in the workflow listAPI view .
Getting error:
Got AttributeError when attempting to get a value
for field `levels` on serializer
`WorkflowSerializer`.
The serializer field might be named incorrectly
and not match any attribute or key on the
`Workflow` instance.
Original exception text was: 'Workflow' object
has no attribute 'levels'.
You can define related_name in the Model like this:
workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE, related_name="levels", default=None, null=False)
I am using related_name='levels', so that in Serializer, it will use that reverse relationship name to fetch WorkflowLevel data from db.

Django queryset for multilevel Foreignkey reference

Following are my models:
class A(models.Model):
owner = models.ForeignKey(User, null=False)
a_name= models.CharField(max_length=200, null=False, unique=True)
class B(models.Model):
owner = models.ForeignKey(User)
b_name= models.CharField(max_length=100, null=False)
class C(models.Model):
a= models.OneToOneField(
A,
on_delete=models.CASCADE,
null=False,
unique=True,
)
b= models.OneToOneField(
B,
on_delete=models.CASCADE,
null=False,
unique=True,
)
class D(models.Model):
c= models.OneToOneField(C,
on_delete=models.CASCADE,
null=False,
unique=True,
)
d1 = models.IntegerField(null=False, default=1)
I am trying to override the queryset in ListView generic class to get the list of all the objects in model 'D' where the 'owner' in model 'A' in current logged in user. I am unable to write the filter for the query.
D.objects.filter(self.c__a__owner==self.request.user)
But I am getting error as:
'MyListView' object has no attribute 'c__a__owner'
Please guide me how to achieve this.
Thanks.
Your query shouldn't have self. Also, you use a keyword assignment instead of a comparison in the filter method. It should like:
D.objects.filter(c__a__owner=self.request.user)