I have the following models:
class Thematics(models.Model):
title = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.title
class Pathology(models.Model):
title = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.title
class Organ(models.Model):
title = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.title
class Surgerytype(models.Model):
title = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.title
class Content(models.Model):
thematics = models.ManyToManyField(Thematics, null=True, blank=True)
pathology = models.ManyToManyField(Pathology, null=True, blank=True)
organs = models.ManyToManyField(Organ, null=True, blank=True)
surgery = models.ManyToManyField(Surgerytype, null=True, blank=True)
I have a lot of Content instances, which themselves have a lot of M2M instances related to them. You can think of Surgerytypes as tags.
I have this query:
content = Content.objects.all()
# surgeries is an array of Surgerytype instances titles
query = content.filter(Q(surgery__title__in=surgeries)
For simplicity I will focus on one M2M model, Surgerytype, and admit that I could replicate then chain the query with the 3 other models.
I create 3 instances of Surgerytype with title: "Diagnosis", "Surgery", "Therapeutic"
I then create 3 instances of Content to which I add these M2M relations with surgery (the M2M to Surgerytype)
Content instance 1 --> add(Diagnosis)
Content instance 2 --> add(Diagnosis, Surgery)
Content instance 3 --> add (Diagnosis, Surgery, Therapeutic)
The whole idea here is to have a dynamic filtering by the client/doctor who can choose tags to get to the type of content he needs.
So if he/she clicks :
on Diagnosis and no other tag, the doctor should see Content instance 1,2 and 3.
on Diagnosis and Surgery or just Surgery, the doctor should see Content instance 2 and 3
on Diagnosis, Surgery, Therapeutic or just Therapeutic, the doctor should see Content instance 3
On Diagnosis and Therapeutic, the doctor should see Content 3
So this is an AND problematic.
When I ajax send to my backend a tag (i.e. a Surgerytype instance title), all good the query returns all the instances of Content that include this tag. Now, the problem is that if I select two tags, the queryset returns nothing instead of all Content instances that include these 2 tags and possibly more tags. I have found on SO how to do this for 1 M2M model in the Content model but it is quite dirty and not scalable at all (there are 3 other M2M/filters to add in the real Content model). Any ideas? Found many questions related to the subject but it doesn't seem to have a definitive, scalable answer. Many thanks to you all
Related
I have one model:
class Product(models.Model):
slug = models.SlugField(unique=True)
image = models.ImageField(upload_to='media')
title = models.CharField(max_length=150)
description = models.TextField()
short_description = models.CharField(max_length=300)
price = models.DecimalField(max_digits=5, decimal_places=2)
discount_price = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True)
stock_quantity = models.PositiveIntegerField(default=10)
in_stock = models.BooleanField(default=True)
on_sale = models.BooleanField(default=False)
date_added = models.DateTimeField(auto_now_add=True, blank=True)
main_category = models.CharField(default='FW', choices=CATEGORY_CHOICES, max_length=2)
additional_category = models.CharField(choices=CATEGORY_CHOICES, max_length=2, blank=True, null=True)
brand = models.CharField(choices=CATEGORY_CHOICES, max_length=2, blank=True, null=True)
size = models.CharField(max_length=2, choices=CATEGORY_CHOICES, default='M', blank=True, null=True)
def __str__(self):
return self.title
Within this model will be various types of products for example, clothes and books.
These will be defined by the main_category and additional_category fields within the model.
If the product being entered into the database is a piece of clothing I will enter values for size and brand. For books, these will obviously be blank.
However, if the product is a piece of clothing, I have clothing for women, clothing for men and clothing for children. I will be able to define these by selecting 'for women' in the main_category field.
In my templates, I would like to dynamically display a page that shows all clothes, one that displays 'clothes for women', another page that shows 'clothes for men' etc etc. And then a page that displays all books, books for teens, books for adults etc, based on the main_category and additional_category.
If i enter a product, and the main category is 'for women' and the additional category is 'plus size', I would like a template to dynamically display all products that have either 'for women' selected in main_category OR additional_category. And a template that displays all plus size clothing, where main_category OR additional_category is 'plus size'.
My trouble comes when I am writing the views. Do I need to provide a view for women only clothes, plus size only clothes, children's clothes, books, books for adults, books for teens etc. Or can I write just ONE view, that outputs the correct data to multiple templates. Basically, do I need one view per template?
I have read this:
https://docs.djangoproject.com/en/3.0/topics/class-based-views/generic-display/
and have taken a look at get_context_data. Can I define multiple get_context_data functions to return different filtered information for different templates, and if so how do I differentiate between them?
I am current learning, and building a dummy online store with Django in order to learn as much as possible, but finding this particularly complex?
Thanks
A cleaner way to do that is to create an abstract model called Product and use it as a base class for different product types, like clothes and books.
Being Product an abstract class means that Django's ORM won't create a Product table on database. Instead, it will create tables for each subclass including the common fields you define on Product class. Check the code below for better understanding:
# models.py
from django.db import models
class Product(models.Model):
image = models.ImageField(upload_to='media')
title = models.CharField(max_length=150)
# ... (other common fields)
class Meta:
abstract = True
class Clothes(Product):
size = models.CharField(max_length=2, choices=CATEGORY_CHOICES, default='M', blank=True, null=True)
# ... (other specific fields)
From django docs.
I'm trying to figure it out on how I can show only a specific set of dynamic fields in eav to a unique registered model in my apps.models. But I don't know how to this, I've also read the documents but I can't seem to find anything about it, or maybe I've come across it and didn't understand.
Now, what is happening is that, when I add an attribute in the django admin. It also adds the dynamic field in all the models registered in the eav.
What I want to do is that;
model 1 - dynamic_field1, dynamic_field2, dynamic_field3
model 2 - dynamic_field4, dynamic_field5, dynamic_field6
Btw, I'm currently using the django-eav2 the documentation is in the link. I've found my solution for my initial use case here link
Below codes are basically on how to register my models to the eav. Here is my sample models
class ClientName(models.Model):
name = models.CharField(max_length=250, null=True, blank=True)
description = models.TextField(null=True, blank=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return str(self.name)
class CallDetails(models.Model):
client_name = models.ForeignKey(ClientName, on_delete=models.PROTECT, null=True, blank=True, db_index=True)
letter_info = models.TextField(null=True, blank=True)
def __str__(self):
return str(self.client_name)
class Meta:
verbose_name = 'Call Detail'
ordering = ['client_name']
eav.register(ClientName)
eav.register(CallDetails)
below is my admin.py
class CallDetailsAdminForm(BaseDynamicEntityForm):
model = CallDetails
class CallDetailsAdmin(BaseEntityAdmin):
form = CallDetailsAdminForm
admin.site.register(CallDetails, CallDetailsAdmin)
When creating many to many relationships we use an intermediary table. Lets say I use the following entities video, category, tag, and VideoCategory, VideoTag to create the relations.
I'm assuming that many tags/categories can have many videos and vice-versa.
And I do it with through keyword 'cause I want to be able to use extra fields in the future if I want.
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Tag(models.Model):
tag = models.CharField(max_length=50)
def __str__(self):
return self.tag
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='VideoCategory')
tags = models.ManyToManyField(Tag, through='VideoTag')
def __str__(self):
return self.title
class VideoCategory(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
class VideoTag(models.Model):
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
But I was wondering if would be possible to create a taxonomy entity and handle the relationships with categories and tags from just one place.
class Category(models.Model):
category = models.CharField(max_length=50)
def __str__(self):
return self.category
class Tag(models.Model):
tag = models.CharField(max_length=50)
def __str__(self):
return self.tag
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='Taxonomy')
tags = models.ManyToManyField(Tag, through='Taxonomy')
def __str__(self):
return self.title
class Taxonomy(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE, null=True)
video = models.ForeignKey(Video, on_delete=models.CASCADE)
Now the taxonomy entity would hold the category and tag related to videos and vice-versa.
I've included 'null=True' to be able to create relations with categories without tags and with tags but without categories.
If I don't use it. I receive an error:
# sqlite3.IntegrityError: NOT NULL constraint failed: MyApp_taxonomy.category_id
This also means that using that single taxonomy entity for the two relationships could have many NULL Fields if one of these category or tag fields are empty on every concrete relation instance (row).
Question:
What would be better ? To keep the intermediary tables separate (VideoCategory & VideoTag) Or to join these intermediary tables into just one ? (Taxonomy)
Due to my lack of experience with databases I couldn't say if I'm missing something important. If doing it with just one intermediary table would give problems in near future or something like that... Of if it is just fine.
You have to use through_fields argument (doc):
class Video(models.Model):
title = models.CharField(max_length=255)
categories = models.ManyToManyField(Category, through='Taxonomy', through_fields=('video', 'category'))
tags = models.ManyToManyField(Tag, through='Taxonomy', through_fields=('video', 'tag'))
I'm working on a Django project generated via Mezzanine. I've been able to create my models, however I want to have a form where an admin can select from a list to assign a value in a many to many or a one to many relationship. For example, I have a model for Schemas:
class Schema(AutoCreatedUpdatedMixin, SoftDeleteMixin):
"""List of all Schemas in a given database"""
name = models.CharField(max_length=128, null=False)
status = models.BooleanField(max_length=128, null=False, default=True, verbose_name="Is Active")
description = models.CharField(max_length=65535, null=True, blank=True, default=None)
database = models.ForeignKey(Database, on_delete=models.CASCADE)
pull_requests = models.ManyToManyField(Link)
questions = models.ManyToManyField(Question, blank=True)
comments = models.ManyToManyField(Comment, blank=True)
technical_owners = models.ManyToManyField(Employee, related_name='technical_owners_schemas', blank=True)
business_owners = models.ManyToManyField(Employee, related_name='business_owners_schemas', blank=True)
watchers = models.ManyToManyField(Employee, related_name='watchers_schemas', blank=True)
def __unicode__(self):
return "{}".format(self.name)
And I have a model for Employees
class Employee(AutoCreatedUpdatedMixin, SoftDeleteMixin):
"""List of people with any involvement in tables or fields: business or technical owners, developers, etc"""
name = models.CharField(max_length=256, blank=False, null=False, default=None, unique=True)
email = models.EmailField(blank=True, null=True, unique=True)
def __unicode__(self):
return "{}".format(self.employee)
An employee can own multiple schemas and a schema can be owned by multiple employees. My database has an active employee in it, however when I try to create a Schema the employee shows up as Employee Object. Rather I would want the form to show the Employee.name. How can I do this? My admin file contains the following:
class SchemasAdmin(admin.ModelAdmin):
list_display = ['name', 'status', 'database', 'description']
ordering = ['status', 'database', 'name']
actions = []
exclude = ('created_at', 'updated_at', 'deleted_at')
First of all are you using python 2 or 3? For 3, the __str__ method should be used instead of __unicode__. I am writing this because it seems that there's a problem with the __unicode__ method of Employee, which although is defined as:
def __unicode__(self):
return "{}".format(self.employee)
th Employee class does not have an employee attribute (unless there's such an attribute in the mixins that class inherits from (AutoCreatedUpdatedMixin, SoftDeleteMixin) but I don't think that is the case.
In any case, the problem is that you haven't defined a propery __str__ (if using python 3) or __unicode__ (for python 2) method on the Employee class - just define it like:
return self.name
and you should see the employee's name in the django admin select fields.
On the webpage I am currently working on I have to display profiles of different persons. Each person has a profile image that is displayed on the right side. Furthermore, I have the content saved as markdown on the server.
Now I want to add the possibility to add an optional list of images that are displayed under the text and shows something about the person. My model for the person looks like that:
class stipendiat(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
content = models.TextField()
year = models.IntegerField(blank=False, null=False)
form = models.IntegerField(blank=False, null=False)
image = models.ImageField(upload_to='stipendiaten/', blank=True, null=True, default='default.jpg')
gallery = # This is the question
def __unicode__(self):
return self.first_name + " " + self.last_name
Because I want to save some data about the image the model should look like that:
class Image(models.Model):
caption = models.CharField(max_length=512)
year = models.IntegerField()
image = models.ImageField(upload_to=upload_path_handler, blank=False, null=False)
For convenience it should be possible to add an image while editing the form for the person. To be precise, I want to add a person and fill in the necessary information (first_name, last_name, content etc.). At the end should be a list of connected images and a button to add an image rapidly.
Is it necessary to use an external app or is there an elegant solution with relation fields?
Maybe you should use a different model for the gallery images and a foreign key field to link the two models together
class Image(models.Model):
#...
stipendiat = models.ForeignKey(Reporter)
Now you can retrieve the Gallery Images for a stipendiat with id 1 like this
Image.objects.filter(stipentiat__pk=1)