Django ManyToManyField repeated values (that are the same object) - django

I'll try to sum up with a brief description of the logic. I have 2 models (I'm using django smart_selects too):
One "actuacion" can be related with a previous actuacion and in that case they will have the same number of "parcelas" related.
from smart_selects.db_fields import ChainedForeignKey
class Actuacion(models.Model):
[...]
parcelas = models.ManyToManyField('Parcela', related_name="actuaciones", blank=True)
actuacion_precedente = ChainedForeignKey(
'self', on_delete=models.CASCADE, null=True, blank=True,
chained_field="paraje", chained_model_field="paraje")
class Parcela(models.Model):
[...]
In the admin I have:
class ActuacionAdmin(admin.ModelAdmin):
[...]
filter_horizontal = ('parcelas', )
After populating my database I take this output: (the first number is the ID of the object "parcela").
What the hell is going on? Reading directly the database gives me 5 objects properly. However the front-end is duplicating the information.
I've tested and played linking the first actuacion to a second one linked to a third one and the results appears thrice. (and with 4, 5... the same).
Any idea will be tested and appreciated.
Thanks for your help. Pablo :)

Related

Lookup that spans across 3 tables in Django

I want to do a lookup that spans three model classes. I want to find all the PartListings that match the Specific_part in the ListItem. Say Specific part = Radio, there could be several Radios in the PartListings and I want to return the PartListing id of all of them so that I can get other attributes like quantity.
I have these models:
class SpecificPart(BaseModel):
class PartListing(BaseModel):
specific_part = models.ForeignKey(
SpecificPart, on_delete=models.CASCADE, blank=True, null=True,
related_name="part_listing")
class ListItem(BaseModel):
specific_part = models.ForeignKey(SpecificPart, on_delete=models.CASCADE,
related_name="listitem")
I'm trying to put the lookup under the ListItem class like this:
def item_match(self):
part = self.specific_part
return PartListings.filter(specific_part__specific_part=part)
I tried to set it up as a Lookup that spans relationshipsbut am getting an error that PartListing is not defined. I also suspect that I'm referencing the foreign keys incorrectly. I'm also ok with redefining the models if a One to One would be better.
I am a Django newbie so thanks so much for your help!
You can try like this using reverse relation between SpecificPart and PartListing models:
class ListItem(BaseModel):
...
def item_match(self):
return self.specific_part.part_listing.all()

Order Objects using an associated model and timedelta

I have a puzzle on my hands. As an exercise, I am trying to write a queryset that helps me visualize which of my professional contacts I should prioritize corresponding with.
To this end I have a couple of models:
class Person(models.Model):
name = models.CharField(max_length=256)
email = models.EmailField(blank=True, null=True)
target_contact_interval = models.IntegerField(default=45)
class ContactInstance(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name='contacts')
date = models.DateField()
notes = models.TextField(blank=True, null=True)
The column target_contact_interval on the Person model generally specifies the maximum amount of days that should pass before I reach out to this person again.
A ContactInstance reflects a single point of contact with a Person. A Person can have a reverse relationship with many ContactInstance objects.
So, the first Person in the queryset should own the greatest difference between the date of the most recent ContactInstance related to it and its own target_contact_interval
So my dream function would look something like:
Person.objects.order_by(contact__latest__date__day - timedelta(days=F(target_contact_interval))
but of course that won't work for a variety of reasons.
I'm sure someone could write up some raw PostgreSQL for this, but I am really curious to know if there is a way to accomplish it using only the Django ORM.
Here are the pieces I've found so far, but I'm having trouble putting them together.
I might be able to use a Subquery to annotate the date of the most recent datapoint:
from django.db.models import OuterRef, Subquery
latest = ContactInstance.objects.filter(person=OuterRef('pk')).order_by('-date')
Person.objects.annotate(latest_contact_date=Subquery(latest.values('date')[:1]))
And I like the idea of sorting the null values at the end:
from django.db.models import F
Person.objects.order_by(F('last_contacted').desc(nulls_last=True))
But I don't know where to go from here. I've been trying to put everything into order_by(), but I can't discern if it is possible to use F() with annotated values or with timedelta in my case.
UPDATE:
I have changed the target_contact_interval model to a DurationField as suggested. Here is the query I am attempting to use:
ci = ContactInstance.objects.filter(
person=OuterRef('pk')
).order_by('-date')
Person.objects.annotate(
latest_contact_date=Subquery(ci.values('date'[:1])
).order_by((
(datetime.today().date() - F('latest_contact_date')) -
F('target_contact_interval')
).desc(nulls_last=True))
It seems to me that this should work, however, the queryset is still not ordering correctly.

django query model A and exclude some items from related model B

I'm new to Django and I'm facing a question to which I didn't an answer to on Stackoverflow.
Basically, I have 2 models, Client and Order defined as below:
class Client(models.Model):
name = models.CharField(max_length=200)
registration_date = models.DateTimeField(default=timezone.now)
# ..
class Order(models.Model):
Client = models.ForeignKey(ModelA, on_delete=models.CASCADE, related_name='orders')
is_delivered = models.BooleanField(default=False)
order_date = models.DateTimeField(default=timezone.now)
# ..
I would like my QuerySet clients_results to fulfill the 2 following conditions:
Client objects fill some conditions (for example, their name start with "d" and they registered in 2019, but it could be more complex)
Order objects I can access by using the orders relationship defined in 'related_name' are only the ones that fills other conditions; for example, order is not delivered and was done in the last 6 weeks.
I could do this directly in the template but I feel this is not the correct way to do it.
Additionally, I read in the doc that Base Manager from Order shouldn't be used for this purpose.
Finally, I found a question relatively close to mine using Q and F, but in the end, I would get the order_id while, ideally, I would like to have the whole object.
Could you please advise me on the best way to address this need?
Thanks a lot for your help!
You probably should use a Prefetch(..) object [Django-doc] here to fetch the related non-delivered Orders for each Client, and stores these in the Clients, but then in a different attribute, since otherwise this can generate confusion.
You thus can create a queryset like:
from django.db.models import Prefetch
from django.utils.timezone import now
from datetime import timedelta
last_six_weeks = now() - timedelta(days=42)
clients_results = Client.objects.filter(
name__startswith='d'
).prefetch_related(
Prefetch(
'orders',
Order.objects.filter(is_delivered=False, order_date__gte=last_six_weeks),
to_attr='nondelivered_orders'
)
)
This will contain all Clients where the name starts with 'd', and each Client object that arises from this queryset will have an attribute nondelivered_orders that contains a list of Orders that are not delivered, and ordered in the last 42 days.

Access to child object in Django relation

Edit: I would very much like to accomplish this without installing a 3rd-party app. It seems simple/common enough that someone would have posted a line of code that accomplishes this by now?
Couldn't this be done easily in SQL? Would it be taboo to just hit the DB with a custom SQL in the index view?
So I have a parent Class and 2 child Classes. I would like to query all items and return a quick list.
from django.db import models
VIDEO_TYPE_CHOICES = (
('dvd', 'DVD'),
('downloaded', 'Downloaded'),
)
BOOK_TYPE_CHOICES = (
('e_book', 'E-Book'),
('print', 'Print'),
('audio', 'Audio Book'),
)
class Unit(models.Model):
name = models.CharField(max_length=200)
image = models.ImageField()
def __unicode__(self):
return self.name
class Video(Unit):
this_type = models.CharField(max_length=20, choices=VIDEO_TYPE_CHOICES, default='dvd')
run_time = models.CharField(max_length=200)
class Book(Unit):
this_type = models.CharField(max_length=20, choices=BOOK_TYPE_CHOICES, default='print')
pages = models.CharField(max_length=200)
All I want to do is display a list of all "Units" with this_type mushed in there on my index page.
Such as:
Lord Of The Rings, lotr.jpeg, DVD
Treasure Island, treasure_island.jpeg, Print
But I only have access to the Units name and image properties if I do a standard "gimme all Units" query...not this_type. Unless of course I make an assumption about the object and try object.book.this_type for example...which throws an exception if that particular object is not a Book.
I've been researching this for a while now...and while I can find several related questions and several possible methods (generic relations, for example?), I cannot find an example that I can relate to my own use case...or understand at all for that matter. I've only been at this stuff (Python and Django) for about a week now...I learn best when I can just make something work, get an understanding of all the moving parts, and then build on that understanding.
In that light, if someone could give me an example of how to generate the previously mentioned object list, I would be extremely grateful!
Pretty PLS???
I would recommend using the django app model_utils
OOP is generally not the best design pattern for models but if you are going to go that route model_utils has an InheritanceManager which does exactly what you want.

django prefetch_related with filter

models.py:
class Ingredient(models.Model):
_est_param = None
param = models.ManyToManyField(Establishment, blank=True, null=True, related_name='+', through='IngredientParam')
def est_param(self, establishment):
if not self._est_param:
self._est_param, created = self.ingredientparam_set\
.get_or_create(establishment=establishment)
return self._est_param
class IngredientParam(models.Model):
#ingredient params
active = models.BooleanField(default=False)
ingredient = models.ForeignKey(Ingredient)
establishment = models.ForeignKey(Establishment)
I need to fetch all Ingredient with parametrs for Establishment. First I fetch Ingredients.objects.all() and use all params like Ingredients.objects.all()[0].est_param(establishment).active. How I can use django 1.4 prefetch_related to make less sql queries? May be I can use other way to store individual Establishment properties for Ingredient?
Django 1.7 adds the Prefetch object you can put into prefetch_related. It allows you to specify a queryset which should provide the filtering. I'm having some problems with it at the moment for getting a singular (latest) entry from a list, but it seems to work very well when trying to get all the related entries.
You could also checkout django-prefetch which is part of this question which does not seem a duplicate of this question because of the vastly different wording.
The following code would fetch all the ingredients and their parameters in 2 queries:
ingredients = Ingredients.objects.all().prefetch_related('ingredientparam_set')
You could then access the parameters you're interested in without further database queries.