django implementation of models - django

I have to implement two models in a django project --> Country and Continent.
It is possible to import all information about countries and continents from an XML file that populates the database with these two tables.
I've implemented them in this way
from django.db import models
class Continent(models.Model):
name = models.CharField(max_length=255, unique=True)
code = models.CharField(max_length=255, unique=True)
countries = ?
class Meta:
ordering = ['name']
class Country(models.Model):
name = models.CharField(max_length=255)
capital = models.CharField(max_length=255)
code = models.CharField(max_length=255, unique=True)
population = models.IntegerField(default=0)
area = models.IntegerField(default=0)
continent = models.ForeignKey(Continent)
class Meta:
ordering = ['name']
You can see a ? mark in Continent.countries because I don't understand how to implement it. The problem is: "Countries of a continent should be accessible through attribute countries of class Continent"
This means that it is possible to do this:
from MyApplication.model import Country, Continent
europe = Continent.object.get(code=u'eu')
finland = europe.countries.get(code=u'fi')
I've tried models.ForeignKey, but it doesn't work.
It says that "Nonetype object doesn't have any get method"
Can anyone help me please?
Thanks

Django does not support one to many directly, instead you can use the reverse of one-to-one relation to get a one-to-many relation.
So, go ahead with the other approach of using many to one by adding foreign key inside the country relating to continent. Now, you have a one-to-one from country to continent. Next, do a reverse query from Continent's object to get the desired relation. Take a look:
class Continent(models.Model):
...
class Country(models.Model):
...
continent = models.ForeignKey(Continent, related_name="countries")
...
europe = Continent.object.get(code=u'eu')
finland = europe.countries.get(code=u'fi')

Related

How to get count in Django for a model two foreign keys away

I have three modles in my Django app as follows:
class City(models.Model):
city_name = models.CharField(length=50)
class Area(models.Model):
city = models.ForeignKey(City)
area_name = models.CharField(length=50)
class Person(models.Model):
area = models.ForeignKey(Area)
person_name = models.CharField(length=50)
I require cities in order of their population (i.e. Person basis). How is it possible with Django?
Use annotate to count population.
City.objects.annotate(population=Count("area_set___person_set")).order_by("population")

Group ManyToMany in Django admin

I have a model "Company" having many to many relationships with Country and City while country and city have one to many relationship between them.
The problem is that when loading an "enterprise" have to select the countries atienede the company and the cities they serve, but the list of cities is very long and also the cities are all mixed without distinguishing what country you are. What I'd like is to group the cities by country.
It is exactly what django-smart-selects, only this plugin does not work in many to many relationships. Someone could help me adapt this plugin to work with many to many relationship or comment me if they think of another alternative.
Thank you very much!
class Company(models.Model):
name = models.CharField(max_length=255)
countries = models.ManyToManyField(Country)
cities = models.ManyToManyField(City)
class Country(models.Model):
name = models.CharField(max_length=255)
class City(models.Model):
name = models.CharField(max_length=255)
country = models.ForeignKey(Country)
Here is a solution how you can solve this in the admin with smart_selects:
Define the through model for your manytomany relationship (company to city). In the through model you define the relationship to the city as GroupedForeignKey. Then you make an inline in the admin for your Conpany with the through model.
class Country(models.Model):
name=models.CharField(max_length=50)
class City(models.Model):
name=models.CharField(max_length=50)
country=models.ForeignKey(Country)
class CCRel(models.Model):
city= GroupedForeignKey(City, "country")
company = models.ForeignKey("Company")
class Company(models.Model):
name=models.CharField(max_length=50)
country = models.ManyToManyField(Country,through="CCRel")
And the admin.py:
class CInline(admin.TabularInline):
model = CCRel
class CAdmin(admin.ModelAdmin):
inlines=[CInline]
admin.site.register(Company,CAdmin)
It should also work with ChainedForeignKey in a similar manner.
You should remove the country field from the Company model as this is redundant.

Django model - set up a "has_many_through" relationship

Looking for advice on setting up this model.
This job board app has Company, Location, and Job. They should have the following relationships:
A Company can have multiple locations
A Company can have multiple jobs
A Job can have only one Company
A Job can have multiple locations, BUT each Location must be valid for the job's Company
I'd like to create a model that reflects these relationships. I think something like this might work:
class Company(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
class Location(models.Model):
is_primary_location = models.BooleanField()
address = models.CharField(max_length=200)
company = models.ForeignKey(Company)
class Job(models.Model):
title = models.CharField(max_length=200)
company = models.ForeignKey(Company)
location = models.ForeignKey(Location)
But I would really like the "Job has Location(s) through Company" relationship to be enforced. The model doesn't enforce it; I think I'd have to filter the valid Locations when data is displayed, and I'd like to avoid that.
Thanks very much!
Take a look at ForeignKey.limit_choices_to.
This allows you to filter the available choices and is enforced in ModelForm. Since you already have the company foreign key in your Job model, you should be able to use that to filter the choices.
I ended up using https://github.com/digi604/django-smart-selects and wrote the model like this. I don't think limit_choices_to works in this case (according to other SO threads)
from smart_selects.db_fields import ChainedForeignKey
class Company(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
class Location(models.Model):
is_primary_location = models.BooleanField()
address = models.CharField(max_length=200)
company = models.ForeignKey(Company)
class Job(models.Model):
title = models.CharField(max_length=200)
company = models.ForeignKey(Company)
location = ChainedForeignKey(
Location,
chained_field="company",
chained_model_field="company",
show_all=False,
auto_choose=True
)

about multiple relations in django.models? noob here

this is my models.py
from django.db import models
# Create your models here.
class Leagues(models.Model):
LeagueName = models.CharField(max_length=200)
class Team(models.Model):
TeamName = models.CharField(max_length=200)
class LeagueTable(models.Model):
league = models.ForeignKey(Leagues)
team = models.CharField(max_length=200)
matches_played = models.IntegerField()
matches_won = models.IntegerField()
matches_drawn = models.IntegerField()
matches_lost = models.IntegerField()
points = models.IntegerField()
class FixtureTable(models.Model):
league = models.ForeignKey(Leagues)
fixture_date = models.DateField('Fixture Date')
team_one = models.CharField(max_length=200)
team_one_score = models.IntegerField()
team_two = models.CharField(max_length=200)
team_two_score = models.IntegerField()
in the "class FixtureTable", i want team_one and team_two to be linked to two differnt teams in "class Team" models. how to create multiple relations, or is it possible.
PS: this is purely a noob, with a little experience in programming, but no experience with either python or databases.
thankyou.
You can create as many ForeignKeys as you like to the same model. I suspect what's tripping you up is Django giving you an error saying that you need to specify a related name.
By default, Django creates an attribute on the opposite model of the form <model>_set. So in the following scenario:
class FixtureTable(models.Model):
team_one = models.ForeignKey(Team)
Django would add a related manager to Team as fixturetable_set. If you then did:
class FixtureTable(models.Model):
team_one = models.ForeignKey(Team)
team_two = models.ForeignKey(Team)
Django would attempt to add the same attribute twice and obviously fail. The fix is to specify a related_name, so each can have a unique related manager:
class FixtureTable(models.Model):
team_one = models.ForeignKey(Team, related_name='team_one_fixturetables')
team_two = models.ForeignKey(Team, related_name='team_two_fixturetables')
Then, everything will work fine. You can specify whatever you like for related_name as long as it's unique for the model.

How do I write a Django model with ManyToMany relationsship with self through a Model

I want to have a model with a ManyToMany relationship with itself, I don't know how to write this but I'l try to write some code to illustrate what I want to do.
class Person(models.Model):
name = models.CharField()
occupation = models.CharField()
friends = models.ManyToManyField('self', through = PersonFriends)
My Model that I want the friends to go through
class PersonFriends(models.Model)
???
comment = models.CharField()
In a ManyToMany field with through relationship if the other model's name was "Pet" for example I'd name my fields in that through class person and pet and make them models. ForeignKey(Person) and Pet for example
What to I name my fields in my PersonFriends model for the two person-fields now that they are the same model?
You can do something like this:
class Person(models.Model):
name = models.CharField(max_length = 255)
occupation = models.CharField(max_length = 255)
friends = models.ManyToManyField('self', through = 'PersonFriends',
symmetrical = False)
# ^^^^^^^^^^^
# This has to be false when using `through` models. Or else your
# model will not validate.
class PersonFriends(models.Model):
source = models.ForeignKey(Person, related_name = 'source')
# ^^^^^^^^^^^^
# You need different `related_name` for each when you have
# multiple foreign keys to the same table.
target = models.ForeignKey(Person, related_name = 'target')
comment = models.CharField(max_length = 255)
Everything is described in the official docs for ManyToManyField.through_fields (you can search for 'recursive relationships' phrase there to quickly find what you need):
for django 1.11 you have to specify through and (!) through_fields arguments:
class Person(models.Model):
name = models.CharField(max_length=50)
# note the additional arguments here
friends = models.ManyToManyField(
'self',
# recursive relationships to self with intermediary
# through model are always defined as non-symmetrical
symmetrical=False,
through='PersonFriend',
# this argument is required to define a custom
# through model for many to many relationship to self
# position matters: 1 - source (from), 2 - target (to)
through_fields=('person', 'friend'),
)
class PersonFriend(models.Model):
# required relationship-defining foreign keys
# (note that the order does not matter, it matters
# in 'through_fields' argument in 'friends' field of the 'Person' model)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
friend = models.ForeignKey(Person, on_delete=models.CASCADE)
# additional fields
comment = models.CharField()
Without assuming that friendships are symmetrical. Because Buzz Lightyear might be Woody's friend, but Woody isn't friends with Buzz Lightyear till near the end of the film. You can simplify both models and still have reasonable lookup names. You would of course need to make sure that you define two PersonFriends if it's a good friendship.
class Person(models.Model):
name = models.CharField()
occupation = models.CharField()
class PersonFriends(models.Model):
from_person = models.ForeignKey(Person, related_name='friends_with')
to_person = models.ForeignKey(Person, related_name='friends')
comment = models.CharField()
class Meta:
unique_together = ('from_person', 'to_person')
This has the added bonus of a comment for each direction of the friendship. i.e. Tyrion thinks Sansa is a lovely and intelligent, but lost girl. Whereas Sansa might think that Tyrion is an ugly but clever and kind-hearted kinda guy.
class PersonFriends(models.Model):
from_person = models.ForeignKey(Person, related_name='from_person')
to_person = models.ForeignKey(Person, related_name='to_person')
this is from db table structure of a ManyToMany relation to self from my Model structure. Django defines it like that..