Defining a two way many to many in Django - django

Just starting in Python/Django framework so sorry if this is dumb... but i cant find any solution.
class Dealer(models.Model):
name = models.CharField(max_length=200)
contacts = models.ManyToManyField(Contact)
class Contact(models.Model):
name = models.CharField(max_length=200)
dealers = models.ManyToManyField(Dealer)
I have this relation set up however when I run SyncDB it doesnt work. It tells me that Contact is not defined on this line
contacts = models.ManyToManyField(Contact)
Im more familiar with compiled languages. Is there anyway to tell python that the contact class exists, or better yet is there a special syntax im missing for defining this kind of relation.

I dont see a need for a two way ManyToMany in both the models, as they are a M:N relationship (2 way relationship).
Your issue here is, Contact is not defined at the point of execution of this code:
contacts = models.ManyToManyField(Contact)
So You need to wrap it in quotes for it to work
contacts = models.ManyToManyField('Contact')
Documentation on that can be found here
I would recommend the following models:
class Dealer(models.Model):
name = models.CharField(max_length=200)
contacts = models.ManyToManyField('Contact')
class Contact(models.Model):
name = models.CharField(max_length=200)
and It would do exactly what you are looking for.
You can read about ManyToMany relationships here. The same link also covers how to handle Reverse m2m queries

If you want to do a two way ManyToMany both, you just only need to do this:
class Dealer(models.Model):
name = models.CharField(max_length=200)
contacts = models.ManyToManyField('Contact', blank=True)
class Contact(models.Model):
name = models.CharField(max_length=200)
dealers = models.ManyToManyField('Dealer', through=Dealer.projects.through, blank=True)
I guess it will work to you.

Related

How to call a a field of one model A into another model B so that b can work as a view

I have created a model called Department, Course. Models are as follow
This is the model for departments and course
class Departments(models.Model):
Department_Id = models.IntegerField(primary_key=True)
Department_Name = models.CharField(max_length=200)
Department_Code = models.CharField(max_length=200)
class Course(models.Model):
Course_Id = models.IntegerField(primary_key=True)
Department_Id = models.ForeignKey(Departments, on_delete=models.CASCADE)
Course_Name = models.CharField(max_length=200)
Course_Code = models.CharField(max_length=200)
I want to create a model called view which can be later on called for search. I want a view model in a such a way that it consit of the data in concat form i.e. name= Department_name+ Course_Name
class View (models.model):
view_id= models.IntegerField(primary_key=True)
Name= Department_name(I want this from Departments table)
+ Course_Name(I want this from Course table)
I try using one to one relation . I would really appricate the help
It's not clear why you'd want to do that. It's never a good idea to duplicate data from one model into another one, as it can lead to inconsistencies.
You can add a ForeignKey in View to your Course model and then when you do f"{view.course.name} {view.course.department.name}" you already have your string:
class View(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
def name(self):
return f"{self.course.name} {self.course.department.name}"
Notes:
Don't call your foreign key Department_id because it's not referring to the id but to the object itself in the Django ORM: department = models.ForeignKey(Department, on_delete=models.CASCADE). As you can see, this makes reading the code much simpler: self.course.Department_id is a Department object not an integer, so self.course.department makes more sense.
Don't prefix your field names with the class, it just makes the code so much less readable: Do you prefer department.name or department.Department_name?
The View model is still a mystery to me, as you can search without it. You can search for example for courses with a matching department name like this:
Course.objects.filter(department__name__icontains="maths")
which will return all courses with "maths" in their department name.
Remove all the ids from your models, they are created automatically by Django anyway (and called id). Again, department.id is much easier to read than department.Department_id. Also in your code, you have to generate the ids yourself since you don't set them to auto-populate.

Django - How to build an intermediate m2m model that fits? / best practice

First of all I have to admit that I'm quite new to all this coding stuff but as I couldn't find a proper solution doing it myself and learning to code is probably the best way.
Anyway, I'm trying to build an app to show different titleholders, championships and stuff like that. After reading the Django documentation I figured out I have to use intermediate models as a better way. My old models.py looks like this:
class Person(models.Model):
first_name = models.CharField(max_length=64)
last_name = models.CharField(max_length=64)
[...]
class Team(models.Model):
name = models.CharField(max_length=64)
team_member_one = models.ForeignKey(Person)
team_member_two = models.ForeignKey(Person)
class Championship(models.Model):
name = models.CharField(max_length=128)
status = models.BooleanField(default=True)
class Titleholder(models.Model):
championship = models.ForeignKey(Championship)
date_won = models.DateField(null=True,blank=True)
date_lost = models.DateField(null=True,blank=True)
titleholder_one = models.ForeignKey(Person,related_name='titleholder_one',null=True,blank=True)
titleholder_two = models.ForeignKey(Person,related_name='titleholder_two',null=True,blank=True)
Championships can be won by either individuals or teams, depending if it's a singles or team championship, that's why I had to foreign keys in the Titleholder class. Looking at the Django documentation this just seems false. On the other hand, for me as a beginner, the intermediate model in the example just doesn't seem to fit my model in any way.
Long story short: can anyone point me in the right direction on how to build the model the right way? Note: this is merely a question on how to build the models and displaying it in the Django admin, I don't even talk about building the templates as of now.
Help would be greatly appreciated! Thanks in advance guys.
So I will take it up from scratch. You seem to be somewhat new to E-R Database Modelling. If I was trying to do what you do, I would create my models the following way.
Firstly, Team would've been my "corner" model (I use this term to mean models that do not have any FK fields), and then Person model would come into play as follows.
class Team(models.Model):
name = models.CharField(max_length=64)
class Person(models.Model):
first_name = models.CharField(max_length=64)
last_name = models.CharField(max_length=64)
team = models.ForeignKey(to=Team, null=True, blank=True, related_name='members')
This effectively makes the models scalable, and even if you are never going to have more than two people in a team, this is good practice.
Next comes the Championship model. I would connect this model directly with the Person model as a many-to-many relationship with a 'through' model as follows.
class Championship(models.Model):
name = models.CharField(max_length=64)
status = models.BooleanField(default=False) # This is not a great name for a field. I think should be more meaningful.
winners = models.ManyToManyField(to=Person, related_name='championships', through='Title')
class Title(models.Model):
championship = models.ForeignKey(to=Championship, related_name='titles')
winner = models.ForeignKey(to=Person, related_name='titles')
date = models.DateField(null=True, blank=True)
This is just the way I would've done it, based on what I understood. I am sure I did not understand everything that you're trying to do. As my understanding changes, I might modify these models to suit my need.
Another approach that can be taken is by using a GenericForeignKey field to create a field that could be a FK to either the Team model or the Person model. Or another thing that can be changed could be you adding another model to hold details of each time a championship has been held. There are many ways to go about it, and no one correct way.
Let me know if you have any questions, or anything I haven't dealt with. I will try and modify the answer as per the need.

Django and reverse relations from foreign keys

suppose the following simple models:
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
author = models.ForeignKey(User, related_name='author_set')
How can I get all the authors that participated in a particular blog (i.e. pk=1)? I tried something like this, but it didn't work.
User.objects.author_set.filter(blog=Blog.objects.get(pk=1))
Many thanks in advance!
User.objects.filter(author_set__blog__pk=1)
I wasn't paying attention to your related name, so the code above (revised) now uses the proper related name. However, this is a really bad related name. The related name should describe what's on the opposite side, i.e. Entry. So really it should be related_name='entry_set'. However, that's the default anyways, so you can remove related_name if you just want that. I would typically use a simple pluralized version of the related class, which would be in this case related_name='entries'. Or, you might want to use something like "blog_entries" to be more specific.

Django: foreign key queries

I'm learning Django and trying to get the hang of querying foreign keys across a bridging table. Apologies if this is a duplicate, I haven't been able to find the answer by searching. I've got models defined as follows
class Place(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
class PlaceRef(models.Model):
place = models.ForeignKey(Place) # many-to-one field
entry = models.ForeignKey(Entry) # many-to-one field
class Entry(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=10)
If I want to retrieve all the Entries associated with a particular Place, how do I do it?
place = get_object_or_404(Place, id=id)
placerefs = PlaceRef.objects.filter(place=place)
entries = Entry.objects.filter(id.....)
Also, if there is a more sensible way for me to define (or get rid of) PlaceRefs in Django, please feel free to suggest alternatives.
Thanks for helping out a beginner!
First, I'd suggest rewriting the models to:
class Place(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
class Entry(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=10)
places = models.ManyToManyField(Place, related_name='places')
So you can query:
Entry.objects.filter(places__id=id)
In your current model:
Entry.objects.filter(placeref_set__place__id=id)
Note that the double underscore __ is used to jump from one model to the next. Also, django creates some fields on the model that help you navigate to related objects. In this example: Entry.placeref_set. You can read more about it here:
http://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward

Django order by related field

I want to sort a QuerySet of contacts by a related field. But I do not know how.
I tried it like this, but it does not work.
foundContacts.order_by("classification.kam")
Actually in a template I can access the kam value of a contact through contact.classification.kam since it is a OneToOne relationship.
The (simplified) models look like this:
class Classification(models.Model):
kam = models.ForeignKey(User)
contact = models.OneToOneField(Contact)
class Contact(models.Model):
title = models.ForeignKey(Title, blank=True, null=True)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
It should be:
foundContacts.order_by("classification__kam")
Here is a link for the Django docs on making queries that span relationships: https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships
You can also see some examples in the order_by reference:
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.order_by
as the documentation indicates, it should be used as in queries about related models
https://docs.djangoproject.com/en/3.0/ref/models/querysets/#order-by
foundContacts.order_by("classification__kam")
I've struggled a lot with this problem, this is how I solved it:
contact ordered by "kam" (Classification) field:
show_all_contact = Contact.objects.all().order_by(title__kam)
classification ordered by Users email (no sense in it, but only show how it works):
show_all_clasification = Classification.objects.all().order_by(kam__email)