Update foreign key of one model based on another model - python

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()

Related

How to select multiple items with multiple quantities in django rest framework?

Models.py
class BaseModel(models.Model):
branch = models.ForeignKey(Branch, on_delete=models.PROTECT, blank=True, null=True)
company = models.ForeignKey(
Company, on_delete=models.PROTECT, blank=True, null=True
)
class Meta:
abstract = True
class MealMenu(BaseModel):
employee = models.ForeignKey(
Employee, on_delete=models.PROTECT, null=True, blank=True
)
item_name = models.CharField(max_length=50, null=True, blank=True)
quantity = models.PositiveIntegerField()
price = models.FloatField()
def __str__(self):
return f"{self.item_name} {self.price}"
class MealOrder(BaseModel):
RECEIVED = "Received"
PENDING = "Pending"
REJECTED = "Rejected"
MEAL_CHOICES = (
("Breakfast", "Breakfast"),
("Lunch", "Lunch"),
("Dinner", "Dinner"),
)
STATUS_CHOICES = (
(RECEIVED, "Received"),
(PENDING, "Pending"),
(REJECTED, "Rejected"),
)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, null=False)
total_items = models.IntegerField(null=True, default=0)
total_amounts = models.FloatField(default=0.0)
menu = models.ForeignKey(MealMenu, on_delete=models.PROTECT)
quantity = models.PositiveIntegerField(default=1, blank=False)
meal_time = models.CharField(max_length=25, choices=MEAL_CHOICES)
employee = models.ForeignKey(Employee, on_delete=models.PROTECT)
date = models.DateField(auto_now=True)
status = models.CharField(max_length=25, choices=STATUS_CHOICES, default=PENDING)
I have two models. In First Model i have created a menu item_name,price and quantity.
In MealOrder i have foreign key MealMenu Model and created quantity field separately.
I want to select multiple items with their multiple quantities. But i can't understand the scenario.
So you could have a separate model to handle the quantity for different items in an order.
Like this:
class MealOrderItem(BaseModel):
order = models.ForeignKey(
MealOrder, on_delete=models.PROTECT, null=True, blank=True
)
quantity = models.PositiveIntegerField()
meal = ForeignKey(
MealMenu, on_delete=models.PROTECT, null=True, blank=True
)
This will help you create multiple meal menu selections for an order with each having its own quantity.

Django: how to save instance to a foreign key field based on the fields equally

So I have a user model that has a foreign key relation with class/room, I want a user to be able to press one button and all the users/students would be equally distributed throughout the class/room foreign key based on fields from the model like age, height and other fields.
so if there are 4 students 2 with age 14 and 2 with age 15 and there are two classes, the function should put one 14-year-old and one 15-year-old in 1 class and the same in the other class as well, just iterate through the users and distribute them by the selected field values equally, any resource or code snippet would be highly appreciated.
user model if needed
class User(AbstractBaseUser, PermissionsMixin):
class SEX(models.TextChoices):
MALE = "MALE", "Male"
FEMALE = "FEMALE", "Female"
id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False, unique=True)
sex = models.CharField(
_("Sex Type"), max_length=50, choices=SEX.choices, default=None, blank=True, null=True)
email = models.EmailField(
_("Email"), max_length=254, unique=True, default=None, blank=True, null=True)
student_id = models.CharField(
_("student id"), unique=True, max_length=10, blank=True, null=True)
firstname = models.CharField(max_length=250, blank=False, null=True)
middlename = models.CharField(max_length=250, blank=False, null=True)
lastname = models.CharField(max_length=250, blank=False, null=True)
grade = models.ForeignKey(Grade, verbose_name=_(
"grade"), on_delete=models.SET_NULL, blank=True, null=True)
room = models.ForeignKey(Class, verbose_name=_(
"class"), related_name="student_room", on_delete=models.SET_NULL, blank=True, null=True) // class model forignkey
age = IntegerRangeField(min_value=1, max_value=99,
default=25, blank=True, null=True)
image = models.ImageField(
_("photo"), upload_to='user/Users/profile_pic', max_length=None, blank=False, null=True)
joined_date = models.DateTimeField(
_("created at"), auto_now=False, auto_now_add=True)
has_rated = models.BooleanField(_("Has rated the app"), default=False)
...
class Meta:
verbose_name = _("User")
verbose_name_plural = _("Users")
ordering = ('-joined_date',)
objects = CustomAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['firstname', 'lastname']
def __str__(self):
return self.firstname
I have given a code snippet for you to find a solution.It might not be the efficient solution. But you shall have gist.
def assign_class(request, *args, **kwargs):
age14_users = User.objects.filter(age=14).order_by('-joined_date')
age14_users_pk_list=list(age14_users.values_list('pk', flat=True))
age15_users = User.objects.filter(age=15).order_by('-joined_date')
age15_users_pk_list=list(age15_users.values_list('pk', flat=True))
age14_users_count = len(age14_users_pk_list)
age15_users_count = len(age15_users_pk_list)
classes= Class.objects.all()
class_count = classes.count()
class_pk_list=list(classes.values_list('pk', flat=True))
slice = age14_users_count//class_count
sliced_users_list_age14=[age14_users_pk_list[i:i+slice] for i in range(0, len(age14_users_pk_list), slice)]
#output eg. [[1,2,3],[4,5,6],[7,8]]
#User will be distributed to rooms rationally
'''
if we loop through sliced user clusters.. we can assign
each cluster to room rationally
'''
new_class_pk_list = class_pk_list.copy()
for lst in sliced_users_list_age14:
for user_pk in lst:
user = User.objects.get(pk=user_pk)
user.room_id =new_class_pk_list[0]
user.save()
del new_class_pk_list[0] #delete the class after assigning
#from copied list
'''
Now you can distribute the other cluster of group (eg. age15_users)
like above
'''

Django Admin tabularInline very slow request

I have Location app in my project. There are list of countries, their states and cities.
model.py
class Country(models.Model):
class Meta:
verbose_name = 'Country'
verbose_name_plural = 'Countries'
unique_together = ['name', 'iso2'],
name = models.CharField(
max_length=255,
verbose_name=_('Country name'),
)
iso2 = models.CharField(
max_length=2,
null=True,
blank=True,
verbose_name=_('iso2'),
)
phone_code = models.CharField(
max_length=15,
null=True,
blank=True,
verbose_name=_('Phone code'),
)
def __str__(self):
return self.name
class State(models.Model):
name = models.CharField(
max_length=100,
verbose_name=_('State'),
)
country = models.ForeignKey(
Country,
on_delete=models.SET_NULL,
verbose_name=_('Country'),
related_name='states',
related_query_name='states',
null=True,
)
state_code = models.CharField(
max_length=20,
null=True,
blank=True,
verbose_name=_('State code'),
)
def __str__(self):
return self.name
class City(models.Model):
name = models.CharField(
max_length=70,
verbose_name=_('City name'),
)
state = models.ForeignKey(
State,
on_delete=models.SET_NULL,
null=True,
verbose_name=_('State'),
related_name='cities',
related_query_name='cities',
)
country = models.ForeignKey(
Country,
on_delete=models.SET_NULL,
verbose_name=_('Country'),
related_name='cities',
related_query_name='cities',
null=True,
)
def __str__(self):
return self.name
I'm trying to get list of country cities in Django admin via Tabular inline, but when I click on any country it loads very slow (about 1 minute). How to optimize it?
When I did it in Shell - Country.objects.get(name='USA').cities.all() it returns results less than 10ms
admin.py
from .models import Country, City
class CountryCitiesAdmin(admin.TabularInline):
model = City
class CountryAdmin(admin.ModelAdmin):
inlines = (CountryCitiesAdmin,)
list_display = ('name', 'iso2', 'phone_code')
search_fields = ('name', 'code', 'phone_code',)
admin.site.register(Country, CountryAdmin)
You may have to use the raw_id_fields property. What's happening is that it's pulling all of the possible values to populate the select html element. Setting raw_id_fields = ['country', 'state'] will make it an input that shows the ID of the instance instead.

Model Many to Many relations with Abstract Class

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)

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