I have some chained foreign key relationships like this:
class Continent(models.Model):
continent = models.CharField(max_length=30)
class Country(models.Model):
country = models.CharField(max_length=30)
continent = models.ForeignKey(Continent)
class City(models.Model):
city = models.CharField(max_length=30)
country = models.ForeignKey(Country)
class Person(models.Model):
name = models.CharField(max_length=30)
continent = models.ForeignKey(Continent)
country = models.ForeignKey(Country)
city = models.ForeignKey(City)
Is it strictly necessary to have continent and country fields into Person class to make chained select work?
I would like that Person model stores only city foreign key, but in admin edit form I would like to show continent/country/city chained select.
Related
Suppose I have three models such as -
class company(models.Model):
companyName = models.charField()
class branch(models.Model):
branchName = models.charField()
company = models.ForeignKey(company, on_delete=models.CASCADE)
Now in the third model, that is customer I want to have unique customer per compnay so I did -
class customers(models.Model):
customerName = models.charField()
branch= models.ForeignKey(branch, on_delete=models.CASCADE)
company = models.ForeignKey(company, on_delete=models.CASCADE)
class Meta:
unique_together = (
('company', 'customerName'),
)
Now since the branch has already got company as a foreign field and I'm again using both branch and company in the customers model, will this form a cyclic structure, or is this a wrong way of doing it?
And if I remove the company from the customers model because branch already has company as a foreign field, how can I set unique customers per company at the database level?
This shouldn't create a cyclical structure, but you don't need company as an attribute.
You can access company through the branch foreign key. This should work:
class customers(models.Model):
customerName = models.charField()
branch= models.ForeignKey(branch, on_delete=models.CASCADE)
class Meta:
unique_together = (
('branch__company', 'customerName'),
)
Although, branch and customerName should theoretically be unique_together as well.
I need to have user inputing his address by first select country, then city, then district, and then sub-district. How do I best implement this functionality in django Form? The models are similar to this:
Class Country(models.Model):
name = models.CharField(max_length=30)
Class City(models.Model):
name = models.CharField(max_length=30)
country = models.ForeignKey(Country)
Class District(models.Model):
name = models.CharField(max_length=30)
city = models.ForeignKey(City)
Class Subdistrict(models.Model):
name = models.CharField(max_length=30)
district = models.ForeignKey(District)
You can use Filtering results based on the value of other fields in the form from django-autocomplete-light
I have a simple Person class and a Club class that should contain lots of Person instances:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=200)
class Club(models.Model):
name = models.CharField(max_length=200)
persons = models.ForeignKey(Person, on_delete=models.CASCADE)
How do I add more than one Person to the persons attribute? I want to build a database and then save it as follows:
club = Club(name='some_club')
club.person.add(Person(name='Alex'))
club.person.add(Person(name='John'))
club.save()
# etc. ...
Your foreign key is the wrong way round. To allow multiple people to be members of each club, the FK needs to be on Person pointing to Club.
class Person(models.Model):
name = models.CharField(max_length=200)
club = models.ForeignKey("Club", on_delete=models.CASCADE)
class Club(models.Model):
name = models.CharField(max_length=200)
...
some_club = Club(name='some_club')
some_club.save()
some_club.person_set.add(Person(name='Alex'))
some_club.person_set.add(Person(name='John'))
# Or:
Person.objects.create(name="Alex", club=some_club)
class Club(models.Model):
name = models.CharField(max_length=200)
class Person(models.Model):
name = models.CharField(max_length=200)
club = models.ForeignKey(Club, on_delete=models.CASCADE)
club1 = Club(name='some_club')
club1.save()
person1 = Person(name='Alex', club=club1)
person1.save()
person2 = Person(name='John', club=club1)
person2.save()
Edit: changed istance name to club1
I have 3 models using Django Framework:
class Student(models.Model):
name = models.CharField()
surname = models.CharField()
class Group(models.Model):
groupId = models.AutoField()
name = models.CharField()
students = models.ForeignKey(Student)
class Faculty(models.Model):
facultyId = models.AutoField()
students = models.ForeignKey(Student)
I need to get the list of all students and for each one to have the student's group and faculty.
Well, first you need to modify your model relationships. With your current models, each Faculty and Group will have a single student.
You can modify the model to this:
class Group(models.Model):
groupId = models.AutoField()
name = models.CharField()
class Faculty(models.Model):
facultyId = models.AutoField()
class Student(models.Model):
name = models.CharField()
surname = models.CharField()
group = models.ForeignKey(Group)
faculty = models.ForeighKey(Faculty)
Then to get the Group and faculty of each student you can use select_related.
Now your query will look like this:
Students.objects.all().select_related('group', 'faculty')
class Student(models.Model):
name = models.CharField()
surname = models.CharField()
class Group(models.Model):
groupId = models.AutoField()
name = models.CharField()
students = models.ForeignKey(Student, related_name="group")
class Faculty(models.Model):
facultyId = models.AutoField()
students = models.ForeignKey(Student, "related_name"="faculty")
you can get this data Student.objects.filter(group__isnull=False, faculty__isnull=False )
It will return the student who have faculty and group.
for Json data:
class Student(serializer.ModelSerializer):
class Meta:
model = Student
fields = ('name', 'surname' , 'group', 'faculty')
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.