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)
Related
This question is in relation to project 2 of the cs50 course which can be found here
I have looked at the following documentation:
Django queryset API ref
Django making queries
Plus, I have also taken a look at the aggregate and annotate things.
I've created the table in the template file, which is pretty straight forward I think. The missing column is what I'm trying to fill. Image below
These are the models that I have created
class User(AbstractUser):
pass
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Listing(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
description = models.TextField()
initial_bid = models.IntegerField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date_created = models.DateField(auto_now=True)
def __str__(self):
return self.title
class Bid(models.Model):
whoDidBid = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
list_item = models.ForeignKey(Listing, default=0, on_delete=models.CASCADE)
bid = models.IntegerField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now=True)
def __str__(self):
return_string = '{0.whoDidBid} {0.list_item} {0.bid}'
return return_string.format(self)
This is the closest I could come to after a very long time. But the result I get is just the number 2. Ref image below
Listing.objects.filter(title='Cabinet').aggregate(Max('bid'))
Where 'Cabinet' is a Listing object that I have created. And placed two bids on them.
So the question is, how do I get the Maximum bid value(i.e. 110 for this case) for a particular listing? Using the orm. I think if I used a raw sql query, I could build a dict, send it to the template with the queryset. Then while looping through the queryset, get the value for the key, where the key is the name of the listing or something along those lines. Nah, I would like to know how to do this through the ORM please.
Here's answer #1
Bid.objects.filter(list_item__title='Cabinet').prefetch_related('list_item').aggregate(Max('bid'))
What happens when you try this (sorry, I don't have any objects like this to test on):
Bid.objects.values(list_item__title).prefetch_related('list_item').annotate(Max('bid'))
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 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()
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 models:
class City(models.Model):
name = models.CharField(max_length=50, verbose_name='Qyteti')
slug = models.SlugField(unique=True)
class Business(models.Model):
name = models.CharField(max_length=120, verbose_name='emri')
slug = models.SlugField(unique=True)
city = models.OneToOneField(City, verbose_name='qyteti')
created = models.DateTimeField(auto_now_add=True, verbose_name='krijuar')
categories = models.ForeignKey(Category, related_name='businesses', verbose_name='kategoria')
user = models.ForeignKey(User, related_name='user_businesses', verbose_name='autori')
geom = gis_models.PointField(u"longitude/latitude", geography=True, blank=True, null=True)
I want to create a serach like yelp.com
I want people to search in three different ways.
One type of business in all cities.
All type of businesses in one city.
One type of business in one city.
I've tried chain from itertools, but no results so far.
I'd like to do just a simple search for now, not with external search engines.
Anyone's help is appreciated.
You need to do the following:
1) Change in your model:
class Business(models.Model):
city = models.ForeignKey(City, verbose_name='qyteti', related_name='businesses')
2) Queries:
1) one_type = Business.objects.filter(name = "some_business_type").select_related('city')
one_type.city.name
2) one_city_all_business = City.objects.filter(name = "London").prefetch_related('businesses')
one_city_all_business.businesses.all() - here u get a list of all businesses for London
3) one_type_one_city = City.objects.filter(name = "London").filter(businesses__name = "some_business_type").prefetch_related('businesses')
The only problem here - you need to decide how user will select what query to run, I mean how will you define what user wants to search for.