Say I have a model Foo that needs to refer to a value that can be one of several datatypes. To account for that I have several models for each datatype. Is it possible from within the Foo model to create a getValue method that would return the value from the first value method it can find connected with it?
example:
class Foo(models.Model):
def getValue(self):
if self.hasatr('foovalueint'):
return self.foovalueint
elif self.hasatr('foovaluestring'):
return self.foovaluestring
elif self.hasatr('foovaluedatetime'):
return self.foovaluedatetime
class FooValueInt(models.Model):
foo = models.OneToOneField(Foo, on_delete=CASCADE, primary_key=True)
value = models.IntegerField()
class FooValueString(models.Model):
foo = models.OneToOneField(Foo, on_delete=CASCADE, primary_key=True)
value = models.CharField(max_length=50)
class FooValueDateTime(models.Model):
foo = models.OneToOneField(Foo, on_delete=CASCADE, primary_key=True)
value = models.DateTimeField()
Or is there a better way to solve this multiple datatype issue?
Related
Say I have the models
class A(models.Model):
class B(models.Model):
class C(models.model):
b = models.ForeignKey(B)
class D(models.Model):
c = models.ForeignKey(C)
a = models.ForeignKey(A)
What would a ORM query look like to select all Bs that are related to C's that are related to a specific A through table D?
As mentioned by the comment on your post you can use the autogenerated related name. But it never hurts to set it yourself.
class C(models.model):
b = models.ForeignKey(B, related_name="c")
class D(models.Model):
c = models.ForeignKey(C, related_name="d")
a = models.ForeignKey(A, related_name="d")
Then:
B.objects.filter(c__d__a=specific_a_obj).distinct()
class C (models.Model):
b = models.ForeignKey(on_delete=models.CASCADE, related_name='c_related')
final query:
c_ids = D.objects.values_list(
'c__id', flat=True).filter(a__id="specific A object id palced here")
query = B.objects.filter(c_related__id__in=c_ids).distinct()
Assume, we have model
class BaseModel(models.Model):
is_a = models.BooleanField()
and two models related to this one:
class A(models.Model):
value_1 = models.IntegerField()
base = models.ForeignKey(BaseModel, related_name='a')
class B(models.Model):
value_1 = models.IntegerField()
value_2 = models.IntegerField()
base = models.ForeignKey(BaseModel, related_name='b')
What I need is to refer to A or B depending on is_a property.
For example,
base = BaseModel.objects.get(id=1)
if base.is_a:
obj = A.objects.create(value_1=1, base=base)
else:
obj = B.objects.create(value_1=1, value_2=2, base=base)
return obj
or
if base.is_a:
queryset = base.a.all()
else:
queryset = base.b.all()
return queryset
i.e., every time I have to check the is_a property.
Is there more graceful way?
There are two only related models, A and B, no other ones will appear in the nearest future.
Part of the problem can be solved with django-polymorphic, e.g.:
class A(PolymorphicModel):
...
class B(A):
...
This allows to retrieve all A's and B's with one request like base.b.all(), but the problem here is that every B creates instance of A, which is unwanted.
I've considered GenericForeignKey as well. As far as I understood it has a number of limitations like "1) You can't use GenericForeignKey in query filters ; 2) a GenericForeignKey won't appear in a ModelForm" (from GenericForeignKey or ForeignKey).
One idea is to add choices to the BaseModel to have a string representation of your boolean value. If you set the strings equal to the A and B model names, you can use the model.get_foo_display() method to return the name of the model. Then use the Python getattr() method to access attributes as variables.
class BaseModel(models.Model):
base_model_choices = (
(True, 'A'),
(False, 'B'),
)
is_a = models.BooleanField(choices=base_model_choices)
For example,
base = BaseModel.objects.get(id=1)
queryset = base.getattr(models, get_is_a_display()).all()
obj = getattr(models, get_is_a_display()).objects.create(base=base)
I'm trying to add a model class with abstract=True in meta to another abstract class.For example,
class MainRecord(models.Model):
date = models.DateTimeField(auto_now_add=True,null=True)
X_data = models.EmbeddedField(
model_container=X,
model_form_class= X_Form,
)
class X(models.Model):
HRCT = models.BooleanField()
Y = models.EmbeddedField(
model_container=Y,
model_form_class=Y_Form,
)
class Meta:
abstract = True
class Y(models.Model):
Y_present = models.BooleanField()
Location = models.EmbeddedField(
model_container=Location,
model_form_class=Location_Form,
)
class Meta:
abstract = True
In Django admin, I'm able to see the embedded fields and it's corresponding checkboxes. I'm able to add/update values for the boolean field HRCT (Embedded from class X) but I'm not able to save the values/updates in the fields embedded from class Y to class X.
I have two model classes class A and class B. The second class is related to the first using a foreign key. I want to be able to search class A objects by an attribute of class B (inside django admin):
class A(models.Model):
a1 = models.CharField()
a2 = models.CharField()
class B(models.Model):
fk = models.ForeignKey(A, on_delete=models.CASCADE,)
b1 = models.CharField()
class AAdmin(admin.ModelAdmin):
search_fields = ['a1', 'b1']
admin.site.register(A, AAdmin)
Add a related_name to your Foreign Key and use it for the lookup you need:
class A(models.Model):
a1 = models.CharField()
a2 = models.CharField()
class B(models.Model):
fk = models.ForeignKey(A, on_delete=models.CASCADE, related_name='something')
b1 = models.CharField()
class AAdmin(admin.ModelAdmin):
search_fields = ['a1', 'something__b1']
admin.site.register(A, AAdmin)
My models.py looks like that :
class B(models.Model):
...
class C(models.Model):
...
class D(models.Model):
...
class A(models.Model):
b = models.ForeignKey(B, blank=True, null=True)
c = models.ForeignKey(C, blank=True,null=True)
d = models.ForeignKey(D, blank=True,null=True)
In views.py, I have to initialize an empty A, and fill it later. I can use
i = A().save()
But when I try something like :
i.b.add(objectb)
This exception occurs :
'NoneType' object has no attribute 'b'
I tried to cancel the null=True :
class A(models.Model):
b = models.ForeignKey(B, blank=True)
c = models.ForeignKey(C, blank=True)
d = models.ForeignKey(D, blank=True)
But then another exception occured :
A.b_id may not be NULL
I can't figure out how to initialize an empty but not "None" A.
I need your help,
Thanks you
I think you are confusing ManyToManyField and ForeignKey
To initialize a Foreign key, you would just do:
i = A().save()
i.b = objectb
i.save()
where objectb is an instance of class B
The reason i.b.add(objectb) throws an exception is,
i.b is accessing the attribute b of the model instance i, which is None, and when the ORM tries to call the add on b, it is indeed None. Hence the error.
Try this:
a = A()
b = B()
b.save()
a.b = b
a.save()