Django Admin list values from many to many fields - django

For a podcast site I do have a Guest model which (stripped down) looks like this.
class Guest(models.Model):
...
episodes = models.ManyToManyField(Episode)
name = models.CharField(max_length=100, blank=False)
...
also there are a few other models connected through many to many fields with the guest model like Job and Topic (simple models with one or two CharField with some information and the ManyToManyField relation with Guest.
Now I want to display The Job(s) of a guest and his Topics in the Admin List of Guests. Also for the linked Episodes Model I want to count the amount of episodes a guest was in and also show the date (published_at field in Episode model) of the newest and the oldest Episode the guest was in.
I tried a few things already but I can't seem to get the data from the many to many fields into that list display. I'm on Django 2.0.7

You cant just show, you make create one function and JOIN the values together...
class AdminGuest(admin.ModelAdmin):
list_display = ('_episodes')
def _episodes(self, obj):
return "\n".join([a.nome for a in obj.episodes.filter()])
_episodes.short_description = "List of Episodes"

Related

Django Admin not limiting choices on ManyToMany field

I suddenly am having a problem with my django admin panel.
I have the following models:
class Role(models.Model):
name = models.CharField("Name", max_length=32)
class Person(models.Model):
name = models.CharField("Name", max_length=64)
role = models.ForeignKey(Role)
class Team(models.Model):
rep = models.ManyToManyField(
Person,
related_name="rep_on",
limit_choices_to={'role__name': 'Sales Rep'})
eng = models.ManyToManyField(
Person,
related_name="eng_on",
limit_choices_to={'role_id__name': "Engineer"})
(The two options in the limit_choices_to dictionaries are the two methods I've tried. In the past it seemed like role_id__name worked, but now it doesn't.)
If I create roles for the Sales Rep and Engineer, and create a bunch of people and attach roles, when I create a Team in the admin, I get dropdowns like I expect:
There are two problems. Each dropdown contains every Person object, so limit_choices_to doesn't seem to work at all, and of course these relationships are generic "TEAM-PERSON RELATIONSHIPS" and I'd like to be able to at least label those correctly.
I swear this worked before, and now it's not working. Any ideas as to what could be causing this?
EDIT:
I created a toy application to explore this and tried to slowly recreate the full issue. In my real app I am using two Inlines in the admin interface for the Team object and excluding the model fields. I added them into my test code and managed to recreate the issue.
class RepInline(admin.TabularInline):
model = Team.rep.through
class EngInline(admin.TabularInline):
model = Team.eng.through
class TeamAdmin(admin.ModelAdmin):
inlines = [RepInline, EngInline]
admin.site.register(Role)
admin.site.register(Person)
admin.site.register(Team, TeamAdmin)
And my admin screen looks like:
The given HTML Select fields are filtered, but the dropdowns are not, So the issue lies in the TabularInline, so I have to decide if I want to keep them or not.

django - many-to-many and one-to-many relationships

I am working in django, am planning a database for rides for users.
each User can be on multiple Rides (over time) and each Ride can have multiple Users (passengers) in it.
Also, for each Ride there has to be only one Driver (also a User) so I think I have a many-to many relationship between the Rides and Users tables for what user is on what ride, and also a One-To-Many relationship between the Rides's Driver_id and the User_id. right?
My questions are-
I saw in the django docs that I should put a many-to-many field in One of the models. Does it matter which one? and also, does it create a new table like rides_users?
and also, what is the difference (in One-To-many relationship) between using a foreignKey field and a OneToManyField field?
EDIT:
Currently, there are my models:
def get_image_path(models.Model):
return os.path.join('photos',str(instance.id),filename)
class UserProfile(models.Model):
user=models.OneToOneField(User)
phone_number=models.CharField(max_length=12)
profile_picture=models.ImageField(upload_to=get_image_path, black=True, null=True)
class Ride(models.Model):
driver=models.ForeignKey(UserProfile, related_name="r_driver")
destination=models.ForeignKey(Destination, related_name="r_final_destination")
leaving_time=models.DateTimeField()
num_of_spots=models.IntergerField()
passengers=models.ManyToMany(UserProfile, related_name="r_passengers")
mid_destinations=models.ManyToMany(Destination, related_name="r_mid_destinations")
class Destination(models.Model):
name=models.CharField(max_length=30)
As you can see, each Ride has multiple mid_destination and multiple passengers. a Ride also has One driver and One final destination.
The Issue is - when a User adds a Ride, I want the driver, destination and mid_destinations and the rest of the fields to be set by the User (the driver is user adding the Ride), Except for the passengers field. I want the other Users to add themselves to the ride, so when the Ride is created the User (driver) doesn't have to set the passengers.
How do I go about it? and also, any other suggestions about the models?
There is no such thing as a OneToManyField.
It doesn't matter from a practical point of view which side the ManyToManyField lives on. Personally, I'd put it on Ride, both to avoid changing the User model and because conceptually I'd say that rides are the main objects here.
And yes, adding the field will automatically create the linking table.
what you want is probably something like this
class MyModel(models.Model):
driver = models.ForeignKey(to=User, related_name='r_driver')
# you need to use a related name if you want to link to the same model more than once
passengers = models.ManyToManyField(User, related_name="r_passengers")

Django models with variable number of fields

I'm working on a new project and I'd like to create a django model that will have a variable number of EmailFields depending on another variable. What I'm trying to create is a House model that has all the members of the house in it (more specifically, their email addresses). Seeing as not all houses are the same size some will have more members than others.
I'd like the user to enter the number of members in their house and have django create an according number of EmailFields on the model. Is there any easy way to accomplish this? Thanks.
Because Django's model fields are directly linked to fields in a table in the database, a variable number of fields isn't possible. Instead, have another table with a foreign key:
class House(models.Model):
# normal house fields go here
class EmailAddress(models.Model):
email = models.EmailField()
house = models.ForeignKey(House, related_name='email_addresses')
Now you can access all the emails related to a house by using:
house = House.objects.get(pk=1)
house.email_addresses.all()
The ForeignKey documentation might be useful.
No. Put the emails in a separate model and link them back to House with a ForeignKey.

Django - can you explain this?

I have three models:
System_Contact
System
Contact_list
The Contact_List model has two fields: contact and sys and, not surprisingly, is just a manyToMany model to associate a list of contacts to each system. I have modelForm for adding a new contact to the system's list of contacts:
class Add_Contact_Form(ModelForm):
class Meta:
model = Contact_List
fields = ('contact',)
Simple, right? My confusion is this: Even thought the Contact_List model has many many duplicate contacts (because one contact can be associated with many systems) each contact is only displayed once within the form's Select widget.
Why?!
I mean, this is a great default behaviour for my purposes, but I want to make sure this is actually the correct default behaviour that I can rely on, not some random error I have done that just happens to work out for me now.
It's not that it's default behaviour, it's that the select widget in your contact_list form is displaying all of the entries that are from the contact table.
Every model is a table in the database, therefore you have 3 tables:
ContactTable - where every row in the table is a person
SystemTable - where every row in the table is a computer (for arguements sake)
ContactListTable - where every row is a mapping between a system and a list of users
If this is what you are trying to do, you should have the following:
class Contact(models.Model):
name = ...
class System(models.Model):
type = ...
class ContactList(models.MOdel):
system = models.ForeignKey(System)
contacts = models.ManyToManyField(Contact)
This means that every row in the ContactList table is a relationship between a particular machine from the system table and a list of contacts from the contact table

Setting up a weird model in django?

This may be difficult to explain.
I'm a little new to django and the whole idea of models.
Let's say I'm making an article app, where each article has a creator, but other users can edit the article at will. I'm having a little difficult on how to create the models for this.
Firstly,
I extend the user profile with the following:
class UserProfile(models.Model):
#Required field:
user = models.OneToOneField(User)
#Other Fields:
headline = models.CharField()
industry = models.CharField()
article= models.ForeignKey(articleModel.article)
Here is the first place I'm getting confused, do I put the foreignkey field in the user model? My reasoning for it being placed here is because each article can have many editors.
Now here is my article model:
class article(models.Model):
#primary key is already true
creator = models.ForeignKey(userModel.UserProfile)
title = models.CharField()
text = models.TextField()
Over here, I put the ForeignKey field so it would relate back to the creator, because every article has a single creator. (As a side note, I do want to make it so an article can have multiple creators, but I don't know what to do in this scenario).
I'm finding it a bit odd that the UserProfile model is referencing the article model, and the article is referencing it back. Can someone please help me unjumble my brain?
Thank you.
:)
As simple as possible
from django.db.models import *
from django.contrib.admin.models import User
# UserProfile should be provided by django-profiles
class UserProfile(User): # Subclassing user creates an automatic 1-1 called user
headline = CharField()
industry = CharField()
class Article(Model):
# ALWAYS primary key to User, not UserProfile
creator = ForeignKey(User, related_name='articles_created')
contributors = ManyToManyField(User, related_name='articles_edited')
created = DateTime(auto_now_add=True)
modified = DateTimeField(auto_now=True)
title = CharField()
text = TextField()
class Meta:
order = ['created', 'title']
fun stuff:
creator = Article.objects.all()[:1][0].creator.getUserProfile().headline
considder using django-versions if you want to keep track of edits.
class Article(VersionedModel)
EDIT: actually subclasses user
Nothing "weird" here. This is no such a django problem than a database structure problem. You need to read about 1 to 1, 1 to n and n to n relationships between tables.
Do you really need to record all editors of an article ? An article has many editors, and a user can edit many articles, so this is a many to many relationship. Here's how do do it in django.
Perhaps another field in your article model for last editor would provide you with the information you need.
lastEditor = models.ForeignKey(userModel.UserProfile)
If you really want to keep all editors you will need to implement another model which records something like: article_id, editor and edit time (maybe even the article text if you are interested in changes). You could then query this medel based on the current article to obtain a list of all editors.
you could do the same with: article_id and creator to obtain a list of creators of an article (this would replace the article field in your UserProfile class)