DJANGO: How can I duplicate attribute from other class? - python

I want to duplicate an attribute from other class.
class PedidoCliente(Pedido):
total_pagado = models.DecimalField(blank=True, max_digits=10, decimal_places=2,default = 0,verbose_name="Pagado $") # default 0 para el error for += int
barril_encargado = models.DecimalField(blank=True, default=0, max_digits=10, decimal_places=2,verbose_name="Barr. entregados")
fecha_entrega = models.DateField(verbose_name="Fecha Entrega")
class DetallePedidoCliente(DetallePedido):
comments = models.CharField(max_length=300, verbose_name="Comentarios")
precio_venta = models.DecimalField(max_digits=16, decimal_places=2, default = 0)
pedido = models.ForeignKey(PedidoCliente,on_delete=models.CASCADE)
fecha_entrega = the same from PedidoCliente
I'm new at OPP so sorry if it's a silly question.
Thanks!

One should not look to mirror fields of another model. This simply leads to extra work. One needs to update this mirrored field each time it is updated in the other table, etc.
Also it is not very useful when we have already cemented the relationship between the two tables using a Foreign Key.
To access a related fields data is very easy in Django. Suppose we have an instance of DetallePedidoCliente named instance using this we can access the fecha_entrega of the related model by the foreign key as follows:
instance.pedido.fecha_entrega
If one just wants an easy way to refer to this field one may consider adding a property to the model:
class DetallePedidoCliente(DetallePedido):
comments = models.CharField(max_length=300, verbose_name="Comentarios")
precio_venta = models.DecimalField(max_digits=16, decimal_places=2, default = 0)
pedido = models.ForeignKey(PedidoCliente,on_delete=models.CASCADE)
#property
def fecha_entrega(self):
return self.pedido.fecha_entrega
Now we can simply access the field as:
instance.fecha_entrega

Related

Django Many to Many field dependent on another many to many field

I'm creating two many-to-many fields based on same model in a single model. I would like to show only those instances in second many-to-many field which are selected in first many to many field to further apply selection. Through which approach should i handle this behaviour.
class Params(models.Model):
name = models.CharField(max_length = 200)
comments = Model.TextField()
def __str__(self):
return self.name
class Selection(models.Model):
select_params = models.ManyToManyField(Params, blank=True, related_name = "selection_1")
edit_selected_params = models.ManyToManyField(Params, blank=True, related_name =
"selection_from_selec_params")
Thanks and regards
You can use SubQuery is think:
selected = Selection.objects.filter(
edit_selected_params__in=SubQuery(
Selection.objects.filter(select_params__isnull=False).values_list("select_params", flat=True)
)
)
You can see SubQuery docs

Django collection of instances of same model

I'm new to Django
I'm currently using django 3.2.6. I want make multiple instances of route_stop model and store in SchoolRouteStop.route_graph model.I don't want use ForeignKey because i want to make somthing like like nested dict.
from django.db import models
class geo_fence(models.Model):
radius = models.FloatField()
class geo_location(models.Model):
latitude = models.FloatField()
longitude = models.FloatField()
class address(models.Model):
entity = models.fields.CharField(max_length=100)
apt_plot = models.fields.CharField(max_length=100)
street = models.fields.CharField(max_length=100)
city = models.fields.CharField(max_length=100)
state = models.fields.CharField(max_length=2) #state name in short code
zip_code = models.fields.IntegerField()
class route_stop(models.Model): # this for multiple bus stops
route_stop_id = models.fields.IntegerField()
school_id = models.fields.CharField(max_length=100)
route_number = models.fields.CharField(max_length=100)
school_route_stop_uuid = models.fields.CharField(max_length=100, primary_key=True)
registered_arrival_time = models.TimeField()
time_from_src = models.FloatField()
is_school = models.BooleanField(default=False)
geo_fence = models.ForeignKey(geo_fence, on_delete =models.CASCADE)
geo_location = models.ForeignKey(geo_location, on_delete = models.CASCADE)
address = models.ForeignKey(address, on_delete = models.CASCADE)
class SchoolRouteStop(models.Model):
school_id = models.CharField(max_length=100)
school_route_number = models.IntegerField()
route_type = models.CharField(max_length=2)
route_id = str(school_id)+'_'+str(school_route_number)+str(route_type)
route_graph= models.ForeignKey(route_stop,related_name='School', on_delete = models.CASCADE)
# Create your models here.
You have to use a ForeignKey here because you will lose all the Django ORM features and performances if you try to hack this.
Trying to use a JSONField or something else instead would also mean losing integrity constraints you would need to implement yourself, which you really want to avoid.
The way Django works is you implement your models to be stored efficiently in the database, then you use views & serializers to manipulate them.
Your models need to be refined, I really have a hard time understanding their real purpose because there are id fields everywhere (that should also probably be ForeignkeyField), and everything seems a little confusing.
For example, why is school_route_stop_uuid a CharField when UUIDField does exist?
Why is route_id not a property?
Also, make sure to follow the naming conventions in Python, it will make you code way cleaner. According to PEP 8 (https://www.python.org/dev/peps/pep-0008/#class-names):
Class names should normally use the CapWords convention.

How do I check if two instances of a Django model are the same across a set of attributes and annotate a queryset accordingly?

My app has a model "OptimizationResult", where I store results from mathmatical optimization. The optimization distributes timeslots over projects. I need to indicate whether the current results is different from a recent result, based on a set of attributes (in particularly not the primary key)
The attribute optimization_run is a coutner for different runs
Project is a ForeignKey to the project.
By overwriting the __hash__ and __eq__ functions on the model I can compare the different instances by
OptimizationResults.objects.filter(proj = 1).filter(optimization_run =1).first() == OptimizationResults.objects.filter(proj = 1).filter(optimization_run = 2).first()
. But as I understand __eq__ and __hash__ are not available on the database.
How would I annotate the results accordingly? Something like
OptimizationResults.objects.filter(optimization_run = 2).annotate(same_as_before = Case(When(),default=False))
Edit
Added .first() to the code, to ensure that there is only one element.
class OptimizationResult(models.Model):
project = models.ForeignKey(project, on_delete=models.CASCADE)
request_weight = models.IntegerField()
periods_to_plan = models.IntegerField()
unscheduled_periods = models.IntegerField()
scheduled_periods = models.IntegerField()
start = models.DateField(null=True, blank=True, default=None)
end = models.DateField(null=True, blank=True, default=None)
pub_date = models.DateTimeField('Erstellungsdatum', auto_now_add=True, editable=False)
optimization_run= models.ForeignKey(OptimizationRun, on_delete=models.CASCADE)
I'd like to compore different entries on the basis of start and end.
Edit 2
My fruitless attempt with Subquery:
old = OptimizationResult.objects.filter(project=OuterRef('pk')).filter(optimization_run=19)
newest = OptimizationResult.objects.filter(project=OuterRef('pk')).filter(optimization_run=21)
Project.objects.annotate(changed = Subquery(newest.values('start')[:1])== Subquery(old.values('start')[:1]))
results in TypeError: QuerySet.annotate() received non-expression(s): False
We can use a subquery here, to make an annotation:
from django.db.models import Exists, OuterRef, Subquery, Q
to_exclude = {'pk', 'id', 'project', 'project_id', 'optimization_run', 'optimization_run_id'}
subquery = OptimizationResult.objects.filter(
project_id=OuterRef('project_id')
optimization_run=1,
**{f.name: OuterRef(f.name)
for f in OptimizationResult._meta.get_fields()
if f.name not in to_exclude
}
)
OptimizationResult.objects.filter(
optimization_run=2
).annotate(
are_same=Exist(subquery)
)
Here we will thus annotate all the OptimizationResults with an optimization_run=2, with an extra attribute .are_same that checks if there exists an OptimizationResult object for optimization_run=1 and for the same project_id, where all fields are the same, except the ones in the to_exclude set.

Django choices in Admin when Enum is used

I have a model where I am using Enum for choices:
class Agreement(models.Model):
class Category(enum.Enum):
EULA = 0
PROVIDER = 1
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
category = models.IntegerField(
choices=[(choice.name, choice.value)
for choice in Category])
title = models.CharField(max_length=128)
content = models.TextField()
I register it using simple admin site registration:
admin.site.register(Agreement)
When admin site renders the object it doesn't allow me to save it? Has anyone had a similar issue?
According to the documentation:
The first element in each tuple is the actual value to be set on the model, and the second element is the human-readable name.
name and value should be the other way around, like this:
category = models.IntegerField(
choices=[(choice.value, choice.name)
for choice in Category])
because category is an integer field and name returns a string.

How to create django database model that "knows" what kind of category it is?

In Django, I have the following models.py
class Product(RandomPrimaryIdModel):
title = models.CharField(max_length=20, blank=True, null=True)
price = models.CharField(max_length=20, blank=True, null=True)
condition = models.CharField(max_length=20, blank=True, null=True)
class Mattress(Product):
length = models.CharField(max_length=50)
size = models.CharField(max_length=5)
class Pillow(Product):
shape= models.CharField(max_length=50)
comfort= models.CharField(max_length=5)
The idea is that there's a "product" model and several "product_type" models. I'm trying to create a database scheme that relates the two. The end goal is so that when I given access to a primary id for an object whose product_type is unknown, I can simply query/filter that object to find out what the product_type is of the object.
I know that sounds a bit confusing, but how would I go about implementing the correct way? The current scheme (the one above) is not the correct solution I believe.
According to the docs on multi-table inheritance you can reference the lowercase name of the model. In your case to find out the "product type" you'd do something like:
product = Product.objects.get(id=12)
try:
mattress = product.mattress
is_mattress = True
except Mattress.DoesNotExist:
is_mattress = False
You could abstract this out to a helper method that would do the tests for you and return the type as a string or enum of some sort.
If you have a reference to an object, can't you use something like:
p = Product.objects.get(id=1)
class_of_p = str(p.__class__)
and then parse the resulting string
"<class 'whatever.models.Pillow'>"
to find what you need? Apologies if I'm missing something.

Categories