Model Many to Many relations with Abstract Class - python

I have the following models.py
class Institution(models.Model):
name = models.CharField(_('Name'), max_length=150, db_index=True)
slug = models.SlugField(_('Domain name'), unique=True)
class Company(Institution):
type = models.PositiveSmallIntegerField()
class HC(Institution):
type = models.PositiveSmallIntegerField()
bed_count = models.CharField(max_length=5, blank=True, null=True)
I have the models that are generated from Institutions and I want to follow the Institutions from the Profile model.
class Profile(models.Model):
user = models.OneToOneField(User)
about = models.TextField(_('About'), blank=True, null=True)
following_profile = models.ManyToManyField('self', blank=True, null=True)
following_institution = models.ManyToManyField(Institution, blank=True, null=True)
following_tag = models.ManyToManyField(Tag, blank=True, null=True)
I want to make M2M relations to all models that inherits Institutions. Is there a way to do this with Generic Relations?

Sounds like you're ready for polymorphism:
https://django-polymorphic.readthedocs.org
Otherwise you'll have to add them individually, so your Institution model would look something like this:
class Institution(models.Model):
name = models.CharField(_('Name'), max_length=150, db_index=True)
slug = models.SlugField(_('Domain name'), unique=True)
class Meta:
abstract = True
and the manytomany just basic like this:
following_company = models.ManyToManyField(Company, blank=True, null=True)
following_hc = models.ManyToManyField(Institution, blank=True, null=True)

Related

Creating an Inline Formset - Foreign Key Issue

I have the following 2 models that I want to use in a form set. I'm not sure what I've got wrong
models.py
class AppTradingPartnerTrp(models.Model):
id_trp = models.AutoField(primary_key=True)
tpid_trp = models.CharField(max_length=50, blank=True, null=True)
name_trp = models.CharField(max_length=50)
description_trp = models.CharField(max_length=100, blank=True, null=True)
idtrn_trp = models.ForeignKey('AppTransmissionTrn', models.DO_NOTHING, db_column='idtrn_trp', blank=True, null=True)
class AppCustomerTpRel(models.Model):
id_rel = models.AutoField(primary_key=True)
idcst_rel = models.ForeignKey(AppCustomerCst, models.DO_NOTHING, db_column='idcst_rel')
idtrp_rel = models.ForeignKey(AppTradingPartnerTrp, models.DO_NOTHING, db_column='id_trp')
cust_vendor_rel = models.CharField(max_length=50, blank=True, null=True)
sender_id_rel = models.CharField(max_length=50, blank=True, null=True)
old_vendor_rel = models.CharField(max_length=50, blank=True, null=True)
vendor_name_rel = models.CharField(max_length=50, blank=True, null=True)
category_rel = models.CharField(max_length=50, blank=True, null=True)
And here is where I'm trying to create the formset:
forms.py
CstVendorNoFormSet = inlineformset_factory(AppCustomerTpRel, AppTradingPartnerTrp, exclude=())
However when I do runserver I'm getting:
ValueError: 'AppTradingPartnerTrp' has no ForeignKey to 'AppCustomerTpRel'.
It looks like you've got your ForeignKey relationships the wrong way round.
Side note: I noticed that in your 'AppTradingPartnerTrp' model, for the idtrn_trp FK field, you have got 'AppTransmissionTrn' as a string, I think it should be AppTransmissionTrn without the apostrophes.
You have reversed the model order
inlineformset_factory(parent_model, model, ... )
Parent model is AppTradingPartnerTrp as it has multiple AppCustomerTpRel (foreign key) so
CstVendorNoFormSet = inlineformset_factory(AppTradingPartnerTrp, AppCustomerTpRel, exclude=())

Update foreign key of one model based on another model

I have a student model:
class Student(User):
religion = models.ForeignKey(
Religion, on_delete=models.SET_NULL, null=True)
caste = models.ForeignKey(Caste, on_delete=models.SET_NULL, null=True)
date_of_birth = models.DateField(default=timezone.now)
parent_name = models.CharField(max_length=255, default=None)
address = models.CharField(max_length=255, default=None)
phone_number1 = models.CharField(
"Phone Number 1", max_length=10)
phone_number2 = models.CharField(
"Phone Number 2 (optional)", max_length=10, blank=True)
classes = models.ForeignKey(
Class, on_delete=models.SET_NULL, default=None, null=True, blank=True)
def __str__(self):
return self.first_name+" "+self.last_name
# Control model features
class Meta:
verbose_name = 'Student'
verbose_name_plural = 'Students'
And an admission model:
class Admission(models.Model):
admission_date = models.DateField()
classes = models.ForeignKey(
Class, on_delete=models.SET_NULL, null=True)
student = models.ForeignKey(
Student, on_delete=models.SET_NULL, null=True)
Also a class model that takes in all the information of the class the student is in:
class Class(models.Model):
class_name = models.CharField(
max_length=10,
default=None
)
division_name = models.CharField(
max_length=10,
default=None
)
class_teacher = models.ForeignKey(
Teacher, on_delete=models.SET_NULL, default=None, null=True, blank=True)
institute = models.ForeignKey(
Institute, on_delete=models.SET_NULL, default=None, null=True, blank=True)
def __str__(self):
return self.class_name+" "+self.division_name+" "+self.institute.name
# Control model features
class Meta:
verbose_name = 'Class'
verbose_name_plural = 'Classes'
I want to achieve the following: change student info based on the admissions model. When I update the Admission info, it should take the class and update the class in the student model based on the class provided in the admission model. How can this be achieved?
maybe you can try to use signal?
from django.dispatch import receiver
from django.db.models.signals import post_save
#receiver(post_save, sender= Admission) # it works after saving (created or updated)
def update_student_info(sender, instance, **kwargs):
# change student info based on the admissions model
admission_class = instance.classes
admission_student = instance.student
admission_student.classes = admission_class
admission_student.save()

How to undisplay the field with empty value in django admin?

I am currently working on django. I created 4 classes in models.py, one of them is ReactionMeta class. This class has 62 columns, which defined as below:
class Reactionsmeta(models.Model):
id = models.ForeignKey('Reactions', db_column='id', primary_key=True, max_length=255, on_delete=models.CASCADE)
name = models.CharField(max_length=255, blank=True, null=True)
metabolite1 = models.ForeignKey('Metabolites', db_column='metabolite1', blank=True, null=True,
on_delete=models.CASCADE)
stoichiometry1 = models.CharField(max_length=255, blank=True, null=True)
metabolite2 = models.ForeignKey('Metabolites', db_column='metabolite2', blank=True, null=True,
on_delete=models.CASCADE, related_name='+')
stoichiometry2 = models.CharField(max_length=255, blank=True, null=True)
metabolite3 = models.ForeignKey('Metabolites', db_column='metabolite3', blank=True, null=True,
on_delete=models.CASCADE, related_name='+')
stoichiometry3 = models.CharField(max_length=255, blank=True, null=True)
metabolite4 = models.ForeignKey('Metabolites', db_column='metabolite4', blank=True, null=True,
on_delete=models.CASCADE, related_name='+')
#...
Some of the reactions, may have 6 metabolites, however, some of reactions may only have 2 metabolites and stoichiometries, which means there is no value of this reaction in metabolite3,4,5,6...columns and stoichiometry 3,4,5,6...columns.
In that case, how can I only display the Charfield with data while undisplay those Charfield with no value in django-admin?
So I think there is model design issue here. For my case i would have done this as follows
class ReactionMeta(models.Model):
reaction = models.ForeignKey(Reaction, ..)
name = models.CharField(..)
data = models.ForeignKey(Data, ..)
Contructing the Data class to hold the Stoichiometry and Metabolite
class Data(models.Model):
stoichiometry = models.CharField(..)
metabolite = models.ForeignKey(..)

How can I access objects in a django model composed of two foreign keys?

These are the relevant classes of my app. I want basically understand if the a certain user (form AuthUser) is linked to a business (from BusinessInformation) by looking at UserBusinessInformation. Thanks
class AuthUser(models.Model):
password = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)
is_superuser = models.IntegerField()
username = models.CharField(unique=True, max_length=150)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.CharField(max_length=254)
is_staff = models.IntegerField()
is_active = models.IntegerField()
date_joined = models.DateTimeField()
class Meta:
managed = False
db_table = 'auth_user'
class BusinessInformation(models.Model):
business_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
lat = models.CharField(max_length=255)
lng = models.CharField(max_length=255)
formatted_address = models.CharField(max_length=255, blank=True, null=True)
locality = models.CharField(max_length=255, blank=True, null=True)
country = models.CharField(max_length=255, blank=True, null=True)
administrative_area_level_5 = models.CharField(max_length=255, blank=True, null=True)
administrative_area_level_4 = models.CharField(max_length=255, blank=True, null=True)
administrative_area_level_3 = models.CharField(max_length=255, blank=True, null=True)
administrative_area_level_2 = models.CharField(max_length=255, blank=True, null=True)
administrative_area_level_1 = models.CharField(max_length=255, blank=True, null=True)
postal_code = models.CharField(max_length=45, blank=True, null=True)
route = models.CharField(max_length=255, blank=True, null=True)
street_number = models.CharField(max_length=45, blank=True, null=True)
phone = models.CharField(max_length=255, blank=True, null=True)
phone2 = models.CharField(max_length=255, blank=True, null=True)
phone3 = models.CharField(max_length=255, blank=True, null=True)
email = models.CharField(max_length=255, blank=True, null=True)
email2 = models.CharField(max_length=255, blank=True, null=True)
email3 = models.CharField(max_length=255, blank=True, null=True)
website = models.CharField(max_length=255, blank=True, null=True)
facebook = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = False
db_table = 'business_information'
class UserBusinessInformation(models.Model):
user = models.ForeignKey(AuthUser, models.DO_NOTHING)
business = models.ForeignKey(BusinessInformation, models.DO_NOTHING)
class Meta:
managed = False
db_table = 'user_business_information'
When I try to access to UserBusinessInformation in my views, I do not manage neither using _set.
def school(request, schoolname):
school_searched = BusinessInformation.objects.get(name=schoolname)
user_linked = school_searched.userbusinessinformation_set.all()
I miss the many to many field:
class BusinessInformation(models.Model):
business_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
users = models.ManyToManyField(AuthUser,
through='UserBusinessInformation')
...
Then, in your view:
def school(request, schoolname):
school_searched = BusinessInformation.objects.get(name=schoolname)
user_linked = school_searched.users.all()
Quoting Extra fields on many-to-many relationships django docs:
For these situations, Django allows you to specify the model that will be used to govern the many-to-many relationship. You can then put extra fields on the intermediate model. The intermediate model is associated with the ManyToManyField using the through argument to point to the model that will act as an intermediary.
Let me finish with a little advice, it is true, 'These are the relevant classes of my app', but you can illustrate this sample with just few fields. Learn about How to create a Minimal, Complete, and Verifiable example
[if you want access a field that’s a ForeignKey, you’ll get the related model object just like]
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()`enter code here`
def __str__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __str__(self):
return '%s %s' % (self.first_name, self.last_name)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __str__(self):
return self.title
[you can access like that.... ]
b = Book.objects.get(id=50)
b.publisher
b.publisher.website

Make a form from models using ModelForm, Models have many Foreignkeys( one class is the foreign key for the other.)

I wanted to make a form which should be showing all the fields defined in models, wether the fields include a foreign key to some other class in the models. I am using ModelForm to generate forms.
My models look like
class Employee(Person):
nickname = models.CharField(_('nickname'), max_length=25, null=True,
blank=True)
blood_type = models.CharField(_('blood group'), max_length=3, null=True,
blank=True, choices=BLOOD_TYPE_CHOICES)
marital_status = models.CharField(_('marital status'), max_length=1,
null=True, blank=True, choices=MARITAL_STATUS_CHOICES)
nationality = CountryField(_('nationality'), default='IN', null=True,
blank=True)
about = models.TextField(_('about'), blank=True, null=True)
dependent = models.ManyToManyField(Dependent,
through='DependentRelationship')
pan_card_number = models.CharField(_('PAN card number'), max_length=50,
blank=True, null=True)
policy_number = models.CharField(_('policy number'), max_length=50,
null=True, blank=True)
# code specific details
user = models.OneToOneField(User, blank=True, null=True,
verbose_name=_('user'))
date_added = models.DateTimeField(_('date added'), auto_now_add=True)
date_modified = models.DateTimeField(_('last modified'), auto_now=True)
#models.permalink
def get_absolute_url(self):
return ('contacts_employee_detail', [str(self.id)])
class Person(models.Model):
"""Person model"""
title = models.CharField(_('title'), max_length=20, null=True, blank=True)
first_name = models.CharField(_('first name'), max_length=100)
middle_name = models.CharField(_('middle name'), max_length=100, null=True,
blank=True)
last_name = models.CharField(_('last name'), max_length=100, null=True,
blank=True)
suffix = models.CharField(_('suffix'), max_length=20, null=True,
blank=True)
slug = models.SlugField(_('slug'), max_length=50, unique=True)
phone_number = generic.GenericRelation('PhoneNumber')
email_address = generic.GenericRelation('EmailAddress')
address = generic.GenericRelation('Address')
date_of_birth = models.DateField(_('date of birth'), null=True, blank=True)
gender = models.CharField(_('gender'), max_length=1, null=True,
blank=True, choices=GENDER_CHOICES)
class Address(models.Model):
"""Street Address model"""
TYPE_CHOICES = (
('c', _('correspondence address')),
('p', _('present address')),
('m', _('permanent address')),
)
address_type = models.CharField(_('address type'), max_length=1,
choices=TYPE_CHOICES)
content_type = models.ForeignKey(ContentType,
limit_choices_to={'app_label': 'contacts'})
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
street = models.TextField(_('street'), blank=True, null=True)
city = models.CharField(_('city'), max_length=200, blank=True, null=True)
province = models.CharField(_('State/UT'), max_length=200, blank=True,
null=True)
post_code = models.CharField(_('postal code'), max_length=15, blank=True,
null=True)
country = CountryField(_('country'), default='IN')
date_added = models.DateTimeField(_('date added'), auto_now_add=True)
date_modified = models.DateTimeField(_('date modified'), auto_now=True)
So please if anyone could help me out, or suggest me some useful links from where i can get some help. Thank You!!!
Here is the documentation...
Basic usage is:
class EmployeeForm(ModelForm):
class Meta:
model = Employee
fields = ('somefield','otherfield')
etc...
fields is a optional argument, used for defining witch fields will be presented on the form... You can also override some fields using the following
class EmployeeForm(ModelForm):
otherfield = forms.CharField(...)
class Meta:
model = Employee
fields = ('somefield','otherfield')
That means, Your form is created from Employee model, "somefield" and "otherfield" will be added as form fields, and somefield will be populated directly from your model, but otherfield will be defined as if you override it in the form class...
EDIT: Overriding is used for small changes, so ,it is not right to change the data type of the field... As far as you gave the field same name, there is no problem, it will match the related model field using the name of the form field... So:
class SomeModel(Model):
somefield = CharField()
class SomeForm(ModelForm):
somefield = Charfield(Widget=...)
class Meta:
model = SomeModel
Since field names are equivalent, there is no problem...
Basic reason for overriding is, you may wish to use a widget to change the appearance of the form field(making a TextField looks like a single line Charfield) or pass some attributes (like defining cols and rows of a text field, or addng a simlpe datepicker to a datetime field. Or you may wish to use choices parameter to populate a field with value-label pairs...
You must aviod any kind of data-based changes, if you do, you might get a database level error.

Categories

Resources