I have this code:
class Zapas(models.Model):
tym_domaci = models.ForeignKey(Tym, on_delete=models.CASCADE)
tym_hoste = models.ForeignKey(Tym, on_delete=models.CASCADE)
datum = models.DateTimeField('datum zapasu')
goly_domaci = models.PositiveIntegerField(default=0)
goly_hoste = models.PositiveIntegerField(default=0)
for x in range (goly_domaci):
strelec = models.ForeignKey(Hrac, on_delete=models.CASCADE, limit_choices_to={Hrac.tym == tym_domaci})
nahraval = models.ForeignKey(Hrac, on_delete=models.SET_NULL, blank=True, null=True, limit_choices_to={Hrac.tym == tym_domaci})
for x in range (goly_hoste):
strelec = models.ForeignKey(Hrac, on_delete=models.CASCADE, limit_choices_to={Hrac.tym == tym_hoste})
nahraval = models.ForeignKey(Hrac, on_delete=models.SET_NULL, blank=True, null=True, limit_choices_to={Hrac.tym == tym_hoste})
What i am trying to do, is to load all the players that scored a goal and players that assisted on it (if there is any) for each team. Problem is, that i cannot use goly_domaci and goly_hoste in the for loop because they are PositiveIntegerField and not an Integer. Is there any way to convert the PositiveIntegerField into Integer? Or can I even use the for loop like this? I am new to python and Django so I really dont know how to solve it. Thanks for help :-)
No that is not the reason. This code doesn't make sense; you can't define fields dynamically like that. Fields depend on columns in the database, a model must have a fixed number of fields. And goly_domaci is itself a field, it doesn't have a value at this point; it only has a value when accessed from an actual instance, at which point it's far too late to be defining other fields.
But this isn't what you want to do anyway. There is no point defining all those separate foreign keys to the same target model. What you want to do is define a separate model for Goals, which points to this model (I assume Zapas means Game).
class Goal(models.Model):
game = models.ForeignKey(Zapas)
team = models.ForeignKey(Tym, on_delete=models.CASCADE)
strelec = models.ForeignKey(Hrac, on_delete=models.CASCADE)
nahraval = models.ForeignKey(Hrac, on_delete=models.SET_NULL, blank=True, null=True)
Then you can drop your goly_domaci and goly_hoste fields altogether, as you can calculate them when you need to display them:
goly_hoste = my_zpas.goal_set.filter(team=my_zpas.tym_hoste).count()
goly_domaci = my_zpas.goal_set.filter(team=my_zpas.tym_domaci).count()
Related
I have a model which acts a as schedule where there are multiple FK relationships to the same user table. All of these fields can be blank/null.
The issue is, when i do a for loop, i am trying to match the users based on when they appear on a certain shift, then add a +1 to a counter to get the total shifts for that user.
The model looks like this:
class WeekdayAssignment(models.Model):
"""Model definition for WeekdayAssignment."""
start_date = models.DateField(auto_now=False, auto_now_add=False)
end_date = models.DateField(auto_now=False, auto_now_add=False)
triage_emea_1 = models.ForeignKey(TeamMember, on_delete=models.DO_NOTHING, related_name="triage_emea_1", blank=True, null=True)
triage_nam_1 = models.ForeignKey(TeamMember, on_delete=models.DO_NOTHING, related_name="triage_nam_1", blank=True, null=True)
triage_nam_2 = models.ForeignKey(TeamMember, on_delete=models.DO_NOTHING, related_name="triage_nam_2", blank=True, null=True)
triage_nam_3 = models.ForeignKey(TeamMember, on_delete=models.DO_NOTHING, related_name="triage_nam_3", blank=True, null=True)
...
As you can see i have 4 triage shifts and the same user can work any of those shifts.
I want to do a for loop to count how many times a user is on a shift in any one of those fields.
Without getting into all the details of what I am doing, i will keep it simple as the error happens right away.
Views.py
def someview(request):
shift_users = TeamMember.objects.all()
weekday_shifts = WeekdayAssignment.objects.all()
for t in shift_users:
for ws in weekday_shifts:
print(ws.triage_nam_3)
As long as there is a value in the field, this will print fine but if the field is empty (i.e. no users selected for that field) it fails with TeamMember matching query does not exist.
I have tried to do check if None but it gives the same problem. Now this error goes away once I populate a user but how can i check if it's empty and just skip it?
Thanks in advance.
You can catch models.DoesNotExist exception.
def someview(request):
shift_users = TeamMember.objects.all()
weekday_shifts = WeekdayAssignment.objects.all()
for t in shift_users:
for ws in weekday_shifts:
try:
print(ws.triage_nam_3)
except TeamMember.DoesNotExist:
continue
I am fairly new to Django, but I am working on an application that will follow a CPQ flow or Configure, Price, Quote. The user should select the product they would like to configure as well as the options to go with it. Once selected, the program should query an external pricing database to calculate price. From there the program should output the pricing & text data onto a PDF quote. I was able to get the application working using the specific product inheriting from a base product class. The issue is now that I've created a second product child class, I cannot use a singular "related_name". I've omitted the lists associated with the drop down fields to help with readability, but I've posted my models.py file below.
Is there a way I can iterate through Product objects that are pointing to a Quote object with a foreign key? A lot of answers I've found on SO relating to this were able to be solved either by specifying the "_set" or "related_name". I've seen other answers use the select_related() method, however, I can't seem to get the query right as the program won't know which set it needs to look at. A quote could have any mix of product instances tied to it, so am unsure how to handle that query. Again, I have been using django under 6 months, so I am a bit green. I am not sure if I am just not fundamentally understanding the big picture here. I thought about instead of using inheritance, to make Product a standalone class and to save the Compact or WRC info to it so I could just use one "related_name", but also thought that would just create another nested layer that would still fail.
Any help would be very appreciated! I've definitely hit the wall.
models.py
class Quote(models.Model):
project_name = models.CharField(max_length=256,blank=True)
customer_first_name = models.CharField(max_length=256,blank=True)
customer_last_name = models.CharField(max_length=256,blank=True)
company_name = models.CharField(max_length=256, blank=True)
address1 = models.CharField(max_length=256, blank=True, help_text ="Address")
address2 = models.CharField(max_length=256, blank=True)
city = models.CharField(max_length=256, blank=True, default="")
state = models.CharField(max_length=256, blank=True, default="")
zip_code = models.CharField(max_length=256, blank=True, default="")
country = models.CharField(max_length=256, blank=True, default="")
phone = PhoneField(blank=True)
email = models.EmailField(max_length=254,blank=True)
grand_total = models.FloatField(default=0)
create_date = models.DateTimeField(default = timezone.now)
class Product(models.Model):
class Meta:
abstract = True
price = models.FloatField(default=0)
total_price = models.FloatField(default=0)
quantity = models.IntegerField()
quote = models.ForeignKey('quote.Quote', on_delete=models.CASCADE)
quantity = models.IntegerField()
class Compact(Product):
base_size = models.CharField(choices=size, max_length = 256)
filter = models.CharField(choices=filter_list, max_length = 256)
product_name = models.CharField(max_length=256,default="Compact")
class WRC(Product):
base_size = models.CharField(choices=size, max_length = 256)
construction = models.CharField(choices=construction_list, max_length = 256)
outlet = models.CharField(choices=outlet_list, max_length = 256)
product_name = models.CharField(max_length=256,default="WRC")
I was able to figure out my issue, but wanted to answer in case someone came across a similar problem as myself. I was able to get get all product objects attached to a quote instance dynamically by modifying the get_context_data() method of my QuoteDetailView. I also needed to use the django library NestedObjects from django.contrib.admin.utils to grab all related objects to the quote instance. I also added a timestamp field to the Product class to be able to sort them. QuoteDetailView copied below.
class QuoteDetailView(FormMixin,DetailView):
model = Quote
form_class = ProductSelectForm
def get_context_data(self, **kwargs):
### collects related objects from quote
collector = NestedObjects(using=DEFAULT_DB_ALIAS)
collector.collect([kwargs['object']])
### slice off first element which is the quote itself
related_objects = collector.nested()
related_objects = related_objects[1:]
### get context data for qoute object
context = super().get_context_data(**kwargs)
context['now'] = timezone.now()
### if number of list items is above 0, then add them to the context
### and sort by timestamp
if len(related_objects) != 0:
context['items'] = sorted(related_objects[0], key=lambda x: x.timestamp)
return context
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
I think this is a python question (maybe for x in list), but might have a django framework ¿query/or-the-like?
I have an intermediary class/model:
class VehicleFeatures(models.Model):
personal_equipment = models.OneToOneField(PersonalEquipment, null=True, blank=True, )
commercial_equipment = models.OneToOneField(CommercialEquipment, null=True, blank=True, )
personal_vehicle = models.OneToOneField(PersonalVehicle, null=True, blank=True, )
commercial_truck = models.OneToOneField(CommercialTruck, null=True, blank=True, )
commercial_tractor = models.OneToOneField(CommercialTractor, null=True, blank=True, )
…
def __unicode__(self):
# assume one and only one is allowed
return '{}'.format(self.whichever_of_the_fields_exists)
# Extra Credit :)
# assume any number is allowed
How do I return the Model.field that has a reference (ultimately to get that model's name, to pass back to the other side of this many-to-many)?
Notes:
trying to follow option 2 and 3 in this article
I am not worried about performance (yet) but if you are aware of a low cost option, then please teach us why one is better than another
Visual of models
121-Referent: Vehicle (abstract model) with concrete models [listed above]
M2M: VehicleFeatures (to connect to concrete models)
12M: Features (fields for many vehicle features)
One approach that is sometimes used in similar "entity-attribute-value" models is to add an additional field which OneToOneField is populated. Something like this:
class VehicleFeatures(models.Model):
personal_equipment = models.OneToOneField(PersonalEquipment, null=True, blank=True, )
commercial_equipment = models.OneToOneField(CommercialEquipment, null=True, blank=True, )
personal_vehicle = models.OneToOneField(PersonalVehicle, null=True, blank=True, )
commercial_truck = models.OneToOneField(CommercialTruck, null=True, blank=True, )
commercial_tractor = models.OneToOneField(CommercialTractor, null=True, blank=True, )
# Add a field to store the type of relation that is set for this instance
relation_type = models.CharField(max_length=50)
When the object is saved, you do the for x in list thing and determine which field is not null, and set relation_type to the name of that field, e.g.:
def save(self):
for k in ['personal_equipment', 'commercial_equipment', 'personal_vehicle' ...]:
if getattr(self, k) is not None:
self.relation_type = k
return super(VehicleFeatures, self).save()
This is significantly more efficient than doing the same loop every time you query the object.
Then your __unicode__ method would be:
def __unicode__(self):
return '{}'.format(getattr(self, self.relation_type))
This is for the case when only one field is ever set, but you could extend it quite easily to support multiple fields - e.g., by making relation_type a comma-separated string, or if your database supports it, an ArrayField.
I have two fields in my model.py one has multi choice drop down and one that is empty. What I would like to have is that if the user select "Gas" from the menu for type, I would like the amount field to get auto populated with distance * 2
Can I do that?
CHOICE = (
('Meal', 'Meal'),
('Gas', 'Gas'),
)
type = models.CharField(max_length=10, choices=CHOICE)
distance = models.CharField(max_length=100)
amount = models.CharField(max_length=100)
Thanks in advance.
You can use the django-observer app for this. Although there are cleaner Javascript approaches, you can make the automation totally depend on Django.
First, modify the amount field as:
amount = models.CharField(max_length=100, blank=True, null=True)
since it won't take any values when the model object is initially saved to the database. Then the rest of the code will look something like:
from observer.decorators import watch
def compute_amount(sender, obj, attr):
if obj.type == 'Gas':
obj.amount = obj.distance * 2
obj.save()
#watch('type', compute_amount, call_on_created=True)
class FuelConsumption(models.Model):
CHOICE = (
('Meal', 'Meal'),
('Gas', 'Gas'),
)
type = models.CharField(max_length=10, choices=CHOICE)
distance = models.CharField(max_length=100)
amount = models.CharField(max_length=100, blank=True, null=True)