django relationship how to map an indirect relation in model - django

I have three models
class Venue(models.Model):
property_values = models.ManyToManyField('feature.PropertyValue')
class Feature(models.Model):
name = models.CharField(max_length=255, null=False, blank=False)
class PropertyValue(models.Model):
name = models.CharField(max_length=255, null=False, blank=False)
feature = models.ForeignKey('Feature', null=False, blank=False)
In this I want to be able to configure 'feature' in venue model saying that belongs to it via property value.
Like
class Venue(models.Model):
property_values = models.ManyToManyField('feature.PropertyValue')
feature = models.ManyToManyField(via property_value something)

You already have access to feature through property_values
one = Venue.objects.first()
one.property_vaues.all()[0].feature

You can use add methods of Django objects:
https://docs.djangoproject.com/en/1.11/topics/db/examples/many_to_many/
venue = Venue.objects.get(id=1) # example
feature = Feature.objects.get(id=1) # example
venue.property_values.add(feature)
You can remove using remove function also

Related

how to filter objects by a specific choice

I have model like this:
class ScientificInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_approved = models.CharField(max_length=64, choices=(('0', 'yes'), ('1', 'no')), blank=True)
is_interviewed = models.BooleanField(default=False)
how can I filter this model by is_approved field which is a choicefield? I wrote this line but doesnt work
approved = ScientificInfo.objects.filter(is_approved__in='0').all()
Using the exact field lookup would probably make more sense here:
approved = ScientificInfo.objects.filter(is_approved__exact='0').all()
https://docs.djangoproject.com/en/4.0/ref/models/querysets/#exact
Put values inside () as
approved = ScientificInfo.objects.filter(is_approved__in=('0')).all()

Is there a shorter / simpler query than this one?

I have this very simple models: a Clip can have many AdBase and an AdBase can have many Clip's.
class AdBase(models.Model):
title = models.CharField(max_length=200, default=None, null=True,
blank=False)
class Clip(models.Model):
ads = models.ManyToManyField(AdBase, related_name='clips',
through='ClipAd')
class ClipAd(models.Model):
clip = models.ForeignKey(Clip, on_delete=models.CASCADE,
blank=False, null=False)
ad = models.ForeignKey(AdBase, on_delete=models.CASCADE,
blank=False, null=False)
position = models.IntegerField(default=0, blank=False, null=False)
I want in the class Clip, a query which returns all its clips ordered by their position.
I've come up with this:
class Clip(models.Model):
ads = models.ManyToManyField(AdBase, related_name='clips',
through='ClipAd')
def ads_by_position(self):
# there might be a simpler query than this:
return [a.ad
for a in ClipAd.objects.filter(clip=self).order_by('position')]
But I'm sure there's a simpler syntax using the ads property of my class Clip but I didn't find one.
Any idea (or is this the only solution)?
You can use prefetch_related for this purpose. It will also decrease your DB load a lot. Also, using custom managers worths a look.
class ClipManager(models.Manager):
def get_with_adds():
return Clip.objects.filter().prefetch_related("ads")
class AdBase(models.Model):
title = models.CharField(max_length=200, default="")
class Clip(models.Model):
ads = models.ManyToManyField(AdBase, related_name='clips',
through='ClipAd')
objects = ClipManager()
class ClipAd(models.Model):
clip = models.ForeignKey(Clip, on_delete=models.CASCADE)
ad = models.ForeignKey(AdBase, on_delete=models.CASCADE)
position = models.IntegerField(default=0)
clips_with_adds = Clip.objects.get_with_adds()
You can access related many to many items directly:
def ads_by_position(self):
return self.ads.all().order_by('position')

Nested Query / not directly related field in Django

If the models are as follows,
class Subject(BaseModel):
name = models.CharField(db_column='name', max_length=200, blank=False, null=False, unique=True)
class Meta:
managed = True
db_table = 'Subject'
class Topic(BaseModel):
name = models.CharField(db_column='name', max_length=200, blank=False, null=False, unique=True)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, null=False, related_name='subject_topic')
class Meta:
managed = True
db_table = 'Topic'
class Question(BaseModel):
topic = models.ForeignKey(Topic, on_delete=models.CASCADE, null=False, related_name='question_topic')
class Meta:
managed = True
db_table = 'Question'
How can I make a query Question for a subject.
questions = Question.objects.filter(topic_in=Topic.objects.get(subject=subject).only('id').all())
but it's not working. Any help would be really great help.
Your current "inner queryset" won't give you multiple values, it only returns 1.
Topic.objects.get(subject=subject).only('id').all()
You are using .objects.get() which returns a model instance, so for example .only() or .all() on that won't work unless your model has such a defined function.
Furthermore you don't really need 2 querysets, you can get your result with only one:
my_subject_ids = [...] # these are the ids of Subject models you want
Question.objects.filter(topic__subject_id__in=my_subject_ids)
You can also query for Subject.name, just use the following for this: topic__subject__name__in=my_list.
If you want to query for a specific Subject-instance you can use topic__subject=my_obj.
You also might wanna take a look at the docs for more information on that.

Having trouble linking two fields with one another, then implementing them to another model

I'm working on a project which helps users find jobs.
So one of the models, named Oferta is used for details about a job. Someone who is looking for emplooyes, just completes a form which is based on this model, and people will be looking at it.
Here's this model:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
cor = models.CharField(max_length=50)
dataSolicitare = models.DateField(default=date.today)
denumireMeserie = models.CharField(max_length=50)
locuri = models.IntegerField()
agentEconomic = models.CharField(max_length=50)
adresa = models.CharField(max_length=150)
dataExpirare = models.DateField()
experientaSolicitata = models.CharField(max_length=200)
studiiSolicitate = models.CharField(max_length=200)
judet = models.CharField(max_length=20)
localitate = models.CharField(max_length=25)
telefon = models.CharField(max_length=12)
emailContact = models.EmailField(max_length=40)
rezolvata = models.BooleanField(default=False)
def __str__(self):
return self.cor
The COR field is the code asociated to a job. Also, denumireMeserie means job name.
So these should be linked. Let's say, if code 1 means "Cook", these should be link - there will be no other job with a different code, or another job for code 1.
So, in my opinion, these two fields should have a OneToOne relationship between them, if I'm not mistaken.
But these codes and jobs need to be implemented in the database - so they need a model too.
class CORMeserii(models.Model):
CodCOR = models.CharField(max_length=25, primary_key=True, unique=True)
MeserieCor = models.OneToOneField(CodCOR, max_length=50, unique=True, on_delete=models.CASCADE)
And here is how I tried to do it, but obviously it won't work, because onetoonefield needs a model as the first parameter.
So, my questions are:
How can I link these two fields as I told you, and then link Oferta.cor to CORMeserii.CodCOR and Oferta.denumireMeserie to CORMeserii.MeserieCor?
(because each job with its code and name should be implemented in the database, then chosen in each Oferta (which means offer))
As Dirk pointed out on your previous question, you have not understood what relationship fields do in Django.
A ForeignKey or a OneToOneField gives you access to the entire related object. This means you can access any of the fields on that related object.
So your Oferta model does not need a denumireMeserie field; that belongs on the other model, which we might call "Job". Oferta has a link to that model, ie a ForeignKey:
class Oferta(models.Model):
solicitant = models.ForeignKey(User, on_delete=models.CASCADE)
job = models.ForeignKey('Job', on_delete=models.CASCADE)
and Job has the details of the job:
class Job(models.Model):
cor = models.CharField(max_length=50)
denumireMeserie = models.CharField(max_length=50)
Now you can create a Job and an Oferta for that job:
my_job = Job.objects.create(cor=1, denumireMeserie='Cook')
my_oferta = Job.objects.create(job=my_job, ...rest of the fields...)
Now you can access the job name via the relationship:
print(my_oferta.job.denumireMeserie)
which will give you "Cook".

How to serialize multiple models with one Serializer using DjangoRestFramework?

I have these Models all of which have PointField:
class Place(models.Model):
title = models.CharField(max_length=75, verbose_name='Заголовок')
category = models.ForeignKey(PlaceCategory, verbose_name='Категория')
...
point = geomodels.PointField(geography=True, blank=True, null=True)
...
class Event(models.Model):
title = models.CharField(max_length=75, verbose_name='Заголовок')
address = models.CharField(max_length=255, blank=True, null=True, verbose_name='Адрес')
city = models.ForeignKey(City, verbose_name='Город')
...
point = geomodels.PointField(blank=True, null=True)
...
class Meeting(models.Model):
title = models.CharField(max_length=75)
participants = models.ManyToManyField(User, related_name='participating_meetings')
...
point = geomodels.PointField(blank=True, null=True)
...
In project I have /points API url. By this url I want to return filtered set or all the points to show them on map.
I checked DRF documentation, there is example how to build Serializer for one Model, but how do I build the API view for these multiple models?
This kind of use case is typical of where you'd need to drop the default auto generated things (serializer / view) and roll your own. I would gather the data by myself, run them through a PointSerializer - might be optional - which would inherit from Serializer and return the result.