Foreign key which related to other foreign key choice - python

I'm trying to make the following models in django:
class Client(models.Model):
client = models.CharField(max_length=200)
loyal = models.BooleanField(default=False)
class Contact(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
client_id = models.ForeignKey(Client, on_delete=models.SET_NULL,null=True)
class Activity(models.Model):
title = models.CharField(max_length=30)
text = models.CharField(max_length=1000)
client_id = models.ForeignKey(Client, on_delete=models.PROTECT)
contact_id = models.ForeignKey(Contact, on_delete=models.PROTECT,limit_choices_to={'id__in': client_id.contact_set.all().values('id').query})
What i want to achieve - when i creating an activity and choose client in it - i want that in contact field i have to choose only from the contacts which related to choosen client, because when i do:
contact_id = models.ForeignKey(Contact, on_delete=models.PROTECT)
Django allow me to choose from all the contacts. I want to limit somehow the list of contacts from i need to choose, i try this way:
contact_id = models.ForeignKey(Contact, on_delete=models.PROTECT,limit_choices_to={'id__in': client_id.contact_set.all().values('id').query})
But i receive this error:
AttributeError: 'ForeignKey' object has no attribute 'contact_set'
How should i do it right?

Related

How to get table data (including child table and sub child data) based on id which obtains from another table data? Django

views
company = Company.objects.get(id = company_id) # getting input from django urls (<int:company_id>)
vehicles = CompanyContainVehicles.objects.filter(company_id=company.id) # Give all rows having same id (company.id)
all_vehicles = Vehicle.objects.filter(companies=company) # Gives all row with id provide by company
all_vehicles_parts = VehiclePart.objects.filter(__________) # Not Working
models
class Company(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(blank=True, null=True, unique=True)
description = models.TextField()
class Vehicle(models.Model):
vehicle_number = models.IntegerField()
name = models.CharField(max_length=255)
slug = models.SlugField(blank=True, null=True, unique=True)
companies = models.ManyToManyField(
Company,
through='CompanyVehicle',
related_name='companies'
)
class CompanyVehicle(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class VehiclePart(models.Model):
id = models.AutoField(primary_key=True)
vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE)
type = models.ForeignKey(PartType, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
How do I get VehiclePart's with their Vehicle? (I think I will give all the data in a variable and we should divide it and add it with their Vehicle). Also, what can we do to access data if VehiclePart contains a child class named VehiclePartDetail?
I think I will give all the data in a variable and we should divide it and add with their Vehicle.
You don't have to. Django can read ForeignKey relations in reverse. You can query with:
qs = Vehicle.objects.prefetch_related('vehiclepart_set')
then you can enumerate over the queryset, and for each Vehicle object, access this with .vehiclepart_set.all(). For example:
for item in qs:
print(vehicle_name)
for part in item.vehiclepart_set.all():
print(part.id)

Django - Relationships in Models

In Django there are field types called ForeignKey and OneToMany/OneToOne, I was wondering would I use ForeignKey or the relationship type as the field type in this scenario? User to Profile has been identified as OneToOne but I'm unsure about the others.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
fullname = models.CharField(max_length=100)
dob = models.DateField()
address = models.TextField()
city = models.CharField(max_length=100)
profilephoto = models.ImageField(default='default_profile.jpg', upload_to='reviewApp/static/profile_images')
class Product(models.Model):
name = models.CharField(max_length=100)
brand = models.CharField(max_length=100)
cost = models.DecimalField(max_digits=8, decimal_places=2, default=0.00)
category = models.CharField(max_length=100)
releasedate = models.DateField()
description = models.TextField()
productphoto = models.ImageField(default='default_product.jpg', upload_to='reviewApp/static/product_images')
class Review(models.Model):
product = models.ForeignKey(Product)
profile = models.ForeignKey(Profile)
author = models.ForeignKey(User, on_delete=models.CASCADE)
rating = model.PositiveSmallIntegerField(default=1, validators = [MinValueValidator(1), MaxValueValidator(5)])
reviewtext = models.TextField()
postdate = models.DateTimeField(auto_now_add=True)
lastmodified = models.DateTimeField(auto_now=True)
So from what I see here, it seems to be good if the following is what you want:
User can have only one profile and one Profile is related to only one user.
a Profile can make multiple Review but a Review belongs to only one profile.
A Product can have multiple Review but a Review is specific to one Product.
Be carefull to define the on_delete argument for your foreign keys depending of what you want to keep in your database after a delete.
More info from the doc : https://docs.djangoproject.com/fr/2.2/ref/models/fields/#arguments

Django - filtering out already rated restaurants in yelp like app

Consider the following database model:
class User:
id = models.BigAutoField(primary_key=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
class Restaurant:
id = models.BigAutoField(primary_key=True)
title = models.CharField(max_length=50)
class Rating:
id = models.BigAutoField(primary_key=True)
by_user = models.ForeignKey(to='User',
on_delete=models.PROTECT,
related_name='written_ratings')
for_restaurant = models.ForeignKey(to='Restaurant',
on_delete=models.PROTECT,
related_name='received_ratings')
score = models.SmallIntegerField()
# make sure only one vote per user per restaurant
class Meta:
unique_together = ('by_user', 'for_restaurant')
For a given User, we can obtain a list of Restaurant that we have not yet rated by performing the following query (that I have learned from my last post)
eligible_restaurants = Restaurant.objects.exclude(rating__by_user_id=my_id)
But what happens when the Ratings don't point directly at the Restaurants - but rather at an intermediate Profile object?
class User:
id = models.BigAutoField(primary_key=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
class Restaurant:
id = models.BigAutoField(primary_key=True)
title = models.CharField(max_length=50)
current_profile = models.OneToOneField(to='Profile',
on_delete=models.PROTECT,
related_name='+')
# the `+` means to not generate a related name
class Profile:
# this is here acting as an intermediate between
# `Restaurant` and `Rating` so that we can keep track
# of all reviews - deleting/remaking would simply be
# creating a new `Profile` and setting the `Restaurant`
# to point to it instead - the old one will act as a
# historical record
id = models.BigAutoField(primary_key=True)
by_restaurant = models.ForeignKey(to='Restaurant',
on_delete=models.PROTECT,
related_name='written_profiles')
picture_url = models.CharField(max_length=500)
picture_desc = models.CharField(max_length=500)
class Rating:
id = models.BigAutoField(primary_key=True)
by_user = models.ForeignKey(to='User',
on_delete=models.PROTECT,
related_name='written_ratings')
for_profile = models.ForeignKey(to='Profile',
on_delete=models.PROTECT,
related_name='received_ratings')
score = models.SmallIntegerField()
# make sure only one vote per user per restaurant
class Meta:
unique_together = ('by_user', 'for_profile')
How would I query for eligible restaurants now?
You could filter them starting with restaurants
restaurant_ids = Rating.objects.filter(by_user=user).values_list('for_profile__by_restaurant', flat=True).distinct()
eligible_restaurants = Restaurant.objects.exclude(id__in=restaurant_ids)
Note: this will generate only one query because django's querysets are lazy.

Django - how to query all users associated with a "listing" object

My models look like this:
CustomUser has a many to many relationship with a "Listing" object
Each Listing object has an "author" field
author = models.ForeignKey(CustomUser)
Essentially, a listing has both an author (CustomUser) and custom users who need confirmation.
I'm trying to get all the custom users who need confirmation for all the listings posted by the author.
I'm not sure what the correct way to query is.
Listing.objects.filter(author=author).needsConfirmation_set.all()
The models
class CustomUser(models.Model):
user = models.OneToOneField(User)
location = models.CharField(max_length=50)
rating = models.FloatField(null=True)
level = models.CharField(max_length=50)
followers = models.ManyToManyField("self", related_name="followers")
following = models.ManyToManyField("self", related_name="following")
interested = models.ManyToManyField('Listing', related_name = 'interested', default=None)
needsConfirmation = models.ManyToManyField('Listing', related_name = 'needsConfirmation', default=None)
confirmed = models.ManyToManyField('Listing', related_name = 'confirmed', default=None)
class Listing(models.Model):
subject = models.CharField(max_length=42)
location = models.CharField(max_length=50, default="N/A")
description = models.CharField(max_length=500)
author = models.ForeignKey(CustomUser)
date = models.DateTimeField(default=timezone.now)
I think it's as simple as:
CustomUser.objects.filter(needsconfirmation__author=author)

Django get_or_create fails on models.ForeignKey fails

Have a model with two classes
class Employee(models.Model):
emp_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
phone_number = models.CharField(max_length=20, unique=True)
company = models.ForeignKey(Company, db_column='company_id')
class Company(models.Model):
company_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=150)
phonenumber = models.CharField(max_length=20, unique=True)
in my views.py i have a method that receive a post request and does registers an employee using get_or_create like so
employee, created = Employee.objects.get_or_create(name=emp_name, phone_number=emp_phone_number,company_id=emp_company_id)
employee.save()
but get_or_create results in an error
Cannot resolve keyword 'company_id' into field. Choices are:name,phone_number,company
how do i save the company_id as reference key?
Try:
company = Company.objects.get(id=company_id)
employee, created = Employee.objects.get_or_create(name=emp_name, phone_number=emp_phone_number,company=company)
employee.save()

Categories

Resources