User-generated fields in Django - django

I'm building a Djano application which displays a set of images, and a form for each image for recording specific image characteristics. The user initializes a "project", where they specify the set of images that will be displayed for assessment. At project initialization, I'd like to give the user the ability to add custom boolean fields (i.e. a set of checkboxes), but I can't figure out how to build the database models.
For example, a user might initialize my_project with image_A.png, image_B.png and image_C.png for assessment. The default form they'll get for each image lets them choose between PASS, FAIL and UNKNOWN. They might wish to add custom fields like "poorly cropped", "over-exposed" or "blurry" (the idea being that the image could be a global PASS, but small failures, specific to the context of this image set, could still be recorded).
Generally, I'm trying to come up with a way to model user-generated fields in Django.

If I correctly understand, you don't need dynamic model fields, instead you can add model, which contains specific attributes for image in project, something like:
class Image(models.Model):
name = models.CharField()
img = models.ImageField()
class ProjectImage(models.Model):
image = models.ForeignKey('Image')
project = models.ForeignKey('Project')
flag = models.CharField(choices=PASS_FAIL_UNKNOWN)
class ProjectImageTag(models.Model):
project_image = models.ForeignKey(ProjectImage)
value = models.CharField()
class Project(models.Model):
images = models.ManyToManyField('Image', through=ProjectImage)
Also, you can store such tags in json field or postgres hstore field instead of separate table.
EDIT
Variation with predefined keys:
class ProjectImage(models.Model):
image = models.ForeignKey('Image')
project = models.ForeignKey('Project')
flag = models.CharField(choices=PASS_FAIL_UNKNOWN)
class Image(models.Model):
name = models.CharField()
img = models.ImageField()
class Project(models.Model):
images = models.ManyToManyField('Image', through=ProjectImage)
class ProjectImageParams(models.Model):
project_image = models.ForeignKey(ProjectImage, related_name='params')
key = models.CharField()
value = models.BooleanField()
Params of image may be obtained with ProjectImage().params.all(). And yes, django-eav may be a good option.

Related

Django - ImageField with multiple images

I have a model that has an ImageField. I want users to be able to upload multiple images for an object of the model - not only a single image. How can this be done? Whether with and image field or another approach.
You cannot store several images in one ImageField.
One solution for this problem would be to create an additional model (I called it "Attachment" for my social network pet project, call your's whatever should suit you) and have it reference the original model in a Foreign key. That way you can upload as many images as you want and create an instance of that new model for each new image.
Example Attachment model:
class Attachment(DatetimeCreatedMixin, AuthorMixin):
class AttachmentType(models.TextChoices):
PHOTO = "Photo", _("Photo")
VIDEO = "Video", _("Video")
file = models.ImageField('Attachment', upload_to='attachments/')
file_type = models.CharField('File type', choices=AttachmentType.choices, max_length=10)
publication = models.ForeignKey(TheOriginalModelYouUsedImageFieldIn, on_delete=models.CASCADE, verbose_name='Model that uses the image field')
class Meta:
verbose_name = 'Attachment'
verbose_name_plural = 'Attachments'

Documents classification with variable set of labels

I want to create a model where a user can define a set of labels for the purpose of classification of documents. Each label for that document should also have a probability (float) that that document belongs to that label.
So this is what I have for my model with 3 labels (news, business, sports):
class Document(models.Model):
document_name = models.CharField(max_length=100)
proba_label_news = models.DecimalField(max_digits=5)
proba_label_business = models.DecimalField(max_digits=5)
proba_label_sports = models.DecimalField(max_digits=5)
...
But of course there could be more labels what a user can define at the start of a classification project and what a developer can't foresee.
I tried manytomany as an alternative but when I create a Label model and define a new label as "news" than I can't have a different probability for each document label, right?
So what is the django way of solving this problem?
Yes, a many-to-many relationship could work. What you need to add is an intermediatiary 'through' model to store the probability for each document-label relationship. Something like this:
class Label(models.Model):
name = models.CharField(max_length=50)
class LabelProbability(models.Model):
label = models.ForeignKey(Label, on_delete=models.CASCADE)
document = models.ForeignKey("Document", on_delete=models.CASCADE)
probability = models.DecimalField(max_digits=5)
class Document(models.Model):
document_name = models.CharField(max_length=100)
labels = models.ManyToManyField(Label, through=LabelProbability)
Then when you want to add a label to a document, you would use the through_defaults argument to assign a probability. Do something like the following:
news = Label.objects.get(name="news")
document_1.labels.add(news, through_defaults={"probability":0.57})
You can read more about many-to-many fields, and using a through table in django docs here
An alternative approach
Alternatively, you could store the label and the probability together, something like this:
class Label(models.Model):
name = models.CharField(max_length=50)
probability = models.DecimalField(max_digits=5)
document = models.ForeignKey("Document", on_delete=models.CASCADE)
class Document(models.Model):
document_name = models.CharField(max_length=100)
This way, you just have two tables, and each label stores both the name of the label (allowing you to use any name), and the probability. You can add as many labels as you want pointing to the same document (just as before).

How can I add customised choice fields in django (2.1)?

This is the model class that stores the details about an app. In this model is it possible to add a customised list fields. i,e a user should be able to define a set of choices and later it will be available for adding (as tags) to the builds of the app.
class App(models.Model):
bundle_number = models.CharField(max_length=255)
hidden = models.BooleanField(default=False)
class Build(models.Model):
app = models.ForeignKey(App, on_delete=models.CASCADE)
number = models.CharField(max_length=255)
uploaded_date = models.DateTimeField(auto_now_add=True)
If I understand your question right you want to do create a new model Tag with builds attribute:
class Tag(models.Model):
...
builds = models.ManyToManyField(Build, related_name="tags")
Then you can assign multiple tags to one build and vice versa multiple builds to one tag.
You can read more here: https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ManyToManyField

Uploading a stack of images in Django

I'm getting used to Django and I want to upload a stack of images via browser. The user must be able to upload the whole stack from one field to store the images in the database keeping the order. I think I'm looking for something like:
Class Foo(models.Model):
MultiImageField(upload_to = "/stack_name/").
And i have the models like this:
class Stack(models.Model):
user = models.ForeignKey('auth.User')
name = models.CharField(max_length=128)
class Images(models.Model):
position = models.PositiveIntegerField()
stack = models.ForeignKey(Stack)
originalImg = models.ImageField(upload_to='/stacks/')
I'm pretty lost with this, Is there any way to do it?
Thanks.

Django forms with odd model relationship

I am working with an existing database that I can not modify and having some trouble trying to deal with presenting forms for modifying the database in Django. The structure in question is as follows and all models are unmanaged.
class Persons(models.Model):
personid = models.BigIntegerField(primary_key=True, db_column='PersonID')
....
class Phones(models.Model):
phoneid = models.BigIntegerField(primary_key=True, db_column='PhoneID')
number = models.CharField(max_length=60, db_column='Number', blank=True)
type = models.CharField(max_length=15, db_column='Type', blank=True)
...
class Personsphones(models.Model):
personphoneid = models.BigIntegerField(primary_key=True, db_column='PersonPhoneID')
personid = models.ForeignKey(Persons, db_column='PersonID')
phoneid = models.ForeignKey(Phones, db_column='PhoneID')
...
I want to create a form to display all of the 'Phones' associated with a particular 'Persons' and in addition be able to modify/add/remove 'Phones' belonging to a 'Persons'. Right now the only thing I can think of is to display the 'Phones' in a modelformset and then if one is added or removed manually set the 'Personsphones' relation. Any ideas on how to best deal with this model setup?
For making changes to your models you may want to use django-south http://south.aeracode.org/docs/
As far as displaying your 'Phone' under your forms.py you may want to set up class meta like so. With this any changes made to models will reflect on change
class Meta:
model = Persons
exclude = ('user')
In models you may want to use Foreignkey fore relationships between phones and Persons. Better seen in action here https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey