I am working on an basic application and I`m stuck at a displaying some info.
Please take a look:
Models:
class Companies(models.Model):
name = models.CharField()
address = models.CharField()
def __unicode__(self):
return self.name
class Payments(models.Model):
company = models.ForeignKey(Companies)
year = models.CharField(choices=YEAR)
month = models.CharField(choices=MONTHS)
date = models.DateField(auto_now_add=True)
I want a view in which to display ONLY the companies that did not pay the monthly fee.
So I`ve started like this:
def checks(request):
i = datetime.datetime.now()
an_c = i.strftime('%Y')
comp = Companies.objects.all()
pay1 = Payments.objects.filter(an=an_c, month='01')
But in the template I do not know how to filter the "comp" list.
I want to display in the template all the records from "comp" except that ones with the id/pk which can be find in the "pay1.company"
You wouldn't do that in the template. Do the whole thing in the view:
pay1 = Payments.objects.filter(an=an_c, month='01')
comp = Companies.objects.exclude(payments__in=pay1)
(Style note: Django model classes are usually named in the singular, not the plural.)
Related
I'm trying to compare all the things in ModelOne with ModelTwo, to check which things are or are not in one or the other model, then put this in the view context for display in the template.
class Things(model.Model):
name = models.CharField()
class ModelOne(models.Model):
things = models.ManyToManyField(Things)
class ModelTwo(models.Model):
things = models.ManyToManyField(Things)
How would you do this?
one_instance = ModelOne.objects.get(id=one_id)
two_instance = ModelTwo.objects.get(id=two_id)
one_thing_ids = set(one_instance.things.values_list("id", flat=True))
two_thing_ids = set(two_instance.things.values_list("id", flat=True))
shared_thing_ids = one_thing_ids & two_thing_ids
thing_ids_in_one_not_in_two = one_thing_ids - two_thing_ids
thing_ids_in_two_not_in_one = two_thing_ids - one_thing_ids
shared_things = Thing.objects.filter(id__in=shared_thing_ids)
You can then pass shared_things queryset into the template for display.
If your Thing model only has a name field and the names are unique we can simplify a little by altering the model:
class Things(model.Model):
name = models.CharField(unique=True)
or even:
class Things(model.Model):
name = models.CharField(primary_key=True, unique=True)
(in this case the db table will not have an id column, it's not needed)
Either way we can then eliminate the extra Thing query at the end:
one_instance = ModelOne.objects.get(id=one_id)
two_instance = ModelTwo.objects.get(id=two_id)
one_thing_names = set(one_instance.things.values_list("name", flat=True))
two_thing_names = set(two_instance.things.values_list("name", flat=True))
shared_thing_names = one_thing_names & two_thing_names
thing_names_in_one_not_in_two = one_thing_names - two_thing_names
thing_names_in_two_not_in_one = two_thing_names - one_thing_names
...and just pass sets of string names into the template.
it's a stupid question but i'm new to django and I didn't find a answer so far.
I'm trying to get a list of all related Years in the get_savings function.
Don't look at the attributes of Year and Plan. They all exist.
The focus is on the For loop. I also tried for year in self.year_set.all: but it didn't work either.
models.py
class Plan(models.Model):
title = models.CharField(max_length=50)
...
#property
def get_saving(self):
delta: timedelta = now() - self.date_created
months_gone = delta.days / 30
saving = 0
for year in Year.objects.all():
if months_gone > year.months:
saving = saving + year.savings_year
else:
saving = saving + months_gone * year.income_month
return saving
class Year(models.Model):
title = models.IntegerField()
plan = models.ForeignKey(Plan, on_delete=models.CASCADE)
self.year_set.all() is what you need.
all is a function so you need to call it rather than just reference it.
I have a class in my models.py
class Inventory(models.Model):
date = models.DateField(("Date"), default=datetime.now)
product = models.ForeignKey(Product)
stock_in = models.IntegerField()
stock_out = models.IntegerField()
balance = models.IntegerField()
particulars = models.CharField(max_length=250)
Now I want to add some stocks in the balance. Using the stock_in values to add certain numbers to the balance of a specific product in the Inventory class. Using an UpdateView to it, so that I can just Update the stock_in field then adding that value to the balance.
I'm currently using this, I've tried couple of solution in the internet but to no avail.
#property
def total(self):
return self.stock_in + self.balance
There is no 'official' mechanism in Django to do this. Recently, some ideas of adding some official solution to the Django framework were discussed in this thread on the django-developers mailing list. It might serve as an inspiration for what solution is currently best for your case.
Your method works well for simple calculations. If the property gets more expensive to calculate, using #cached_property can help a bit if the value is used multiple times.
You can also rely on the database to compute these values by adding an annotation to the queryset. This requires defining a custom Manager:
class InventoryManager(models.Manager):
def get_queryset(self):
super().get_queryset().annotate(total=F('stock_in') + F('balance'))
class Inventory(models.Model):
date = models.DateField(("Date"), default=datetime.now)
product = models.ForeignKey(Product)
stock_in = models.IntegerField()
stock_out = models.IntegerField()
balance = models.IntegerField()
particulars = models.CharField(max_length=250)
objects = InventoryManager()
This will add a balance attribute to your Inventory model instances if they are retreived using the default manager.
The problem with this approach (like discussed in the linked django-developers thread) is what your expectations are when modals are changed locally.
For example, with the custom manager in place, if I were to change stock_in for a modal, the value of total would still be valid for the value of stock_in at the time of retrieving it from the database:
>> qs = Inventory.objects.filter(date__gte=date(2017, 12, 22))
>> inventory0 = qs[0]
>> print(inventory0.total, inventory0.stock_in, inventory.balance)
100, 50, 50
>> inventory.balance = 100
>> print(inventory0.total, inventory0.stock_in, inventory.balance)
100, 50, 100
Also, an model instance not fetched from the db at all wont have a total attribute:
>> inventory = Inventory(stock_in=20, balance=10)
>> inventory.total
AttributeError: 'Inventory' object has no attribute 'total'
Adding a __getattr__ method to your class might be a solution to this usecase, but will still result in incorrect answers with local changes.
class Daily(models.Model):
rpt_date = models.DateField('Report Date', primary_key=True)
total_d_sors = models.IntegerField()
loaded_d_sors = models.IntegerField()
#diff_d_count
d_sors_missed_eod = models.CharField(max_length=300)
total_m_sors = models.IntegerField() #monthly
loaded_m_sors = models.IntegerField() #monthly
m_sors_missed_eod = models.CharField(max_length=300)
I have the above class in my models.py but when I display it through a view I need to have an additional column which will have the difference between two existing columns (total_d_sors and missed_d_sors) i.e., diff_d_count=(total_d_sors - missed_d_sors)... can someone help?
I'm seeing examples with cursor implementation; is there any other way?
Why don't you add a property on the model and calculate it on the fly as you're displaying it in your template?
class Daily(models.Model):
#property
def diff_d_count(self):
return self.total_d_sors - self.missed_d_sors
Then you can access it in your template or wherever via obj.diff_d_count.
To find difference between 2 columns you can use,
1. annotate
2. F expression
Your query would be,
Daily.objects.annotate(diff=F('total_d_sors')-F('missed_d_sors'))
Sample working code with template,
from django.db.models import F
from django.template import Context, Template
context = Context({"daily_objects": Daily.objects.annotate(diff=F('total_d_sors')-F('missed_d_sors'))})
template = Template("{% for i in daily_objects %} {{i.id}} || {{i.diff}}. {% endfor %}")
template.render(context)
I'm messing around with my first Django site and so far it's going good. I am now facing the challenge of getting some information from the DB. My model looks like this:
class Countries(models.Model):
country = models.CharField(max_length=100)
def __unicode__(self):
return self.country
class OrganisationTypes(models.Model):
organisation_type = models.CharField(max_length=100)
def __unicode__(self):
return self.organisation_type
class Organisations(models.Model):
organisation_name = models.CharField(max_length=200)
organisation_type = models.ForeignKey(OrganisationTypes)
country_of_origin = models.ForeignKey(Countries)
def __unicode__(self):
return self.organisation_name
class Locations(models.Model):
organisation = models.ForeignKey(Organisations)
country_of_location = models.ForeignKey(Countries)
tel_nr = models.CharField(max_length=15)
address = models.CharField(max_length=100)
def __unicode__(self):
return '%s - %s - %s - %s' % (self.organisation, self.country_of_location, self.tel_nr, self.address)
I now want to display a list of locations of which I want to display the organisation_name and the country_of_origin. To achieve this I wrote the following function:
def organisation_locations(requests, organisation_id):
org = Organisations.objects.get(id=organisation_id)
location_list = Locations.objects.filter(organisation=organisation_id).order_by('country_of_location')
output = '<br />'.join([str(loc.organisation)+' from '+str(org.country_of_origin) for loc in location_list])
return HttpResponse(output)
This works correctly, but it doesn't seem like the correct way of doing this. Since the Location table has a foreign key in the Organisations table which in turn has a foreign key in the Countries table I have this vague feeling that Django can do this in one "query" or lookup.
Am I correct in this feeling, or is my way indeed the correct way of doing this? All tips are welcome!
Can't you do:
location_list = Locations.objects\
.filter(organisation=organisation_id)\
.order_by('country_of_location')
output = '<br />'.join([str(loc.organisation)+' from '+str(loc.organisation.country_of_origin) for loc in location_list])
The organisation query isn't necessary. You can access organisation like this: localization.organisation.
What is not Djangonic in your code is the response. You should have a template and do return render_to_response :)