I am building a Django data model and I want to be able to store an array of ImageFields.
Is it possible?
mainimage = models.ImageField(upload_to='img', null = True)
images = models.??
Thanks.
Create another model to images and have foreignkey with your model.
def YourModel(models.Model):
#your fields
def ImageModel(models.Model):
mainimage = models.ImageField(upload_to='img', null = True)
image = models.ForeignKey(YourModel, ...)
I would use the ManyToMany relationship to link your model with an image model. This is the way to aggregate ImageField as django does not have aggregate model field
def YourModel(models.Model):
images = ManyToManyField(ImageModel)
...
def ImageModel(models.Model):
img = ImageField()
name ...
Maybe you need something more performant (this could lead to lots of horrible joins)
Related
In Django, how does one apply a custom transformation while serializing a field?
For instance, I have a model which has a geometry field, which is stored in a specific coordinate system. Now, for this one serializer, I'd like to perform a conversion that converts the coordinates to another coordinate system. How is that done?
The serializer currently looks like this:
class LinkWithGeometrySerializer(serializers.ModelSerializer):
class Meta:
model = Link
fields = ['link_type',
'geometry',
]
The geometry is the field that should have a transformation applied to it.
As Iklinac pointed out, you can use a custom field, but that only pays off when you can reuse it.
There's two other common approaches:
Keep it at serializer level:
class LinkWithGeometrySerializer(serializers.ModelSerializer):
geometry = serializers.SerializerMethodField()
class Meta:
model = Link
fields = ['link_type', 'geometry',]
#staticmethod
def get_geometry(obj: Link):
# for example obtain srid from context, by passing it in via view or hardcode
return obj.geometry.transform(srid=your_srid)
At the model level (make the database do the transformation):
in your view:
from django.contrib.gis.db.models.functions import Transform
TARGET_SRID = 4326
class LinkView(RetrieveAPIVIew):
queryset = Link.objects.annotate(transformed=Transform("geometry", TARGET_SRID))
...
or (srid passed as path component in url):
from django.contrib.gis.db.models.functions import Transform
class LinkView(RetrieveAPIVIew):
def get_queryset(self):
return Link.objects.annotate(transformed=Transform("geometry", self.kwargs["srid"])
serializer
class LinkWithGeometrySerializer(serializers.ModelSerializer):
geometry = serializers.GeometryField(source='transformed') # [1]
class Meta:
model = Link
fields = ['link_type', 'geometry',]
[1] https://github.com/openwisp/django-rest-framework-gis/blob/master/rest_framework_gis/fields.py#L13
I need a model with several "tag" fields. For example:
class Food(models.Model):
type = SomeTagField()
manufacturer = SomeTagField()
It could be done using many-to-many relationships, but I'm not sure if this is a correct approach. It looks a little bit overcomplicated.
I've tried django-tagit and its TaggableManager but without luck:
ValueError: You can't have two TaggableManagers with the same through model.
What would be a correct way to handle that?
"Over-complicated" is subjective, but I would use ManyToManyField
class FoodType(models.Model):
country = SomeField()
nutrients = SomeField()
...
class Manufacturer(models.Model):
name = SomeField()
cost = SomeField()
...
class Food(models.Model):
type = models.ManyToManyField(FoodType, ...)
manufacturer = models.ManyToManyField(Manufacturer, ...)
I am creating a reference lexicon in django. The lexicon is a translator for certain fields from one language to another.
The lexicon goes like this: 'id','lng1','lng2','lng3'
I have a model that uses the lexicon in one of the fields.
class lexicon(models.Model):
lng1 = model.Charfield(max_length=255)
lng2 = model.Charfield(max_length=255)
lng3 = model.Charfield(max_length=255)
lexicon_choices = (
(lng1=lng1),
(lng2=lng2),
(lng3=lng3)
)
class model(models:Model):
model_name = model.Charfield(max_length=255, unique)
field1 = model.Charfield(max_length=3,CHOICES=lexicon_choices)
This works ok, but I want to know, is there a way to glean out the column names from class lexicon and port them as the choices for class model? I am using Django Rest Framework for the first time, and I want to make sure the right lng is there.
Thanks
You can use a ForeignKey on the lexicon class to your main model. This will ensure a One to Many relationship. And you can store the values in database.
yes, possible. but in admin.py
class CustomForm(forms.ModelForm):
class Meta:
model = YourModel
def __init__(self, *args, **kwargs):
super(CustomForm, self).__init__(*args, **kwargs)
choices = [(x.id, x.name) for x in Lexicon.objects.all()]
self.fields['field1'].choices = choices
class YourModelAdmin(admin.ModelAdmin):
form = CustomForm
and your original model looks like:
class YourModel(models:Model):
model_name = model.Charfield(max_length=255, unique)
field1 = models.CharField(max_length=10, choices=(('--', '--'),))
IMPORTANT: do not name your class names with lower case. ;)
I want to change formfield widget depend on other field value. Default is select because model field is foreign key. My models are as follows:
class ProductFeatureValue(BaseName):
feature = models.ForeignKey('ProductTypeFeature')
class Meta:
verbose_name = _(u'Product Feature Value')
verbose_name_plural = _(u'Product Feature Values')
class ProductFeature(models.Model):
product = models.ForeignKey('Product')
feature = models.ForeignKey('ProductTypeFeature')
value = models.ForeignKey('ProductFeatureValue')
And my form is as follows:
class ProductFeatureFormForInline(ModelForm):
class Meta:
model = ProductFeature
def __init__(self,*args,**kwargs):
super(ProductFeatureFormForInline,self).__init__(*args,**kwargs)
if isinstance(self.instance,ProductFeature):
try:
widget_type = self.instance.feature.product_type.producttypefeature_set.all()[0].widget #TODO Fix that 0 slice
if widget_type == u'TEXT':
self.fields['value'] = CharField(widget=TextInput())
if widget_type == u'MULTIPLE_SELECT':
self.fields['value'].widget = MultipleChoiceField()
except:
pass
It changes the fields widget but when it make it charfield and populate it with instance it shows the id of the model not the value (author : 1) and it makes sense to show it that way, but i want to show(author: Dan Brown).
I have tried with initial values but not working. Any tips of doing that will be highly appreciated. Thanks
Your __unicode__() method on the model should dictate what is shown there, if I'm not missing something.
On your model:
class ProductFeatureValue(BaseName):
[... snipped code ...]
def __unicode__():
return self.feature
This snippet assumes that self.feature is what you want to return, and not something else on the parent BaseName.
suppose I have three model like this:
class video(models.Model):
name=models.CharField(max_length = 100)
class image(models.Model):
name=models.CharField(max_length = 100)
class comments(models.Model):
content=models.CharField(max_length = 100)
now i want to notic the user if their video or image get an comment
this is what i want
the message model:
class message(models.Model):
type=models.CharField(max_length = 100) # 'video' or 'image'
video_or_image=models.ForeignKey(video or image)
#the type is just a string to tell if the comment is about the video or image
#video_or_image need to be video foreignkey or image foreignkey depends on type
is it possible.
I currently work around this by two method
first:
class message(models.Model):
type = models.CharField(max_length = 100) # 'video' or 'image'
video_or_image_id = models.IntegerField(default = 1)
#
second
class message(models.Model):
type=models.CharField(max_length = 100) # 'video' or 'image'
video=models.ForeignKey(video)
image=models.ForeignKey(image)
# if the comment is about video just leave the image empty
if the one field to multiple model can not be done, then which my work around method is better, or help me with a better one!
You are looking for a GenericForeignKey.
This is also the way contrib.comments relates comments to commented items.