Group ManyToMany in Django admin - django

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.

Related

ManyToManyField or ForeignKeys in an intermediary model?

I don't understand why should I use ManyToManyField if I will (or might) store extra information along the many-to-many relationships.
The doc here shows this example:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=50)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
Person,
through='Membership',
through_fields=('group', 'person'),
)
class Membership(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
inviter = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="membership_invites",
)
invite_reason = models.CharField(max_length=64)
Why even having the members field there, if the developer already defines the relationship model and also defines the ForeignKeys? :D Why not leaving out the members ManyToManyField ?? What is the benefit? Thank you.
I don't understand why should I use ManyToManyField if I will (or might) store extra information along the many-to-many relationships.
You do not need to do this. But it makes querying more effective. Indeed, you can now query with:
Group.objects.filter(members=some_person)
this is shorter and more descriptive than working with:
Group.objects.filter(membership__person=some_person)
It is thus a "coding shortcut" to go from the Group model to the Person model and vice versa.

Django model relates to two other models

I'm trying to build a dictionary application and having a difficulty with the model.
Now I wrote this
class Term(models.Model):
term_text = models.CharField("phrase term text", max_length=100)
class Definition(models.Model):
term = models.ForeignKey(Term)
definition_text = models.TextField()
class Country(models.Model):
#is this correct method?
#Should i add ForeginKey for both Term and Definition here?
The problem is the Country. Both Term and Definition should have a Country field as Term could be available in many countries and a definition could be limited to certain countries with another definition for others.
now how to do this country model?
I've tried to use django-countries as a model field for Term and Definition but its limiting me to use only 1 country per object.
What you want is ManyToMany relationships on both Term and Definition. That way you'll be able to call my_term.countries and my_definition.countries.
class Term(models.Model):
term_text = models.CharField("phrase term text", max_length=100)
country = models.ManyToManyField(Country)
class Definition(models.Model):
term = models.ForeignKey(Term)
definition_text = models.TextField()
country = models.ManyToManyField(Country)
class Country(models.Model):
# define Country model
class Meta:
verbose_name_plural = "countries"

Django: modelling relations

In my app, there is a model "Image" and couple of models that an image can relate to (Event, Place, Member). I am considering two ways of modelling the image relations. The first one is to put relation field in Image for each related model (the field will be either ForeignKey or ManyToManyField). The second way is to put field "images" to each model that can have associated images (in case of some models it will be just one image). Which way is more recommended?
# the first way
class Member(models.Model):
name = models.CharField('name', max_length=128)
class Event(models.Model):
name = models.CharField('name', max_length=128)
class Place(models.Model):
name = models.CharField('name', max_length=128)
class Image(models.Model):
title = models.CharField('title', max_length=128)
members = models.ManyToManyField(Member)
place = models.ForeignKey(Place)
event = models.ForeignKey(Event)
# the second way
class Image(models.Model):
title = models.CharField('title', max_length=128)
class Member(models.Model):
name = models.CharField('name', max_length=128)
images = models.ManyToManyField(Image)
class Event(models.Model):
name = models.CharField('name', max_length=128)
images = models.ManyToManyField(Image)
class Place(models.Model):
name = models.CharField('name', max_length=128)
images = models.ManyToManyField(Image)
I could also use generic relations (third way) or I could make models like EventImage, PlaceImage, MemberImage (fourth way) but I have already decided these would not work for me that well.
If your relationship is Many-to-one, then the proper way to model it is with ForeignKey.
For Many-to-many relationships, it's less clear on which model to define one. Django documentation says the following:
It doesn’t matter which model has the ManyToManyField, but you should
only put it in one of the models – not both.
Generally, ManyToManyField instances should go in the object that’s
going to be edited on a form. In the above example, toppings is in
Pizza (rather than Topping having a pizzas ManyToManyField ) because
it’s more natural to think about a pizza having toppings than a
topping being on multiple pizzas. The way it’s set up above, the Pizza
form would let users select the toppings.

django implementation of models

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')

ForeignKey field problem in Django

I have declared two of my models this way:
class EmailAddress(models.Model):
customer = models.ForeignKey(Customer)
email_address = models.CharField(max_length=200)
def __unicode__(self):
return self.email_address
class Customer(models.Model):
.
.
.
email_address = models.ForeignKey(EmailAddress)
def __unicode__(self):
name = ''+str(self.title)+" "+str(self.first_name)+" "+str(self.last_name)
return name
The idea is that one customer can have several email addresses associated to him/her...the problem is how to do this correctly...as you can see from my code above, the customer foreign key field has to be after the customer class, but the email address foreign key field has to be after the EmailAddress class...how do I sort out this issue?
There is a serious logic flaw here - ForeignKey from Customer to Email would mean that each customer has only one email. You would want to skip that foreignkey alltogether:
class Email(models.Model):
customer = models.ForeignKey(Customer, related_name='email_addresses')
then simply do customer.email_addresses to get a list of all emails. You dont need another ForeignKey, django uses relationships defined in one model (unlike RoR and other MVC frameworks)
I don't see why you want to use a ForeignKey in EmailAddress.
Extract from Python web development with Django:
Foreign keys are generally used to
define one-to-many (or many-to-one)
relationships.
In the next example a Book has a single Author and an Author can have many Books.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author)
Just add single-quotes around Customer:
class EmailAddress(models.Model):
customer = models.ForeignKey('Customer')
email_address = models.CharField(max_length=200)
def __unicode__(self):
return self.email_address
Menda's answer is correct. There isn't really an ordering problem because the Customer model doesn't need a ForeignKey field. Just remove that and flip the order in which the classes are defined.
class Customer(models.Model):
pass
class EmailAddress(models.Model):
customer = models.ForeignKey(Customer)
email_address = models.CharField(max_length=200)
There's also a Django email field you can use. See Django EmailField. Just wanted to mention that in case it could add value to you application.