Django generic.DetailView: How to join multiple custom contexts? - django-models

I am extending a generic.DetailView of Car with a custom context.
This context shows each Sighting of the car like this:
class CarDetailView(generic.DetailView):
model = Car
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
sighting = Sighting.objects.filter(car_id=context['car'])
context['sighting_list'] = sighting
context['num_sighting'] = Sighting.objects.filter(car_id=context['car']).count()
context['pics_sighting'] = Pic.objects.select_related('sighting_id__car')
return context
Each Sighting has a several pictures in Pic that are related via ForeignKey. How do I get these pictures to show up in its corresponding Sighting entry? That select_related query returns all images.

Related

Django Rest returning related items for each item

I was trying to find answer in similiar questions, but none was meeting my expectations.
I have 2 models:
class Artist(models.Model):
name = models.CharField(max_length=255)
music_type = models.CharField(max_lenght=50)
def __str__(self):
return self.name
class Event(models.Model):
event_name = models.CharField(max_length=255)
...
artists = models.ManyToManyField(Artist)
def __str__(self):
return self.event_name
I also have serializers.py file:
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
fields = '__all__'
class ArtistSerializer(serializers.ModelSerializer):
events = EventSerializer(source='event_set', many=True)
class Meta:
model = Artist
fields ='__all__'
The event in ArtistSerializer allows me to return all events where artist takes part.
Now for each artist I would like to get list of all artists if they ever were taking part in the same event.
For example I have 5 Artists (A1...A5) and 3 Events (E1...E3)
In Event 1: [A1,A3]
In Event 2: [A3,A4,A5,A2]
In Event 3: [A2, A3]
So for A3 I would like to get list [A1,A4,A5,A2]
For A1: [A3]
For A2: [A3,A4,A5]
Unfortunately I have huge problem to create this query as SQL-query and ORM mechanism looks more complicated in this situation. Can somebody help me with this problem or give hints how to solve this?
If it's needed I'm gonna share more code
You can query the through model to get the artists related to an event. This is the intermediate model which django will have created to make that M2M relationship.
Where you have a ManyToManyField it has an attribute of through which is the M2M model.
So from your event model you could do something like Event.artists.through.objects.all() and you'd see all the instances in your M2M model.
So to find out the artists which are linked to a given event you could query that same table;
Event.artists.through.objects.filter(event_id=1).select_related('artist')
This would then return all the objects in the M2M which belong to Event 1. You could then get the artists from there, or just grab the artist IDs Event.artists.through.objects.filter(event_id=1).values_list('artist_id, flat=True)
Given the scenario in your comment...
If you have an artist, then you can run a query to get the events they've been in, and then run another query with those event ids. In that second query you are then looking to get the artist ids that aren't the current artist you're already looking at.
# First get the events that the current artist has been in
event_ids = Event.artists.through.objects.filter(artist_id=1).values_list('event_id, flat=True)
# Then get the other artists who have been in the same events
other_artist_ids = Event.artists.through.objects.filter(event_id__in =event_ids).exclude(artist_id=1).values_list('artist_id, flat=True)
# or the full instances
other_artists = Event.artists.through.objects.filter(event_id__in =event_ids).exclude(artist_id=1).select_related('artist')

custom intermediate table django fetch the records

I have two models with M2M relation. The custom table is defined as with en extra field
class DoctorHospital(models.Model):
clinic = models.ForeignKey(ClinicHospital, on_delete=models.CASCADE)
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
shift = models.CharField(max_length = 10)
Problem is that I am trying to fetch all clinics based on a specific doctor. Data is come based on specific doctor but custom field shift does not come.
here is my class base view
class DoctorDetailView(generic.DetailView):
model = Doctor
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['clinic_hospital_list'] = self.object.clinic_hospital.all()
return context
You can annotate the clinic_hospital_list to obtain the related shift value:
from django.db.models import F
class DoctorDetailView(generic.DetailView):
model = Doctor
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['clinic_hospital_list'] = self.object.clinic_hospital.annotate(
shift=F('doctorhospital__shift')
)
return context
Now the ClinicHospitals that arise from this queryset will have an extra attribute .shift that holds the value of the shift field in the intermediate table.

Dynamicaly connect two models in Django

let's suppose i have two models like below:
class Client(models.Model):
login = models.CharField(max_length=100)
password = models.CharField(max_length=100)
class Users(models.Model):
user_login = models.CharField(max_length=100)
user_pass = models.CharField(max_length=100)
One model [Users] is filled with data, second [Client] is empty. First i can populate Client based on Users. Now all Django data changes will by held only on Client model.
Question:
How to dynamically connect this two models fields? For example if some data is changed on model Client then according data will by changed also on Users model.
Solution suggestion:
I can update or populate Client data and simultaneously update or populate Users data. Is there another solution to do this?
if login is unique then no need to maintain foreign key relations, You can override the save() methods in both models else You have to maintain the foreign key relation and override the save() methods.
With help of this post i manage to link two models with below code:
class Client(models.Model):
login = models.CharField(max_length=100)
password = models.CharField(max_length=100)
# save previous instance
def __init__(self, *args, **kwargs):
super(Invoice, self).__init__(*args, **kwargs)
self.original_login = self.login
# override save method to update another model fields
def save(self, *args, **kwargs):
# import in place to avoid circular imports
from app.models import Users
if self.login != self.original_login:
Users.objects.filter(id=self.id).update(user_login=self.login)
# save changed data on Client model
super(Client, self).save(*args, **kwargs)
The same method goes to the Users model.
Note that this two model are in different apps.

Multi user profile creation function

I'm django learner and I'm trying to design multiple userprofile system.
I recently saw the create_profile function for single userProfile. How can I redesign it to multi user profile creation function?
def create_profile(sender,**kwargs):
if kwargs["created"]:
user_profile=Student.objects.create(user=kwargs["instance"])
post_save.connect(create_profile,sender=User)
Have two models for each profile type. If you want, have them inherit from a base model but you don't need to.
class Student(models.Model):
user = models.ForeignKey(User)
# more fields
class Master(models.Model):
user = models.ForeignKey(User)
# more fields
myuser = User.objects.get(...)
student = Student.objects.create(user=myuser)
master = Master.objects.create(user=myuse

Updating existing entity in endpoints-proto-datastore

I am using Endpoints-proto-datastore written by Danny Hermes for Google App Engine and need help figuring out how to update an entity.. My model for what I need to update is the following
class Topic(EndpointsModel):
#_message_fields_schema = ('id','topic_name','topic_author')
topic_name = ndb.StringProperty(required=True)
topic_date = ndb.DateTimeProperty(auto_now_add=True)
topic_author = ndb.KeyProperty(required=True)
topic_num_views = ndb.IntegerProperty(default=0)
topic_num_replies = ndb.IntegerProperty(default=0)
topic_flagged = ndb.BooleanProperty(default=False)
topic_followers = ndb.KeyProperty(repeated=True)
topic_avg_rating = ndb.FloatProperty(default=0.0)
topic_total_rating = ndb.FloatProperty(default=0.0)
topic_num_ratings = ndb.IntegerProperty(default=0)
topic_raters = ndb.KeyProperty(repeated=True)
And as you can see, the rating properties have a default of 0. So each time a topic is rated, I need to update each of the rating properties. However, none of my properties is the actual rating being provided by the user. How can i pass in the value the user rated the topic to be able to update the properties in the model? Thanks!
You can do this by having an "alias" property called rating associated with your UserModel:
from endpoints_proto_datastore.ndb import EndpointsAliasProperty
class UserModel(EndpointsModel):
...
def rating_set(self, value):
# Do some validation
self._rating = value
#EndpointsAliasProperty(setter=rating_set)
def rating(self):
return self._rating
This will allow ratings to be sent with UserModels in requests but won't require those ratings to be stored.
You're better off using the OAuth 2.0 token for the user and calling endpoints.get_current_user() to determine who the user is in the request.
Something like a dedicated model for ratings could be much easier:
from endpoints_proto_datastore.ndb import EndpointsUserProperty
class Rating(EndpointsModel):
rater = EndpointsUserProperty(raise_unauthorized=True)
rating = ndb.IntegerProperty()
topic = ndb.KeyProperty(kind=Topic)
and then transactionally retrieving the Topic from the datastore and updating it in a request method decorated by #Rating.method.

Resources