A version of this question has been asked here several times but none of the answers provided solve my exact problem.
I'm trying to bulk_create a batch of objects of a model with a ManyToMany field.
In this case, the ManyToMany field refers to the same model, though I'd also be interested in the general case.
Let's say this is my model:
class Person(models.Model):
name = models.CharField(max_length=20, blank=True, null=True)
friends = models.ManyToMany("self", related_name="friends_with", null=True)
After bulk_creating a large number of Person objects, I want to add the information who's friends with whom within this group.
Is there a more efficient way to go about this than looping through each new Person and calling .set(friend_pks) or .add(*friend_pks)?
I.e., an analogue of bulk_update.
I've achieved some speed-up by wrapping the loop into with transaction.atomic() (from this answer) but it's still quite slow.
Okay, my post was premature -- it seems that this answers the question.
The key is to bulk_create the through models. In this example:
friends_relation_1 = Person.friends.through(from_person_id=1, to_person_id=2)
friends_relation_2 = Person.friends.through(from_person_id=2, to_person_id=8)
Person.friends.through.objects.bulk_create([friends_relation_1, friends_relation_2, ...])
Related
I've been reading through the Django documentation and looking over some of the other answers on the site for a couple of hours now, yet I still can't get it to sink in. I know this isn't Django specific, but the examples I use will be from a Django project.
My question boils down to when is it appropriate to use each:
Many-to-many relationships
Many-to-one relationships
One-to-one relationships
One-to-one, more or less makes sense to me.
Now for the other two. While I understand the differences between them in isolation, when it comes to using them practically in a project, I get confused. Here is an example:
class User(AbstractUser):
pass
class Listing(models.Model):
title = models.CharField(max_length=64)
description = models.TextField()
class Watchlist(models.Model):
user = models.ForeignKey(User, related_name='watchlist', on_delete=models.CASCADE)
item = models.ManyToManyField(Listing)
class Comment(models.Model):
user = models.ForeignKey(User, related_name='comments', on_delete=models.SET_NULL)
comment = models.TextField()
Would this be the correct use of Many-to-one(ForeignKey) and Many-to-many?
Should Watchlist.item be a ForeignKey? Or is M2M correct?
Wouldn't it simplify to make the 'Watchlist' part of the User class? (give them an empty list to populate with listing ID's)
Why is Watchlist.user not a One-to-one relationship, if each watchlist belongs to a single user, and a user can only have one list?
Apologies for my stupidity, I just can't get this to sink in!
Thank you.
edit: Context, the models are from a 'learning' project I was working on intended to be an auction site, similar to eBay. The watchlist is sort of a 'wish' list... for the user to watch an item, not for site to watch a user!
To explain it simply these django-models or objects represents tables in your database and the fields are like the columns in them. So with a one-to-one relation you can only have one row in one table relating to one row in another table. For example one user in the user table (represented by one row) can only relate to one row in a profile table. But your user can have many comments, so this would be a one-to-many/foreignkey relation (if you set unique=true on a fk, it will in practice function as 1:1). If the users can collaborate on writing comments, or for example as here on stackoverflow where users can edit other users comments, that would be a many-to-many relation.
Database design can be complicated/complex, especially using an ORM without basic knowledge of SQL and how it all works beneath. In general it requires a bit of planning even for a simple application.
my problem is the following. I have two models in the database, which I link together using a ManyToMany relationship. For the admin page I currently use "admin.TabularInline" to bind different objects to one via the graphic. I still want to specify an order in the connections, preferably numbers which represent an order for processing. A bit more figuratively described I have the model "Survey" and the model "SurveyQuestion". So I connect many SurveyQuestions with the Survey. But I can't specify an order, because I don't have an additional field for it. It is not known before how many questions will be in a survey. Nor is it known which questions will be inserted. Usually they are built during the compilation of the survey and may be used later for another survey. I am grateful for every tip!
This can be achieved by defining a custom relationship table between the Survey and SurveyQuestion using through argument. For example you can define a relationship model:
class Question(models.Model):
question = models.CharField(max_length=256)
class Survey(models.Model):
name = models.CharField(max_length=256)
questions = models.ManyToManyField(Questions, through='Questionnaire')
class Questionnaire(models.Model):
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
question_order = models.IntegerField()
The details and example can be found here:
https://docs.djangoproject.com/en/3.1/topics/db/models/#extra-fields-on-many-to-many-relationships. If you do not want to mess up with the models, then you have to find out some hack like was proposed by Ronak Muhta.
I'm looking for a nice way to query(DJANGO) temporal data, which is stored in different tables, but share the same model. Here's an example data model:
class myModel(models.Model):
x = models.FloatField()
class Meta:
db_table = "24-01-2017"
Now, I could of course loop over the different days, changing _meta.db_table for every iteration, but there should be a way to do this in a single query in DJANGO. This doesn't seem to be it, as DJANGO develops this may be outdated and I don't see anything related in the documentation.
How to handle this neatly?
Thanks in advance!
Edit 1
Hm, probably I'm just looking for a way to perform a outer join... But I can't find any implementation for this.
Small dilemma here; I want to allow users to create a list of tasks (via a model form) which will be stored in the database for them to read or update each of the fields in future (so to mark a task as completed for example).
In the model I've created something like this...
tasks_to_do = models.CharField(max_length=300, null=True)
However, I want users to be able to add as many or as few different tasks as they want. Should I do something like...
task_1 = models.CharField(max_length=100, null=True)
task_2 = models.CharField(max_length=100, null=True)
task_3 = models.CharField(max_length=100, null=True)
etc., which seems quite tedious/wasteful of code.
Or should I somehow try to store a series of strings as a list?
Apologies for the lack of code; very unsure about how to approach this problem as I haven't come across anything like this before.
Thanks in advance!
I think the easiest and the most obvious solution would be to to create two separate models - one for tasks list and another for a single task.
class TodoList(models.Model):
# you can put here some additional information, like the name of the list, when it was created etc.
class Task(models.Model):
todo_list = models.ForeignKey(TodoList)
# you can put extra info about the single task (the creator, date due etc.)
So everytime you want to add a new task to your list, you create another Task object with todo_list field's value set to TodoList object.
Or you can add it another way, using reverse relationship as described in docs
Its Django 1.7, I have User model with date_joined field. I have another related model Userprofile. Also, the database is already existing with few thousand entries already.
Now, i want to add this date_joined field to userprofile
date_joined = models.DateTimeField(auto_now_add=True, null=True)
And for the already existing rows in the Userprofile model, i want to put the value already there in the User model.
Although i can write a simple function to do this, I was curious if there is a simpler way to do that through models directly during creating that column only.
As you already know, date_joined is already present in your data - Django provides it by default. It sounds like you want to duplicate that existing data into your UserProfile instances. Duplicating data is never a good idea. It can go out of sync, you need to pepper your code with synchronization functions, etc. My advice is to NOT try to do what you're trying to do. Just utilize the existing data as needed. Django is giving you a "gimme" here and it sounds like you want to make things more complicated than they need to be. Remove date_joined from UserProfile.