Django : Multiple possible types in ForeignKey Field - sql

I want to model the following relationship where the Vehicle owner field could be either a Person or a Company. How can we do that in Django?
class Person(models.Model):
name = ...
other_details = ...
class Company(models.Model):
name = ...
other_details = ...
class Vehicle(models.Model):
owner = models.ForeignKey(x) # 'x' could be a Person or Company

Use Generic foreign key
ex.
class Vehicle(models.Model):
content_type = models.ForeignKey(ContentType, null=True, blank=True)
object_id = models.PositiveIntegerField(null=True, blank=True)
content_object = generic.GenericForeignKey('content_type', 'object_id')
while saving the object you need to get the content_type of the model to which you want to give generic FK and object id of that model.
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get_for_model(Company)
object_id = company_object.id
ve = Vehicle()
ve.content_type = content_type
ve.object_id = object_id
ve.save()
hope this will help you.

Related

SQL Query logic to Django ORM Query logic

I have tried to think about how the following SQL query would be structured as a Django ORM query but I have had no luck in my multiple attempts. Can anyone help?
SELECT targets_genetarget.gene, count(targets_targetprediction.gene) as total
FROM targets_genetarget
LEFT OUTER JOIN targets_targetprediction on targets_targetprediction.gene =
targets_genetarget.gene
WHERE list_name LIKE %s
GROUP BY targets_genetarget.gene
class GeneTarget(models.Model):
list_name = models.CharField(max_length=100)
gene = models.CharField(max_length=50)
date_added = models.DateField(auto_now=True)
class Meta:
unique_together = (('list_name', 'gene'),)
def __str__(self):
return self.list_name
class TargetPrediction(models.Model):
specimen_id = models.CharField(max_length=100)
patient_peptide = models.ForeignKey(Peptide, on_delete=models.CASCADE, verbose_name="Peptide", related_name="predictions")
allele = models.ForeignKey(Allele, on_delete=models.CASCADE, verbose_name="Allele", related_name="predictions")
gene = models.CharField(max_length=50)
class Meta:
unique_together = (('specimen_id', 'patient_peptide', 'allele', 'gene'),)
def get_absolute_url(self):
return f'/samples/specid-{self.specimen_id}'
def __str__(self):
return (f'Specimen: {self.specimen_id} Peptide: {self.patient_peptide} Allele: {self.allele} Gene: {self.gene} ')
There's nothing stopping you declaring the TargetPrediction.gene field as a foreign key using the to_field attribute, so you wouldn't need to change the data at all:
class TargetPrediction(models.Model):
...
gene = models.ForeignKey("GeneTarget", to_field="gene")
Now your query simply becomes:
GeneTarget.objects.filter(list_name="whatever").values("gene").annotate(total=Count("targetprediction"))

Querying GenericRelation field DJango

models.py
class Contact(models.Model):
attributes = GenericRelation(
AttributeValue,related_query_name='contact',content_type_field='target_content_type',object_id_field='target_object_id')
class AttributeValue(models.Model):
attribute = models.ForeignKey(Attribute, related_name="attribute")
# the object instance we are associating this attribute to
target_content_type = models.ForeignKey(ContentType, related_name="attribute_value_target_content_type",
on_delete=models.CASCADE, blank=True, null=True)
target_object_id = models.PositiveIntegerField(blank=True, null=True, db_index=True)
target = GenericForeignKey('target_content_type', 'target_object_id')
class Attribute(models.Model):
name = CHarFIeld()
I want to get all the contacts that follow both the conditions below
Have an AttributeValue model object in attributes field with
attributes__attribute__name = 'crop_name' and
attributes__value='groundnut'
Have an AttributeValue model object in attributes field with attributes__attribute__name = 'crop_season' and attributes__value='winter'
One way to achieve this is mentioned as follows:
Contact.objects.all().filter(Q(attributes__attribute__name='crop_name') & Q(attributes__value='groundnut')).filter(Q(attributes__attribute__name='crop_season') & Q(attributes__value='winter'))
The above mentioned query works fine. But I want to construct a single such query that can be given into .filter()
i.e. something like
Contact.objects.filter(query)
I tried doing something like
Contact.objects.filter(Q(Q(attributes__attribute__name='crop_name') & Q(attributes__value='groundnut'))& Q(Q(attributes__attribute__name='crop_season') & Q(attributes__value='winter')))
Expecting that query would respect the braces, but it doesn't like that i guess
P.S. I am using django(1.11.4) + postgres(9.5.7) combination

Django Rest Framework - Could not resolve URL for hyperlinked relationship using view name "field-detail"

I know that this inconvenient is very presented, may be that I need learn more about of serializer relationships
I have the following model:
class Field(models.Model):
FIELD_TYPE_NATURE = 'Grama natural'
FIELD_TYPE_ARTIFICIAL = 'Grama sintetica'
FIELD_TYPE_CHOICES = (
(FIELD_TYPE_NATURE, u'Grama natural'),
(FIELD_TYPE_ARTIFICIAL, u'Grama sintetica'),
)
MODALITY_11 = 'Fútbol 11'
MODALITY_8 = 'Fútbol 8'
MODALITY_CHOICES = (
(MODALITY_11, u'Fútbol 11'),
(MODALITY_8, u'Fútbol 8'),
)
name = models.CharField(
max_length=150,
unique=True,
db_index=True,
primary_key=True,
)
field_type = models.CharField(
choices=FIELD_TYPE_CHOICES,
default=False,
blank=False,
max_length=20,
verbose_name=('Tipo de material/grama de la cancha')
)
modality = models.CharField(
max_length=40,
blank=False,
verbose_name='Modalidad'
)
photo = models.ImageField(upload_to='fields', blank=True, null=True)
location = models.CharField(max_length=150, blank=False)
def __str__(self):
return '%s %s %s' % (self.name, self.field_type, self.location)
My serializer is the following:
class FieldSerializer(serializers.HyperlinkedModelSerializer):
#url = serializers.HyperlinkedIdentityField(view_name='field-detail',)
class Meta:
model = Field
fields = ('url', 'name','field_type','modality','photo','location')
My viewset is:
class FieldViewSet(viewsets.ModelViewSet):
queryset = Field.objects.all()
serializer_class = FieldSerializer
This is my router:
router = routers.DefaultRouter()
router.register(r'fields', FieldViewSet)
And my url:
...
url(r'^api/', include(router.urls)),
...
When I go to the http://localhost:8000/api/fields/ url I get the following message:
File "/home/bgarcial/.virtualenvs/fuupbol2/lib/python3.5/site-packages/rest_framework/relations.py", line 386, in to_representation
raise ImproperlyConfigured(msg % self.view_name)
django.core.exceptions.ImproperlyConfigured: Could not resolve URL for **hyperlinked relationship using view name "field-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.**
[11/Nov/2016 16:39:53] "GET /api/fields/ HTTP/1.1" 500 187477
When I use HyperlinkedIdentityField in my FieldSerializer class:
class FieldSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='field-detail',)
class Meta:
model = Field
fields = ('url', 'name','field_type','modality','photo','location')
I follow getting the same error.
Althought when I go to the url http://localhost:8000/api/fields/ I want get is a list of my objects, then is possible that I should put:
url = serializers.HyperlinkedIdentityField(view_name='field-list',)
?
I use HyperlinkedIdentityField according to:
This field can be applied as an identity relationship, such as the
'url' field on a HyperlinkedModelSerializer. It can also be used for
an attribute on the object.
I put the field-list in my view_name attribute and I get the error related
Could not resolve URL for hyperlinked relationship using view name "field-list". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
I don't understand the situations when I should use view_name attribute in relation to if I wnt get a list objects, a object detail and so ... although here explain something about it.
When I should use HyperlinkedModelSerializer and ModelSerializer

Unique if not null SQLAlchemy and Django

Given this simple table written in SQLAlchemy and Django models.py, how would I set UPC to be unique if not null. UPC won't be available for all items, but if is it should be unique.
class Products(base):
__tablename__ = u'products'
id = Column(Integer(), primary_key=True, autoincrement = True)
product_name = Column(String(), unique=True, nullable=False)
upc = Column(String(), nullable = True)
And
class Products(models.Model):
id = models.AutoField(primary_key=True)
product_name = models.TextField()
upc = models.TextField(null=True, blank=True)
Multiple rows with NULL values should not be a problem for the unique constraint. Only "values" must be unique, NULL is no value.
Have you tried?:
upc = Column(String(), unique=True, nullable=True)

Need some help accessing a ForeignKey row's data while performing a select with SQLAlchemy

Background Schema:
class Checkpoint(db.Model):
id = db.Column(db.Integer, primary_key=True)
creator = db.Column(db.Integer, db.ForeignKey('user.id'))
name = db.Column(db.String(255))
description = db.Column(db.String(255), nullable=True)
price = db.Column(db.Float, nullable=True)
expiry = db.Column(db.DateTime, nullable=True)
date_created = db.Column(db.DateTime)
type = db.Column(db.String(255))
image = db.Column(db.String(255))
longitude = db.Column(db.Float)
latitude = db.Column(db.Float)
class UserCheckpoint(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship("User")
checkpoint_id = db.Column(db.Integer, db.ForeignKey('checkpoint.id'))
checkpoint = db.relationship("Checkpoint")
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255))
facebook_info = db.Column(db.String(255), db.ForeignKey('facebook_user.id'))
facebook_user = db.relationship("FacebookUser")
class FriendConnection(db.Model):
id = db.Column(db.Integer, primary_key=True)
fb_user_from = db.Column(db.String(255), db.ForeignKey('facebook_user.id'))
fb_user_to = db.Column(db.String(255), db.ForeignKey('facebook_user.id'))
class FacebookUser(db.Model):
id = db.Column(db.String(255), primary_key=True)
name = db.Column(db.String(255))
first_name = db.Column(db.String(255), nullable=True)
middle_name = db.Column(db.String(255), nullable=True)
last_name = db.Column(db.String(255), nullable=True)
gender = db.Column(db.String(255), nullable=True)
username = db.Column(db.String(255), nullable=True)
link = db.Column(db.String(255), nullable=True)
I have a user, and as you can see, each user has a Facebook profile, as well as a table depicting inter-facebook-profile friendships. So given the user, the user would have a list of Facebook friends. I would like to get all UserCheckpoints that belong either to the user or his friends, with a given Checkpoint condition:
coord_conditions = and_(Checkpoint.longitude <= longitude + exp_no,
Checkpoint.longitude >= longitude - exp_no,
Checkpoint.latitude <= latitude + exp_no,
Checkpoint.latitude >= latitude - exp_no,
)
How can I do this using the ORM from SQLAlchemy? Thanks!
Summary: How to select UserCheckpoints given that the user_id belong to a list of friends/self; while UserCheckpoint.checkpoint has a set of conditions to fulfill.
Each relation has two methods to defined conditions on related objects: .has() for single referred object and .any() for collections. These methods allow straightforward translation of your task to SQLAlchemy expression. Let's add missing relations to FacebookUser:
class FacebookUser(Model):
# Definitions from question are here
user = relationship(User, uselist=False)
friends = relationship('FacebookUser',
secondary=FriendConnection.__table__,
primaryjoin=(id==FriendConnection.fb_user_from),
secondaryjoin=(FriendConnection.fb_user_to==id))
I've defined FacebookUser.user assuming one-to-one relation (which is usually supplemented with unique constraint on the foreign key column). Just remove uselist=False and adjust name if you allow several users being connected to one facebook account.
A shorter definition of your condition for coordinates:
coord_conditions = Checkpoint.longitude.between(longitude - exp_no,
longitude + exp_no) & \
Checkpoint.latitude.between(latitude - exp_no,
latitude + exp_no)
This condition is definitely wrong even for approximation (-179.9° and 179.9° are very close, while the difference is huge), but this is not main topic of the question.
A condition for users of interest (user with id equal to user_id and his friends):
user_cond = (User.id==user_id) | \
User.facebook_user.has(
FacebookUser.friends.any(FacebookUser.user.has(id=user_id)))
Now the query is quite simple:
session.query(UserCheckpoint).filter(
UserCheckpoint.checkpoint.has(coord_conditions) & \
UserCheckpoint.user.has(user_cond))
Unless you have (or expect) performance issues, I'd suggest avoid optimizing it at the cost of readability.
Basically your query can be split in two parts:
Given the user_id, create a list of users which will contain the user herself as well as all direct friends
Given the list of users from 1., get all UserCheckpoint whose Checkpoint would satisfy the criteria.
Not tested code:
# get direct user for given user_id
u1 = (session.query(User.id.label("user_1_id"), User.id.label("user_id"))
)
# get friends of the user in one direction (from other user to this one)
User2 = aliased(User)
FacebookUser2 = aliased(FacebookUser)
u2 = (session.query(User2.id.label("user_1_id"), User.id.label("user_id")).
join(FacebookUser2, User2.facebook_info == FacebookUser2.id).
join(FriendConnection, FacebookUser2.id == FriendConnection.fb_user_from).
join(FacebookUser, FacebookUser.id == FriendConnection.fb_user_to).
join(User, User.facebook_info == FacebookUser.id)
)
# get friends of the user in other direction (from this user to the other)
User2 = aliased(User)
FacebookUser2 = aliased(FacebookUser)
u3 = (session.query(User2.id.label("user_1_id"), User.id.label("user_id")).
join(FacebookUser2, User2.facebook_info == FacebookUser2.id).
join(FriendConnection, FacebookUser2.id == FriendConnection.fb_user_to).
join(FacebookUser, FacebookUser.id == FriendConnection.fb_user_from).
join(User, User.facebook_info == FacebookUser.id)
)
# create a union to have all pairs (me_or_friend_id, user_id)
u_all = union_all(u1, u2, u3)
# **edit-1: added alias **
u_all = u_all.alias("user_list_view")
# final query which adds filters requirested (by user_id and the checkpoint condition)
q = (session.query(UserCheckpoint).
join(Checkpoint).filter(coord_conditions).
join(u_all, UserCheckpoint.user_id == u_all.c.user_1_id).
filter(u_all.c.user_id == user_id)
)
for u_cp in q.all():
print u_cp
Note, that you could simplify the query somewhat if you defined more relationships in your model and then can remove some primaryjoin conditions from join clauses.