Geodjango and hierarchical locations - django

In a few weeks I want to start building a "datawarehouse" based on django. The database should be filled with data which can be connected to a location. For example population which is connected to country or city, or the anual rainfall or temperature. The parameters are not yet defined and will change over time but they will in general have a quantity, timeperiod (for example anual) and unit (so in the example: population of country X in year Y).
My idea was to have a selfreferencing table in the database named locations in which there would be continents, countries, regions and cities. An example:
ID | parent_id | name
1 | null | Europe
2 | 1 | France
3 | 2 | Paris
I would than have a table which would connect data to a location like such:
ID | location_id | parameter_id | from_date | to_date | quantity
1 | 3 | 1 | 01-01-2000 | 31-01-2001 | 3000000
parameters:
ID | name | unit
1 | population | people
Technically I also want to couple locations to coordinates or polygons such that I can show them on a map.
Is something like this possible in (Geo)Django? I feel that GeoDjango couples a model class to a specific subject such as in this case population. However, I do not know my subjects yet..
Or should I design the database structure different altogether?
Lastly: I want to use a pgSQL with postgis database for this because it is opensource and seems most appropriate. However if I program the website locally I have SQLite, is there a way I can run a pgSQL with Postgis locally on my windows computer (which is rather slow) for development? Can I then easily push it using for example GitLab to a production location (for example amazone AWS)?
Tips and help on this subject is very much appreciated.

For hierarchical data with Django, use Django MPTT:
class Region(MPTTModel):
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
name = models.CharField(max_length=50, unique=True)
geom = models.MultiPolygonField(null=True, blank=True)
class Parameter(models.Model):
name = models.CharField(max_length=50, unique=True)
class RegionParameter(models.Model):
region = TreeForeignKey(Region, null=True, blank=True, related_name='children', db_index=True...)
param = models.ForeignKey(Parameter...)
from_date = models.DateField()
to_date = models.DateField()
value = models.IntegerField()
You can add the geographic data only on the leafs or to all levels in the hierarchy.

Related

How to count quantity with distinct?

I have 2 templates, one representing a product sheet and the other one an actual product in stock.
The stock can have several products that have the same product sheet.
Example:
I can have a product record "Water bottle", and several "water bottle" in the stock.
My models:
class Stock(models.Model):
machine = models.ForeignKey(
"machine.Machine",
verbose_name=_("machine"),
related_name="machine_stock",
on_delete=models.CASCADE
)
product = models.ForeignKey(
"client.Product",
verbose_name=_("product"),
related_name="product_stock",
on_delete=models.CASCADE
)
epc = models.CharField(_("EPC"), max_length=80)
dlc = models.DateField(_("DLC"))
class Product(models.Model):
name = models.CharField(_('Name'), max_length=255)
[...]
I want to retrieve the products in stock sorted by both DLC and name.
On my frontend I want to display a table with for each row:
the name of the product
the dlc
the number of products with this name and this dlc
Example:
If I have 2 product sheets (Product Model) :
water bottle
bottle of coca cola
and I have 5 products in stock (Stock Model) :
2 bottles of water whose dlc is 02/04/2022
2 bottles of cola whose dlc is the 02/04/2022
1 bottle of cola whose dlc is 03/04/2022
I want to display 3 lines in my table:
Quantity | Name | DLC
2 | water | 02/04/2022
2 | cola | 02/04/2022
1 | cola | 03/04/2022
I tried with
queryset = (
Stock.objects.all()
.select_related('product')
.select_related('machine')
.annotate(quantity=Count("product__name", distinct=True))
.distinct("dlc", "product__name",)
.order_by("-dlc")
)
But django ORM don't accept annotate and distinct in the same query.
It's works with:
queryset = (
Stock.objects.all()
.select_related('product')
.select_related('machine')
#.annotate(quantity=Count("product__name", distinct=True))
.distinct("dlc", "product__name",)
.order_by("-dlc")
)
for result in queryset:
result.quantity = Stock.objects.filter(dlc=result.dlc, product__name=result.product.name).count()
But I'm not sure that is the best method to use.

Render data in a table on a Django template from multiple tables after filtering

I am new to Django and any help on my query is appreciated. I am trying to create an inventory portal and want to display summary information in the template as a table.
models.py
class Location(models.Model):
location_name = models.CharField(max_length=5)
....< other attributes >
class Rack(models.Model):
location = models.ForeignKey(Location, on_delete=models.SET_NULL)
rack_id = models.CharField(max_length=10)
....< other attributes >
class Equipment(models.Model):
rack_id = models.ForeignKey(Rack,on_delete=models.SET_NULL)
make = models.CharField(max_length=20)
model = models.CharField(max_length=20)
type = models.CharField(max_length=20)
....< other attributes >
My query
There are several equipments installed on a rack (such as Comms equip, Processing equip, etc.,) which in turn is available on a location. I want to render summary information onto a template where the first column should be location_name, the second column the count of comms equipment in that location, and the third column count of processing equip, and so on.
| Location | Comms Equip | Processing Equip |
| -------- | ----------- | ---------------- |
| Loc1 | 5 | 8 |
| Loc2 | 2 | 10 |
I can obtain the first column by:
views.py
location = Location.objects.all()
context = {'location': location, }
return render(request, 'appname/summary.html', context)
summary.html
{% for x in location %}
{{ x.location_name }}
For second and subsequent columns, I need to filter with a particular location ID which I am unable to obtain with the context available in the views. Hence for the first column it is not with any specific location ID but for rest of the columns, it is with a specific ID (such as count of comms equip with location ID 1) which is where I am struggling. Aplogize if this question is naive but I tried to search for this but was unable to understand any response which answers my question. Thanks.

Django order by foreignkey

models.py:
class Address(models.Model):
text = models.TextField(max_length=2060, null=True, blank=True, default=None, unique=True)
class Tag(models.Model):
text = models.CharField(max_length=255, null=True, blank=True, default=None, unique=True)
class AddressTagJoin(models.Model):
address = models.ForeignKey(Address, on_delete=models.CASCADE, null=True, blank=True, related_name='address_tag_join')
tag = models.ForeignKey(Tag, on_delete=models.CASCADE, null=True, blank=True, related_name='address_tag_join')
In above, Address and Tag objects are only used as AddressTagJoin's foreignkey target.
What I want to do is two kind of queryset..
When I got address "https://www.google.com", I want to get Tag queryset ordered by most used for Address (text = "www.google.com")
Tag.objects.order_by(count_of_AddressTagJoin_and_It's_address_foreignkey_is_for_"www.google.com")
In reverse, I got tag "google", I want to get Address queryset ordered by most how many used for Tag (text="google")
Address.objects.order_by(count_of_AddressTagJoin_and_It's_tag_foreignkey_is_for_"google")
How can I do that?
from what I understood, you require:
"For the address "google.com" most used tags in order"
By taking an example I'll reach to the query.
There is this table AddressTagJoin:
address__text | tag__id
"google.com" | 1
"google.com" | 2
"google.com" | 1
"yahoo.com" | 2
"google.com" | 3
"google.com" | 3
"google.com" | 3
If we filter AddressTagJoin based on address "google.com" and then group this based on tag__id to get the tag counts(for the address most used tags), ordering it we get:
tag__id | tag_count
3 | 3
1 | 2
2 | 1
The desired result which you want is:
tags --> 3, 1, 2
Query for this will be:
from django.db.models import Count
tags_list = list(
AddressTagJoin.objects.filter(address__text__icontains="www.google.com")
.values('tag__id')
.annotate(tag_count=Count('tag__id'))
.order_by('-tag_count')
.values_list('tag__id', flag=True)
)
tags = Tag.objects.filter(id__in=tags_list)
Note
Please check the query there might be little adjustments required. This will give you an idea for the second query, both are almost same.
Also, If you want to optimize this query you can use select_related in the tag_list query. You can refer to the docs here
PS: I haven't implemented the models to check the query because of time constraints.

Return all objects relationships recursive

How i can return all relationships on recursive table on django
Structure(model):
class Category(models.Model):
name = models.CharField(max_length=100)
details = models.CharField(max_length=100)
state = models.IntegerField(default=1,choices=estado_choices,)
parent = models.ForeignKey('self', blank=True, null=True, related_name='category', db_index=False)
I would like return like this on template:
_______________________________________________
# |Category |name |description|
________________________________________________
1 | Principal |Example |example 3 |
2 | Subprincipal |subprincipal |example 3 |
3 | Subprincipal 2 |subprincipal 2| example3
i dont know how return this relationship.. please someone idea..!!
Rather that implementing a hierarchical category model of your own. Build on what others have done! There is a library called django-mptt that works very well for this. The documentation will tell you all you need to know about getting a recursive results from your categories.

django accessing raw many to many created table fields

Model:
class Subjects (models.Model):
name = models.CharField(max_length=100)
places = models.CharField(max_length=100)
class Student (models.Model):
name = models.CharField(max_length=40)
lastname = models.CharField(max_length=80)
subjects = models.ManyToManyField(Subjects, blank=True)
Django creates appname_student_subjects when I use model above.
appname_student_subjects table looks for example, like this:
id | student_id | subjects_id
-----------------------------------------
1 | 1 | 10
2 | 4 | 11
3 | 4 | 19
4 | 5 | 10
...
~1000
How can I access subjects_id field and count how many times subjects_id exists in the table above (and then do something with it). For example: If subject with id 10 exists two times the template displays 2. I know that I should use "len" with result but i don't know how to access subject_id field.
With foreign keys I'm doing it like this in a for loop:
results_all = Students.objects.filter(subject_id='10')
result = len(results_all)
and I pass result to the template and display it within a for loop but it's not a foreign key so it's not working.
You can access the through table directly.
num = (Students.subjects # M2M Manager
.through # subjects_students through table
.objects # through table manager
.filter(student_id=10) # your query against through table
.count())