Is it possible in Django to iterate the creation of a model? - python

I'm trying to create a model with 100 columns. Is it possible to iterate in my models.py file to create many entries at once?
This is an example of what I'm trying to accomplish.
class AgeFactor(models.Model):
'''
Used to populate a table with all the age-factor numbers
'''
gender = models.CharField(max_length=50, null=True, blank=True)
code = models.CharField(max_length=50, null=True, blank=True)
event_code = models.CharField(max_length=50, null=True, blank=True)
oc = models.DecimalField(max_digits=9, decimal_places=4)
for lp in range(101):
if lp > 4:
(f"{lp} = models.DecimalField(max_digits=9, decimal_places=4)")
Thank you.

Yes, although this is not how to do that. What you can do is use a loop mechanism with:
class AgeFactor(models.Model):
'''
Used to populate a table with all the age-factor numbers
'''
gender = models.CharField(max_length=50, null=True, blank=True)
code = models.CharField(max_length=50, null=True, blank=True)
event_code = models.CharField(max_length=50, null=True, blank=True)
oc = models.DecimalField(max_digits=9, decimal_places=4)
for lp in range(5, 101):
locals()[f'data{lp}'] = models.DecimalField(max_digits=9, decimal_places=4)
This will make a set of fields named data5, data6, data7, … data100.
That being said, it is rather "ugly", and often you can better define a many-to-one relation with a ForeignKey [Django-doc] since that makes the data more "flat".
Furthermore if I run this locally it takes some time for Django to fully evaluate the model, so I do not know how well Django scales with a large amount of fields (the for loop itself is not the problem, but Django has a lot of bookkeeping for these fields).
Finally querying can also be slow, because the database has to load all these columns, furthermore queries will be quite large, because the SELECT part will enumerate all the data… fields.

Related

Django Model Instance as Template for Another Model that is populated by Models

I'm trying to create a workout tracking application where a user can:
Create an instance of an ExerciseTemplate model from a list of available Exercise models. I've created these as models so that the user can create custom Exercises in the future. There is also an ExerciseInstance which is to be used to track and modify the ExerciseTemplate created by the user, or someone else. I'm stripping the models of several unimportant fields for simplicity, but each contains the following:
class Exercise(models.Model):
# Basic Variables
name = models.CharField(max_length=128)
description = models.TextField(null=True, blank=True)
def __str__(self):
return self.name
class ExerciseTemplate(models.Model):
# Foreign Models
workout = models.ForeignKey(
'Workout',
on_delete=models.SET_NULL,
null=True,
blank=True
)
exercise = models.ForeignKey(
Exercise,
on_delete=models.SET_NULL,
null=True,
blank=True
)
recommended_sets = models.PositiveIntegerField(null=True, blank=True)
class ExerciseInstance(models.Model):
""" Foreign Models """
exercise_template = models.ForeignKey(
ExerciseTemplate,
on_delete=models.SET_NULL,
null=True,
blank=True
)
workout = models.ForeignKey(
'Workout',
on_delete=models.SET_NULL,
null=True,
blank=True
)
""" Fields """
weight = models.PositiveIntegerField(null=True, blank=True)
reps = models.PositiveIntegerField(null=True, blank=True)
Create a WorkoutInstance from a WorkoutTemplate. The WorkoutTemplate is made up of ExerciseTemplates. But the WorkoutInstance should be able to take the WorkoutTemplate and populate it with ExerciseInstances based on the ExerciseTemplates in the WorkoutTemplate. Here are the models that I have so far:
class WorkoutTemplate(models.Model):
name = models.CharField(max_length=128)
description = models.TextField(null=True, blank=True)
date = models.DateTimeField(null=True, blank=True)
#category...
exercises = models.ManyToManyField(
Exercise,
through=ExerciseTemplate
)
def __str__(self):
return self.name
class WorkoutInstance(models.Model):
# Foreign Models
workout_template = models.ForeignKey(
'WorkoutTemplate',
on_delete=models.SET_NULL,
null=True,
blank=True
)
But this is where I get stuck. I'm not sure how to proceed. My intuition is one of the following:
I need to create a more simple architecture to do this. I'll take any suggestions.
I need to create a method within the model that solves this issue. If this is the case, I'm not sure what this would actually look like.
When you create a new WorkoutInstance object which references a given WorkoutTemplate object you get all its related ExerciseTemplate objects.
Then you just create a new object (row) for each ExerciseInstance in another model (table)
If you link your ExerciseInstance to WorkoutInstance via 'workout' you could do something like:
wt = WorkoutTemplate.get(id=1)
wi = WorkoutInstance.create(workout_template=wt)
for e in wt.exercisetemplate_set.all:
ExerciseInstance.create(exercise_template=e, workout=wi)
You can implent this in the method that creates the new WorkoutInstance or take a look at signals
https://docs.djangoproject.com/en/4.0/topics/db/optimization/#create-in-bulk

Update id's for many to many mapping django

I have two models with many to many mapping:
class Child_details(models.Model):
name = models.CharField(max_length=200, default="")
gender = models.CharField(max_length=2, choices=GENDER_CHOICES)
dob = models.DateField(null=True, blank=True)
images_history = models.ManyToManyField(Image_history, blank=True)
class Image_history(models.Model):
image_type = models.CharField(max_length=100, blank=True, null=True, choices=PAGE_TYPES)
image_link = models.CharField(max_length=100, blank=True, null=True)
Now that, I have two different objects for Child_details: child_obj1 and child_obj2. Since child_obj2 is a duplicate of child_obj1, I wanted to delete that object and before doing that I have to refer all image_history of child_obj2 to child_obj1.
I tried doing:
for image in child_obj2.image_history.all():
image.child_details_id=child_obj1.id
#but, I can't do the above one because there is no child_details_id in image_history model
Django creates a third table with child_details_id, image_history_id.
I wanted to change child_details_id in the third table created by django for many to many mapping.
Is it correct doing that and If so how can I?
I got it. Basically what I've done is I iterated through child_obj2's images_history and made entries in child_obj1's image_history.
for child_image_history in child_obj2.images_history.all():
image_history = Image_history(image_type=child_image_history.image_type, image_name=child_image_history.image_name)
image_history.save()
child_obj1.images_history.add(image_history)
child_image_history.delete()
And deleted the previous entries of child_obj2 which is not required.

Calculating fields with filters in Django

I am extremely new to Django and kinda new to python and programming in general, so i may be asking a dumb question. I am trying to track medications in our inventory at work. Here is my model for the inventory in our safe
class Safe(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT)
date_created = models.DateTimeField(auto_now=True)
drug_name = models.ForeignKey('components.Drug', related_name='drug_remove', on_delete=models.PROTECT, default=0)
amount_removed = models.IntegerField(blank=True, null=True)
amount_added = models.IntegerField(blank=True, null=True)
incident_number = models.CharField(max_length=20, default=0, blank=True)
patient_name = models.CharField(max_length=20, default=0, blank=True)
medic_unit = models.ForeignKey('components.MedicUnit', related_name='medic_unit', on_delete=models.PROTECT, blank=True)
free_text = models.CharField(max_length=1000, default=0, blank =True)
drug_total = computed_property.ComputedIntegerField(compute_from='add_drug')
I would like to store the medication total for each drug in the database. I understand from researching this that storing totals isn't best practice in most cases but I believe this is one exception. Obviously the calculated integer field isn't the answer, but none of my research has gotten me any closer to the answer. My guess is that I first need to filter by 'drug_name' and then calculate the added or subtracted drugs from the previous total in a function within my model. Thanks ahead of time for any help.
I might be getting wrongly what you need. But it seems to me that you just need to compute the drug_total + drug_added - drug_removed is that correct?
Add this to the bottom of your model:
def get_current_amount_of_drug(self):
return self.drug_total - self.drug_removed + self.drug_added
Then from any view or other place where you need it - you can just call
safe = Safe.objects.filter(drug_name="My Drug").first() # or however you filter them and then just get
safe.get_current_amount_of_drug()
Maybe the documentation would help you more:
https://docs.djangoproject.com/en/2.2/topics/db/models/#model-methods

Select related on 3 tables in Django ORM

I need some help to perform a select_related in Django framework.
My model is:
models.py
class Richiesta(models.Model):
# TIPOLOGIE_DISPOSITIVO can be = BK or SC
codice = models.CharField(max_length=20, null=True, blank=True, unique=True)
ufficio_registrazione = models.ForeignKey(UfficioRegistrazione, null=True, blank=False)
tipologia = models.CharField(max_length=50, null=False, blank=False, choices=TIPOLOGIE_DISPOSITIVO, default=TIPOLOGIE_DISPOSITIVO[0][0])
tipo = models.IntegerField(null=False, blank=False, choices=TIPO_CHOICES, default=TIPO_PRIMO_RILASCIO)
data_produzione = models.DateTimeField(null=True, blank=True)
class UfficioRegistrazione(models.Model):
cliente = models.ForeignKey(Cliente, null=False, blank=False)
class Cliente(models.Model):
# provider can be = 1 or 2
denominazione = models.CharField(max_length=100, null=False, blank=False)
codice_cliente = models.PositiveIntegerField(null=False, blank=False, db_index=True)
provider = models.IntegerField(null=False, blank=False, choices=PROVIDER_CHOICES)
and there is the raw sql query I need to perform with Django ORM:
select cms_richiesta.id, cms_richiesta.tipologia, cms_richiesta.data_produzione,
cms_richiesta.ufficio_registrazione_id, cms_ufficioregistrazione.id,
cms_ufficioregistrazione.cliente_id, cms_cliente.id, cms_cliente.provider,
cms_cliente.denominazione, cms_cliente.codice_cliente
from cms_richiesta INNER JOIN cms_ufficioregistrazione on
cms_richiesta.ufficio_registrazione_id=cms_ufficioregistrazione.id
INNER JOIN cms_cliente on cms_ufficioregistrazione.cliente_id =
cms_cliente.id where data_produzione>'2011-01-01' and data_produzione<'2017-
12-31' and cms_cliente.provider = 2 and cms_richiesta.tipologia='BK'
can someone help me?
Richiesta.objects.filter(ufficio_registrazione__cliente__provider=2,tipologia='BK')
and rest filter can be added like that
You can process this as:
from datetime import datetime
Richiesta.objects.select_related(
'ufficio_registrazione',
'ufficio_registrazione__cliente',
).filter(
data_produzione__range=(datetime(2011, 1, 1), datetime(2017, 12, 30)),
ufficio_registrazione__cliente__provider=2,
tipologia='BK',
)
Typically the .select_related(..) is here not necessary, since we perform these JOINs already at the filtering part, but typically it is better to be explicit than implicit (especially in case you would later omit a condition, and still want these related models to be fetched).
It will retrieve Richiesta objects, but with related models already loaded.
You probably meant <= '2017-12-31' in which case the upper bound of the date range needs to be incremented as well.
I dont want paste and copy other answer, but you can use .values() to extract only the columns that you want to work, if you think this is really necessary, because in template you will show only the data that you want
richiesta.values('tipologia', 'data_produzione'...) # when richiesta is the queryset

comparing model A's fields values in model B's field django

I have 100k records in both model 'A' and in model 'B'
Ex:
class A(models.Model):
user_email = models.EmailField(null=True, blank=True)
user_mobile = models.CharField(max_length=30, null=True, blank=True)
book_id = models.CharField(max_length=255, null=True, blank=True)
payment_gateway_response = JSONField(blank=True, null=True)
class B(models.Model):
order = models.ForeignKey(A, null=True, blank=True)
pay_id = models.CharField(max_length=250, null=True, blank=True)
user_email = models.EmailField(null=True, blank=True)
user_mobile = models.CharField(max_length=30, null=True, blank=True)
created = models.DateTimeField(blank=True, null=True)
total_payment = models.DecimalField(decimal_places=3, max_digits=20, blank=True, null=True)
I want to get B's objects using A's values
for example
all_a = A.objects.all()
for a in all_a:
b = B.objects.filter(user_email=a.user_email, user_mobile=a.user_mobile)
This is fine, I am getting the results. But as it's 100k records it's taking too much time. for loop iteration is taking time. Is there any faster way to do this in django?
You can get a list of each value in a and filter b with those values.
a = A.objects.all()
emails = list(a.values_list('user_email', flat=True))
mobiles = list(a.values_list('user_mobile', flat=True))
b = B.objects.filter(user_email__in=emails, user_mobile__in=mobiles)
How ever results may have pair of email and mobile that are not pair in A. But if you make sure that emails and mobiles will be unique in A and the email and mobile in each B are based in one of the A' models, then you won't have any problems.
If you're not interested in caching the A model, you may have a performance increase using iterator() (see for reference https://docs.djangoproject.com/en/1.11/ref/models/querysets/#iterator):
for a in A.objects.all().iterator():
b = B.objects.filter(user_email=a.user_email, user_mobile=a.user_mobile)
You can do
import operator
from django.db.models import Q
q = A.objects.all().values('user_email', 'user_mobile')
B.objects.filter(reduce(operator.or_, [Q(**i) for i in q]))
If you want to do with some operations with every b object depends on a.This is not the way.

Categories

Resources