django display reverse m2m in admin including null - django

I'm trying to display the reverse M2M relationship in the admin i.e. for the below models, not just display for a given service the region(s) it covers, but I also want to see for a given region what services there are. Also the same for payment types. For the reverse views it would be good to see what null entries, e.g. in payment types click on null and see what services have not been assigned payment types yet. (I seem to have this in some services even though I haven't specified null=true in the ManytoManyField declarations, - not sure if M2M fields allow this by default?)
class Service(models.Model):
name = models.CharField(max_length=255)
supplier = models.ForeignKey(Supplier)
payment_methods = models.ManyToManyField(PaymentMethod)
region = models.ManyToManyField(Region)
class Region(models.Model):
unique_id = models.IntegerField(unique=True)
name = models.CharField(max_length=255, blank=True)
def __str__(self):
return str(self.unique_id)
class PaymentMethod(models.Model):
MONTHLY_DIRECT_DEBIT = 'MDD'
CASH_OR_CHEQUE = 'CAC'
QUARTERLY_DIRECT_DEBIT = 'QDD'
PAYMENT_CHOICES = (
(MONTHLY_DIRECT_DEBIT, 'Monthly Direct Debit'),
(CASH_OR_CHEQUE, 'Cash or Cheque'),
(QUARTERLY_DIRECT_DEBIT, 'Quarterly Direct Debit'),
)
unique_id = models.CharField(max_length=3, choices=PAYMENT_CHOICES)
name = models.CharField(max_length=255, unique=True)

Related

Django tables connection

I have 3 django tables connected like this:
Is there anyway to make a query for table Table that will get id_equip from table equip?
models.py
class Vendor(models.Model):
vendor_name = models.CharField(max_length=50)
def __str__(self):
return self.vendor_name
class Equipment(models.Model):
equipment_name = models.CharField(max_length=50)
id_vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None)
def __str__(self):
return self.equipment_name
class Table(models.Model):
table_name = models.CharField(max_length=100)
id_vend = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None)
id_equip = models.ManyToManyField(Equipment)
This part of the django docs is relevant and helpful, I definitely recommend your review at least that section and ideally the whole page.
Your models are already denormalized as evidenced by Table.id_equip which relates to Equipment so you could do:
table = Table.objects.get(SOME_FILTER)
equipment_ids = list(table.id_equip.all().values_list('id', flat=True))
If you wanted to go through the vendor I'd suggest:
table = Table.objects.get(SOME_FILTER)
equipment_ids = list(Equipment.objects.filter(vendor_set__table_set=table).values_list('id', flat=True))
I would recommend that you don't name your relationship fields with id_. With an ORM, these fields should represent the instances of the Model they are mapping to. For example:
class Table(models.Model):
name = models.CharField(max_length=100)
vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None)
equipment = models.ManyToManyField(Equipment)
If you're trying to create the model on top of an existing table, you can make use of the db_column parameter when defining the field.
vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, default=None, db_column="id_vend")

Getting a column instead of an object when relating with PrimaryKeyRelatedField in Django-Rest-Framework

I have a model for applications, which among many attributes have a category. This category is in fact a key to another model that has the category ID, its name, and so on.
class Application(models.Model):
title = models.CharField(max_length=50)
vendor = models.CharField(max_length=50, default="Unknown", null=False)
.
.
.
category = models.ForeignKey('ApplicationCategory', related_name='applications', null=False, default=1, on_delete=models.SET_DEFAULT)
class ApplicationCategory(models.Model):
name = models.CharField(max_length=20, null=False)
description = models.CharField(max_length=200, null=False)
Then, on the Django REST serializers side I have the serializer for the applications:
class SoftwareSerializer(serializers.ModelSerializer):
category = serializers.PrimaryKeyRelatedField(queryset=ApplicationCategory.objects.all())
class Meta:
model = Application
fields = ['id', 'title', ... 'category']
Which is generating the expected API view, with a dropdown for the categories, but showing them as the ApplicationCategory objects and not giving me their name.
API showing Category dropdown with objects instead of names
Is there a way to access attributes of those objects to show the name in the dropdown, for usability sake?
I have also tried creating a CategorySerializer object (class CategorySerializer(serializers.ModelSerializer)) and then using it as category = CategorySerializer(many=False) but instead of dropdowns, I get open text fields for the attributes of the category.
Am I trying to do something that is not expected to work?
try to define the desired text in str method for your ApplicationCategory class:
class ApplicationCategory(models.Model):
name = models.CharField(max_length=20, null=False)
description = models.CharField(max_length=200, null=False)
#example
def __str__(self):
return '%s: %s' % (self.name , self.description)

Django - query the records in all tables that have the foreign key equal to the selected record in the main table

In Django I want to query the records in all tables that have the foreign key project = ProjectMain's chosen pk. So if I choose a record in ProjectMain and it's pk=2 I also want the records from the other three tables where the foreign key product=2.
Tables Methods, Things, and MoreStuff can have multiple records with project=2.
Here are the tables:
class ProjectMain(models.Model):
username = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.CharField(max_length=60)
product = models.ForeignKey(ProductType, on_delete=models.CASCADE)
filler = models.CharField(max_length=100)
class Methods(models.Model):
method_name = models.CharField(max_length=10)
method_test = models.CharField(max_length=50, null=False)
project = models.ForeignKey(ProjectInformation, on_delete=models.CASCADE)
class Things(models.Model):
thing1 = models.CharField(max_length=10)
thing2 = models.CharField(max_length=50, null=False)
project = models.ForeignKey(ProjectInformation, on_delete=models.CASCADE)
class MoreStuff(models.Model):
stuff1 = models.CharField(max_length=10)
stuff2 = models.CharField(max_length=50, null=False)
project = models.ForeignKey(ProjectInformation, on_delete=models.CASCADE)
I've been trying Django querysets and am getting nowhere. Please help.
You can access them via the related_name property as defined in ForeignKey.
project_main = ProjectMain.objects.get(id=2)
methods = project_main.methods_set.all() # All the Methods related to the instance
things = project_main.things_set.all() # All the Methods related to the instance
more_stuffs = project_main.morestuff_set.all() # All the Methods related to the instance

Filtering Django query filtering

I'm doing some querying currently and I was wondering if I would be able to query something from these 3 models where the return would give me all the projects the users are working on. I know about the basic filtering however thats not really enough in this case, how would one go about querying through 2 foreign keys.
class User(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField()
class ProjectUser(models.Model):
project = models.ForeignKey("Project", on_delete=models.CASCADE)
user = models.ForeignKey("User", on_delete=models.CASCADE)
is_lead = models.BooleanField(default=False)
class Meta:
unique_together = (("project", "user"),)
class Project(models.Model):
name = models.CharField(max_length=255)
client = models.CharField(max_length=255)
complete = models.BooleanField(default=False)
You can obtain the Projects a user is working on with:
Project.objects.filter(
projectuser__user=user
)
The double underscores are used to look "through" relations. Furthermore the default related_query_name=… parameter [Django-doc] is, if not specified, the name of the model in lowercase.

ManyToManyField with extra information

I'm working on a django website and I need to store some information about the user like a isVerified BooleanField and a profile picture in an ImageField as well as ratings which stores ratings a user has given different elements. So I made a model like this:
class UserProfile(AbstractBaseUser):
is_verified = models.BooleanField(default=True)
current_profile = models.ImageField(default=static('img/default_profile.jpg'))
ratings = models.ManyToManyField(Element, on_delete=models.CASCADE)
however I'd like to save some more about these ratings (like a timestamp and the actual value the user rated)
Do I need to make a seperate model just for that or can this be acchieved in a better way?
You need to use intermediary table that can be specified via the through keyword.
For example:
class UserProfile(AbstractBaseUser):
is_verified = models.BooleanField(default=True)
current_profile = models.ImageField(default=static('img/default_profile.jpg'))
ratings = models.ManyToManyField(Element, on_delete=models.CASCADE, through='UserProfileElement')
class UserProfileElement(models.Model):
user = models.ForeignKey(UserProfile, models.CASCADE, verbose_name=_('User'))
element = models.ForeignKey(Element, models.CASCADE, verbose_name=_('Element'))
timestamp = models.DateTimeField(_('Timestamp'), auto_now_add=True)
rating = models.PositiveIntegerField(_('Rating'))
class Meta:
unique_together = ('user', 'element')
Django docs: ManyToManyField.through