Can I save a query set for django manytomayfield - django

I have a model suppose
class A(models.Model):
name = models.CharField(max_length=256)
class B(models.Model):
city = models.CharField(max_length=256)
users = models.ManyToManyField(A)
Now can I say if I have to save these models I can use
users = A.objects.all()
and suppose I have a data for to store as
b = B(city="XYZ", user=users).save()
that is can I use directly the complete query set to store the manytomany field data.

You can't pass a many-to-many field when you instantiate a model, in any case.
After the model is saved, though, you can do:
b.users.add(*users)

Related

Preload FK relation in different column Django

I have Django models that looks like this
class Customer(models.Model):
name = models.CharField(_("Name"))
class Feature(models.Model):
label = models.CharField(_("Name"))
class AddOn(models.Model):
customer = models.ForeignKey(Customer)
feature = models.ForeignKey(Feature)
Given that I have an instance of Customer e.g
customer = Customer.objects.get(pk=1)
How do I get all the labels in feature in one query to avoid N+1 query?
For now what I've done is:
[addon.feature.label for addon in self.addon_set.all()]
But I think for each addon.feature will create a query that is not very optimized if there is a lot of addon
You can use values/values_list to get all labels in a single query
self.addon_set.values_list('feature__label', flat=True)
EDIT: Example of the ManyToManyField
class Customer(models.Model):
name = models.CharField(_("Name"))
features = ManyToManyField('Feature', through='AddOn')
class Feature(models.Model):
label = models.CharField(_("Name"))
class AddOn(models.Model):
customer = models.ForeignKey(Customer)
feature = models.ForeignKey(Feature)
You can then perform queries like customer_obj.features.all() or feature_obj.customers.all() and it won't affect your ability to still query the AddOn model

how to optimize the query here with select_related?

i have
class A(models.Model):
field_a = models.OneToOneField(B, on_delete=models.CASCADE)
class B(models.Model):
field_b = models.charField()
how to write the most optimum query here using select_related or something else?
In my use case i need to use both, field_a of model A and field_b of model B somewhere in my code. So can i fetch both the objects in one db hit?
queryset_b = B.objects.get(field_b="some name")
queryset_a = A.objects.get(b=queryset_b).field_a
field_a_of_model = queryset_a
field_b_of_model = queryset_b.field_b
# then some manipulation with both fields
it hits the db twice. Can i do this thing in one db hit using select_related so that it fetches both object at once?
You could use lookup that span relationship
a = A.objects.get(b__field_b="some name")
This would result in single query to database
If you want single query to access fields from b too use select_related()
a = A.objects.select_related().get(b__field_b="some name")
a.field_a.field_b

Django model A can has only one instance of model B

I have two models:
class ModelA(models.Model):
name = models.CharField(max_length=256)
class ModelB(models.Model):
user = models.ForeignKey(MyUser)
model_a = models.ForeignKey(ModelA)
points = models.IntegerField(default=0)
How can I prevent creating the same object? For example:
I have A, B, C instances of ModelA, and two users. In ModelB I need relationships like this:
User1 can has only one 'link' to A, one to B, etc.
User2 the same. He can only one 'link' to each ModelA instance.
Each User can has one record in ModelB associated with ModelA.
E.g. (User1, A, 100), (User2, A, 50)
But if I will try to do something like this
...create(user=User1, model_a=A, points=50)
I need to get from db records with user1, and A, and ad points, not creating another similiar model.
So you want all pairs of user and model_a to be unique. You can specify this in the metadata of the model using unique_together.
unique_together = (("driver", "restaurant"),)
This is a tuple of tuples that must be unique when
considered together. It’s used in the Django admin and is enforced at
the database level (i.e., the appropriate UNIQUE statements are
included in the CREATE TABLE statement).
Django documentation - unique_together
Therefore modify your model in following way:
class ModelB(models.Model):
user = models.ForeignKey(MyUser)
model_a = models.ForeignKey(ModelA)
points = models.IntegerField(default=0)
class Meta:
unique_together = (('user', 'model_a'),)

django manytomany through

If I have two Models that have a manytomany relationship with a through model, how do I get data from that 'through' table.
class Bike(models.Model):
nickname = models.CharField(max_length=40)
users = models.ManyToManyField(User, through='bike.BikeUser')
The BikeUser class
class BikeUser(models.Model):
bike = models.ForeignKey(Bike)
user = models.ForeignKey(User)
comment = models.CharField(max_length=140)
And I would add a user to that bike (presuming I have a myBike and a myUser already)
BikeUser.objects.create(bike = myBike, user = myUser, comment = 'Got this one at a fancy store')
I can get all the users on 'myBike' with myBike.users.all() but how do I get the 'comment' property?
I would like to do something like
for myBikeUser in myBike.users.all():
print myBikeUser.comment
The through table is linked by standard ForeignKeys, so you do a normal ForeignKey lookup. Don't forget that there's a comment for each bikeuser, ie one for each bike/user pairing.
for myBikeUser in myBike.bikeuser_set.all():
print myBikeUser.comment, myBikeUser.user.first_name

Is it possible to instruct Django to save a model instance to a particular table based on its fields?

I'm attempting to construct a Django application that models an existing set of tables. These tables all have the same fields, plus custom fields per table. What I'm wanting to do is model this structure, and have records save to a particular table based on what table model they are attached to.
These tables can be created quite often, so it is unfeasible to construct new models per table.
Perhaps the code will demonstrate what I'm trying to do more clearly:
class CustomField(models.Model):
column_name = models.CharField(max_length=100)
description = models.CharField(max_length=255, blank=True, null=True)
class CustomData(models.Model):
custom_field = models.ForeignKey(CustomField)
value = models.CharField(max_length=100, blank=True, null=True)
# value will always be a nullable varchar(100)
class Table(models.Model):
table_name = models.CharField(max_length=255)
name = models.CharField(max_length=100)
custom_fields = models.ManyToManyField(CustomField)
class Record(models.Model):
table = models.ForeignKey(Table)
... list of common fields omitted ...
custom_values = models.ManyToManyField(CustomData)
When saving a new record that has a foreign key to 'table_1', I would like the eventual operation to be along the lines of insert into table_1 (..fields..) values (..field values..)
Is this possible? I guess I could hook into signals or the save method, but I'd like to find the simplest approach if such exists.
You can create unmanaged models dynamically. You just need to create a dict mapping column names to the data values. Once you have that, you can do the following:
from django.db import models
# This is the dict you created, mapping column names to values
values = {col_1: value_1, col_2: value_2, col_3: value_3, ... }
# Create a dict defining the custom field types, eg {col_name: django_field}
attrs = dict((c, models.CharField(max_length=100, blank=True, null=True)) for c in values)
# Add a Meta class to define the table name, eg table_1
class Meta:
app_label = myapp
db_table = 'table_1'
managed = False
attrs['Meta'] = Meta
attrs['__module__'] = 'path.to.your.apps.module'
DynamicModel = type('MyModel', (models.Model,), attrs)
# Save your data
DynamicModel.objects.create(**values)
Wrap this up in a function, and put it in your .save() method on Record. If you have any common fields, you can add them to attrs, or even better: create an abstract model with all the common fields and inherit that in the last line above instead of models.Model.