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")
Related
Disclaimer: I'm new to Django, so I'm still learning the Django way of doing things.
The project I'm working on has a uUser model and a Student model. Previously, the UserAdmin was doing double duty for both models, but now the time has come to create an independent StudentAdmin that allows admins to easily edit/create/etc students.
User contains base info for Student (i.e. first and last name, email, phone, etc.) and Student contains more info (i.e. parent phone, class, todos, etc.). Related models like 'Class', 'Grade', etc. have FK relationships to User, which at first didn't strike me as an issue.
But when I went to reuse the inline classes created for UserAdmin in the new StudentAdmin, I've run into this error: <class 'my_project.admin.TodoInline'>: (admin.E202) 'my_project.Todo' has no ForeignKey to 'my_project.Student. This isn't surprising, so I thought I could merely override the _init_ method on TodoInline to use parent_model.user, but then I ran into errors relating to ForwardOneToOneDescriptor and missing _meta fields. Given this use case, I believe there has to be a solution to this, but I'm currently at a loss for Django-related vocabulary for researching this issue further.
class TodoInline(admin.TabularInline):
model = Todo
fields = ['content', 'completed', 'category', 'due_date']
verbose_name_plural = "To-do's"
extra = 0
# This doesn't work:
def __int__(self, parent_model, admin_site):
super(TodoInline, self).__init__(parent_model.user, admin_site)
If the answer to this issue is to redefine the FK relationships between models, that's something I can't do at the moment. I need a solution that will allow me to reorient the inline classes (TodoInline is just one of many that I need for StudentAdmin) to use the related User model on the Student model. Thank you in advance!
Despite of your restriction not to reconfigure your foreign key, I see only one possible solution with two different modellings here.
But first of all: If you get the error, a foreign key to your model student is required, why can't you reconfigure that foreign key?
Second: You want to access the parentmodel of student and you've got an foreign key to the model user. From a modelling point of view I wonder, how that is useful - as you want to operate with a student, not with a user? Additionally, if your studentis related to user you can access all userattributes through student. So there is really no point in avoiding the reconfiguration of your foreign key.
So the only two possible (and meaningful) modellings I see are:
(1) Let the model student inherit from user, so student has all field's and methods which are implemented to user. Then reconfigure the foreign key to student (which requires $ python manage.py makemigrations <app> and $ python manage.py migrate <app>)
or
(2)
Define a one-to-one relation between student and user, so a student is uniquely to a user. This also requires to reconfigure your foreign key as describbed in (1).
If student does not differ from user there is an (3) option: Proxy models. With proxy models you can implement multiple modelAdmin for one model.
In Django, I want to filter a QuerySet using a list of Users who the active user is following.
I've opted to extend the User class rather than replace it with a custom class, although I'm not sure that was the right choice.
Hence what I have is a UserProfile class, which has a ManyToManyField to other UserProfiles, and a OneToOneField with User.
My QuerySet looks like Entry.objects.filter(author__in=request.user.userprofile.following.all()) but author is a ForeignKeyField to User rather than UserProfile, so I'm about to change Entry.author to point to UserProfiles instead.
So my questions are, in decreasing priority:
Is it right to have author be a UserProfile instead? Because then I have something like entry.author.user.username which is not intuitive.
Might it be better to just replace the builtin User class with a custom class which has the data I need?
Is it right for UserProfile's following to be a ManyToManyField to other UserProfile rather than to User?
I don't recommend this at all. As you said it's not intuitive, an
author should be a user.
No, a one to one relationship to user is better than creating a custom user class.
I think it will look better if you connect followings to users. This way your original query will also work.
In UserProfile model:
following = models.ManyToManyField(User, related_name="followed_by")
In this scenario user.followed_by is a list of UserProfiles, but user.userprofile.following is a list of users.
Since your users can follow each other and Entries are from those people, it makes totally sense to make the author UserProfile so that both models are logically in the same level
I have a model named Exam. each Exam has a set of users called participants. The only way I found to keep such set in Django is to add a field in User model. But I'd prefer to write this model to be as independent as possible so if later I want to use it again I can do it without changing my User model. So How can I handle having such set without manually modifying the User model fields?
Regarding your comment here is what you could do something like this:
class Exam(models.Model):
participants = models.ManyToMany(settings.AUTH_USER_MODEL, through='Participation')
class Participation(models.Model)
user = models.OneToOneField(settings.AUTH_USER_MODEL)
exam = models.ForeignKey('Exam')
active = models.BooleanField(default=False)
Another option would be to use Django's limit_coices_to. It's not transaction-save, but might do the job. You would just limit to choices to all non-related objects.
I wanted to get a list of objects associated to model A by ManyToMany with model B, e.g. diners (A) confirmed to attend a meal(B). But I'm not sure what getter I should use. I actually wanted to do this to show the associated objects in the admin panel. The method included beneath was one failed attempt I made.
class Meal(models.Model):
diners = models.ManyToManyField(User, through='Attendance', related_name="eating", blank=True)
def diners(self):
return self.eating
Can you help?
Thanks
As ilvar suggested, remove diners method and use self.diners.all() to get objects inside Meal methods. related_name='eating' is for fetching attended meals of a user, reversely.
I arrived at this page with the same problem as OP. I ended up simply removing the reference to the ManyToMany field in list_display in my admin model. The result: on the admin page for that app, under the ManyToMany field name, appeared a nicely formatted multi-selection list widget with the possible values for my ManyToMany relationship shown.
So the solution was to remove the reference in list_display and let Django handle it. This is with Django 1.4.3.
How do I travel through multiple foreign keys in Django? I've tried everything I can think of from the django docs, but I'm obviously missed something (extreme newbie). I have models for scientists, experiments, and theories.
If I want to look at a particular Theory (let's call it 'relativity') and get a list of all of the emails of scientists working on it (kept in the normal django user model), how do I do this?
class Experiment(models.Model)
experimenter = models.ForeignKey(Scientist)
theory = models.ForeignKey(Theory)
class Theory(models.Model)
name = models.CharField(max_length=100)
class Scientist(models.Model)
user = models.ForeignKey(User, unique=True)
institution = models.CharField(max_length=20, null=True, blank=True)
These are simplified versions of my models that I rewrote, so there are probably some errors in it, but the relationships are correct.
I've tried every kind of combinations of select_related(), get(), filter() but can't figure it out. Thanks in advance for your help!
User.objects.filter(scientist__experiment__theory__name=u'relativity')
Take a look at the Django documentation section about Lookups that span relationships. The net takeaway is:
To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
Ignacio's answer shows an example of using the double underscores on field names to span a relationship.
The other relevant portion of Django's documentation would be the Related objects section. Relationships in Django are asymmetrical in the way they are accessed. Forward/normal relationships are accessed as attributes of the models. Backward relationships are accessed:
Django also creates API accessors for the "other" side of the relationship -- the link from the related model to the model that defines the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all().