Django using reverse OneToOne in filter? - django

I have two models:
class CustomUser(models.Model):
...
class Profile(models.Model):
user = models.models.OneToOneField(CustomUser)
fielda = models.IntegerField()
I'm trying to perform a filter query based on the value of a field on the Profile model from the CustomUser model but it's giving me the error name 'profile' is not defined
CustomUser.objects.all().select_related('profile').filter(profile.fielda=0)
I need to start the selection from CustomUser model because I have to prefetch other models with FK to CustomUser so I cannot simply start from Profile model

One uses two consecutive underscores (__) to look "through" a relation, so you can filter with:
CustomUser.objects.filter(profile__fielda=0)
The above will thus retrieve all CustomUsers with a related Profile object where fielda is 0.
Note that the .select_related(..) is not necessary for filtering. This is only used if you want to fetch the data into memory as well.

Related

ManyToMany Field on Django Admin Interface

On Django Rest, I have a many to many relation for a field of material list. Instances of materials are added in a loan model. It works, to add through the admin site but the display is disintuitive: Instances are mixed with materials (instances are in parenthesis).
It's possible to have to separated list ? One to select materials and one other to add/remove instances linked to materials ?
The name that it shows in the list are the results of the __str__ method on your model. So if you want to display something else, you can alter the __str__ method. For example if this is a model Material with a name field, you can set it to:
class Material(models.Model):
name = models.CharField(max_length=128, unique=True)
def __str__(self):
return self.name
You can set the filter_horizontal attribute [Django-doc]:
from django.contrib import admin
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
# …
filter_horizontal = ('materials_field_name',)
this thus will use a widget with two lists where you can move to the right and the left.

How i can get items from a model that are not used in ManyToMany relationship?

I have a Django model (ModelA) with a ManyToManyField linking to another model (ModelB) like this:
class ModelA (models.Model):
field = models.ManyToManyField('ModelB',blank=True )
class ModelB (models.Model):
....
How can I get all objects form ModelB that are not used in ManyToManyField relationship?
Just filter all the objects of ModelB where ModelA is None:
queryset = ModelB.objects.filter(modela=None)
when we use ManyToManyField a third table is automatically created after migration...
which will be 'yourappnameModelAModelB' use this table name in your query.... and dont forget to replace yourappname mentioned with table name

Django models: database design for user and follower

In Django model I am making a table 'followers', which has:
user's id. (this is followed by)
user's id (this is follower)
that's simple a user can follow other users.
How should I define the model in Django?
I tried this, but does not work:
user = models.ForeignKey('self')
follower_id = models.ForeignKey('self')
How should this be done?
thanks
The 'self' argument won't work unless you have a model called self.
Assuming that your assignment model is called Following, and you're using the built in User model then you can do:
class Following(models.Model):
target = models.ForeignKey('User', related_name='followers')
follower = models.ForeignKey('User', related_name='targets')
This will likely need some further uniqueness and validation logic.
Note the related_name attribute, see https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.ForeignKey.related_name. This means that for a given user object you can do user.targets.all() to get users they follow, and user.followers.all() to get users who follow them.
Note also that Django returns target model instances, not IDs, in the ORM. This means that even though the underlying table may be called follower_id, in the python code following.follower will return an actual User object.
Seeing as Following is actually the through table for the many-to-many relationship between Users. I would create a Profile model which extends the Django User model, and then declare the many-to-many relationship (using ManyToManyField).
from django.contrib.auth.models import User
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
following = models.ManyToManyField(User, related_name='followers')
Use the many to many field.
followers = models.ManyToManyField('self', symmetrical=False)

Django using a ManytoMany as a Foreign Key

I'm trying to use a many to many relation as a foreign key for another table, but I'm not sure if this is possible.Consider the following model:
from django.db import models
class Attribute(models.Model):
name=models.CharField(max_length=30)
unit=models.CharField(max_length=30)
class Protocol(models.Model):
name=models.CharField(max_length=30)
attributes=models.ManyToManyField(Attribute,db_table='protocol_attribute')
class Device(models.Model):
serial_number = models.CharField(max_length=30)
id_protocol=models.ForeignKey(Protocol)
class DeviceValues(models.Model):
id_device=models.ForeignKey(Device)
id_protocol_attribute=models.ForeignKey(Protocol.attributes)
value=models.IntegerField()
When I try to validate this model I receive the following error:
First parameter to ForeignKey must be either a model, a model name, or the string 'self'
I know I am not using a model or a model name as the first parameter, but how can I reference as a foreign key the join table that Django will automatically create that handles the mapping between Protocol and Attributes?
A possible workaround could be to add the protocol as a foreign key to the Attribute class and then use the attribute as a foreing key to the DeviceValue class. However, I don't want to do that because I will have protocols that will be sharing attributes. I would prefer to make the join table rather that repeating attributes for each protocol.
Any ideas will be more than welcome....thanks!!!
Alejandro
Using an intermediate table, I solved it. The model ended up like this.
from django.db import models
class Attribute(models.Model):
name=models.CharField(max_length=30)
unit=models.CharField(max_length=30)
class Protocol(models.Model):
name=models.CharField(max_length=30)
attributes=models.ManyToManyField(Attribute,through='DeviceValue')
class Device(models.Model):
serial_number = models.CharField(max_length=30)
id_protocol=models.ForeignKey(Protocol)
class DeviceValue(models.Model):
id_name=models.ForeignKey(Protocol)
id_attribute=models.ForeignKey(Attribute)
id_device=models.ForeignKey(Device)
value=models.IntegerField()
One thing worth mention is that when using sqlall the UNIQUE constraint for the three foreign keys of the DeviceValue tablue was not generated, so I just added it before creating the database.

Django get the value of foreignId from django.contrib.auth.models User

I have created a model which has foreign key to the django.contrib.auth.models User model. I need to retrieve the value the foreign key is referring to. But how to do that?
E.g. my model is
from django.contrib.auth.models import User
def FooModel(models.Model):
user = models.ForeignKey(User)
then I know I can either use:
FooModel.objects.get() or FooModel.objects.filter() but as far as I know they will only return entries from the FooModel only. So how do I retrieve from the User model?
m = FooModel.objects.get(id=123434)
m.user.username
You can use ..That wxample will return you the username of the related user. Also you can create joins using __ on the query filtering. Like:
FooModel.objects.get(user__username='Foo')
But, since you are building your query on FooModel, you will always get FooModel results. So you have you use . to use foreignkey relations to get to the required User field.
EDIT:
Django also allows you to use reverse relations on querysets, so even though User model do not have a foreignkey to FooModel on its model structure, you can use reverse relation of Foomodel.user foreignkey like:
def FooModel(models.Model):
user = models.ForeignKey(User)
foofield = Models.CharField(...)
User.objects.get(foomodel__foofield='Beatles')
will return you the user which have FooModel record with a foreign key to his User record and foofield value of Beatles
You can access foreign key ids by referencing the property name + _id. For example: yourmodel.user_id