Django: avoid data type limitation - python

I have a class which has an IntegerField attr.
In its ModelForm, in the field of this attr, I need to send a String, which later will store an Integer once it is processed in the view.
The problem is that Django doesn't allows this, and when I use form.cleaned_data.get('myattr') it's saying that it's wrong because it should be an Integer.
class Student(models.Model):
teacher = models.IntegerField(null=False) # I'm saving teacher's key here
class Teacher(models.Model:
name = models.CharField(max_length= 50, null=False)
key = models.IntegerField(null=False)
class StudentForm(forms.ModelForm):
teacher = forms.ModelChoiceField(queryset=Teacher.objects.all(), label='Select the teacher')
So, when the user is selecting the student's teacher, that select field will display the name of the teachers available. But in the model it will store their key, which I manage in view.
views.py:
teacher = form.cleaned_data.get('teacher') # it has the name
teacher = Teacher.objects.get(name=teacher).key # getting the key in order to store an Integer, but Django is banning my code before anyway.
How can I handle this without changing the data type of the model?
I even added to_field_name in the form field with the value of the Teachers' key.

One better approach here will be to setup a relationship between your student and teacher(using foregin key).
Depending of the need of your app here is how to do:
If one student can have several teachers and one teacher can have several students : https://docs.djangoproject.com/en/2.1/topics/db/examples/many_to_many/
If one student can have only one teacher but a teacher can have multiple students:
https://docs.djangoproject.com/en/2.1/topics/db/examples/many_to_one/
If one student can only have one teacher, and one teacher can only have one student:
https://docs.djangoproject.com/en/2.1/topics/db/examples/one_to_one/
This is the best way to manage this.
Then you only have to map the Student model in the Student form like:
class StudentForm(forms.ModelForm):
class Meta:
model = Student
#you can add the list of all the fields you want there
fields = ['teacher']
One extra step will be to define the str method of the model so Django will associate a string representation of your model in your form (Here for having a nice way to display Teacher in the student form).
class Teacher(models.Model):
name = models.CharField(max_length= 50, null=False)
#place other fields here ...
def __str__(self):
#if you print a Teacher django will return the string corresponding to the teacher name
return self.name

Related

It is impossible to add a non-nullable field Error when extending Abstract User

I want to extend the Base Abstract User Model and this is the extended model:
class Student(AbstractUser):
birth = models.DateField(default=datetime.date.today)
street = models.CharField(max_length=25)
street_number = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(99)])
city = models.CharField(max_length=20)
province = models.CharField(max_length=20)
code = models.IntegerField(validators=[MinValueValidator(0, MaxValueValidator(9999))])
address = str(street) + str(street_number) + str(city) + str(code) + str(province)
But I get this message popup:
It is impossible to add a non-nullable field 'password' to student without specifying a default. This is because the database needs something to populate existing rows.
However I haven't added a new password field and all the existing password fields (for the superuser) already have a value. What should I do?
When I add a default value and try to migrate it, it complains that there is no such table as 'mainApp_student'.
You don't want to do that. You want a User model (you already have one that Django provides, no need to extend it for now), and a Student model that has a OneToOne relationship with the User model.
Conceptually:
User: models a user of your application and its authentication and permissions
Student: the representation of a person attending classes, with a name, a birthday etc..., also has a user to access your application which is unique to them.
In code:
from django.db import models
from django.contrib.auth.models import User
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE))
# ... other fields: birth address etc...
This page of the docs explains it well, especially the Employee example given:
If you wish to store information related to User, you can use a OneToOneField to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.

Keeping record of foreign key fields selected in Python Django

For a project I have a two model Food and Profile. Each day one profile is created.When users adds forr the food_selected field is updated.Everytime I update the food_selected field in profile I want to keep a record of it. So that I can show all the food selected for a single day
class Food(models.Model):
name = models.CharField(max_length=200 ,null=False)
def __str__(self):
return self.name
class Profile(models.Model):
food_selected = models.ForeignKey(Food,on_delete=models.CASCADE,null=True,blank=True)
How can i solve this problem.
Thank You

Relationship between 2 models in Django

I have two models- Order and Expense. The expense is a crud list respective to the particular Order. How can I make such a relationship between these two models?
models.py - Order
class Order(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,related_name="order",blank=True,null=True)
client_name = models.CharField(max_length=100)
event_name = models.CharField(max_length=100)
contact = models.CharField(max_length=15)
event_date = models.DateField(auto_now_add=False,auto_now=False)
expenses = models.IntegerField(default=0,null=True,blank=True)
Models.py - Expense
class ProjectExpense(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,related_name="project_expense",null=True,blank=True)
order_id = models.IntegerField(default='0')
exp = models.CharField(max_length=100)
exp_desc = models.TextField(null=True,blank=True)
amount = models.IntegerField(default='0')
def __str__(self):
return self.exp
I tried assigning the field Order ID with the current Order. But how will I able to pass the current Order.
I'm guessing you need a ManyToOne Relationship: One Order can have multiple expenses?
For that you can remove the expenses property from the Order model.
And you need to modify the order_id property of the ProjectExpense model like this (as #Lambo already commented):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
When you are querying the Order model the related Expenses will be included if you ask for them and vice versa.
The Objects are created as following in the backend:
new Order:
# input contains the data received from frontend
Order.objects.create(user_id=input.user_id,
client_name=input.client_name,
event_name=input.event_name,
contact=input.contact,
event_date=input.event_date)
new Expense:
# input contains expense details received from frontend
ProjectExpense.objects.create(user_id=input.user_id,
order_id=input.order_id,
exp=input.exp,
exp_desc=input.exp_desc,
amount=input.amount)
It is important that you write order_id= although the property in the model itself is called order.
Thanks all for providing me the answers! The feature I'm looking at is GenericForeignKey. This tutorial helped me understand it.
The working of Expenses associated with the respective Order, is way similar to the Comments and Post like in blogs.

How to change field in ModelForm generated html form?

I'm making one of my first django apps with sqlite database. I have some models like for example:
class Connection(models.Model):
routeID = models.ForeignKey(Route, on_delete=models.CASCADE)
activityStatus = models.BooleanField()
car = models.ForeignKey(Car, on_delete=models.CASCADE)
class Route(models.Model):
name = models.CharField(max_length=20)
and forms
class RouteForm(ModelForm):
class Meta:
model = Route
fields = ['name']
class ConnectionForm(ModelForm):
class Meta:
model = Connection
fields = ['routeID', 'activityStatus', 'car']
And in my website, in the url for adding new Connection, I have cascade list containing RouteIDs. And I'd like it to contain RouteName, not ID, so it would be easier to choose. How should I change my ConnectionForm, so I could still use foreign key to Route table, but see RouteName instead of RouteID?
For now it's looking like this, but I'd love to have list of RouteNames, while still adding to Connection table good foreign key, RouteID
Update the Route Model's __str__ method:
class Route(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
Because the __str__() method is called whenever you call str() on an object. Django uses str(obj) in a number of places like in Modelform. By default it returns id or pk that is why you were seeing ids in model form. So by overriding it with name, you will see the names appear in choice field. Please see the documentation for more details on this.

Django Model choices based off another model

Sorry if this is confusing, I'm still a bit green with Django. So basically I have two models and I want a selection from one to have all the choices from another model. So basically:
class Show(models.Model):
venue = models.CharField(max_length=100, choices = VENUE NAME)
class Venues(models.Model):
Name = models.CharField(max_length=100)
Essentially I want the venue to have a list of the venue names that were input into that model. Is this possible?
In your case you should use many-to-one ForeignKey
It give you access to Venues object from your Show object and it simple to add this to your model.
class Show(models.Model):
venue = models.ForeignKey('Venues', on_delete=models.CASCADE)
class Venues(models.Model):
name = models.CharField(max_length=100)
To get your choices you can use:
Venues.objects.all()
And then the only thing you need is add object or ID to your Show object and save.
Choices are good too but not in this case. For example when you need some const and give user choices like this:
class Show(models.Model):
VENUES_CHOICES = (
(RESTAURANT, 'restaurant'),
(PUB, 'pub'),
)
venues = models.IntegerField(choices=VENUES_CHOICES, default=RESTAURANT)
Its great to use it in order status in my opinion.
add a str def like this in the Venues model will do
def __str__ (self):
return self.name

Categories