Pass model objects to choices field in django - python

I have a model called Student that has a manytomany relationship with a model called Courses. I have another model called Attend in which I want to get all the courses the student is taking and pass it in as a select menu containing the courses the student is taking. I tried to get the id using the foreign key "student" and then get courses belonging to that student and put it in a list and pass it to choices but it didn't work obviously. I would like to know how I can get the courses belonging to the student to appear in the select menu.
Here is my model.
class Attend(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE, default="")
time_signed_in = models.DateTimeField(auto_now_add=True)
isSignedIn = models.BooleanField(default=False)
# Below does not work, I get an error 'ForeignKey' object has no attribute 'id'
#courses = User.objects.get(id=student.id).courses
course = models.ForeignKey(Course, on_delete=models.CASCADE)

To render the courses the student is taking you should try using django forms.
If I understand correctly, you want a form that uses ModelMultipleChoiceField:
Allows the selection of one or more model objects, suitable for
representing a many-to-many relation.
class AttendForm(forms.Form):
courses = forms.ModelMultipleChoiceField(queryset=Courses.objects.filter(student__id=id))
That exapmple would only work to show the data to the user and then retrieving its choice. There is a slightly different approach to this case and that is using a ModelForm.
Every ModelForm also has a save() method. This method creates and saves a database object from the data bound to the form.
ModelForm is a "database driven" form in which you can perform many task involving calls to the database easily.
Note: The queryset I used in the example is just an example, you dont have to use it that way.

Related

Django - Team/User relationships

I'm at a loss... I'm just learning Django and I am really rather confused about how to make a field work the way I would like it to.
I understand that Django has a native "Groups" model. However, I am looking to build my own teams model for customization and practice.
Here is my models.py file for my Users app:
from django.db import models
from django.contrib.auth.models import User
class Team(models.Model):
members = models.ManyToManyField(User)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
admin = models.BooleanField("Admin Status")
Here's where I'm confused. I would like to be able to call the team that the user is part of directly from User.Profile. So, I want to add a field to my Profile class that will automatically populate with the team name when a user is added to a team.
A potential problem I can see is that, currently, I can assign a user to multiple teams. This doesn't bother me, perhaps I can have a Profile model field that automatically populates with a list of all the teams that the user is associated with. Regardless, I can't figure out what type of field I would need to use, or how to do this.
Does that make sense?
A potential problem I can see is that, currently, I can assign a user to multiple teams.
Indeed, you can however easily retrieve the Teams the myprofile object is a member of with:
Team.objects.filter(members__profile=myprofile)
You thus can make a property for the Profile model:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
admin = models.BooleanField("Admin Status")
#property
def teams(self):
return Team.objects.filter(
members__profile=self
)
Then you thus access the Teams of a myprofile with myprofile.teams.
So, I want to add a field to my Profile class that will automatically populate with the team name when a user is added to a team.
From my limited knowledge of database, you can add a name field to your Team model.
Keeping in mind your requirement as mentioned in question, i would suggest you to use django reverse relations to get all the teams the profile is associated with
user_teams = User.objects.get(id='user_id').profile_set.all()[0].team_set.all()
to know more about django ORM reverse relation, here is a very short article

Django user customization database tables

I am trying to build a Django website where the user is able to create custom objects known as items. Each item needs to be able to have certain properties that are stored in the database. For example an item would need properties such as
Serial Number,
Description,
Manufacture Date
However I want the user to be able to specify these fields similar to what Microsoft dynamics allows . For example a user should be able to specify they want a text field with the name Model Number, associated with a specific item type and from then on they can store those properties in the database.
I am not sure the best approach to do this because a standard database model, you already have all the fields defined for a specific table, however this essentially means i have to find a way to have user defined tables.
Does anyone know a good approach to handle this problem, at the end of the day I want to store items with custom properties as defined by the user in a database.
thanks
There are multiple ways you can go.
In non-relational databases you don't need to define all the fields for a collections ( analogous to a table of RDBMS).
But if you want to use SQL with Django, then you can define a Property Model.
class Property(models.Model):
name = CharField()
value = CharField()
item = models.ForeignKey(Item, on_delete=models.CASCADE)
class Item(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
You can render a FormSet of Property form. To add extra empty forms on the fly, render dynamic formsets.

Django: Creating multiple class instances on a single webpage, with Foreign Key dependencies

I have the following code in my models.py:
class Application(models.Model):
team_name = models.CharField(max_length=100)
...
class Participant(models.Model):
name = models.CharField(max_length=100)
grade = models.SmallIntegerField(choices=GRADE_CHOICES, blank=True, null=True)
application = models.ForeignKey(Application, related_name="participants")
...
i.e. There are multiple Participants, and each Participant will be on a single application. (It is defined that each Application will have exactly 8 Participants).
The intended purpose of this code is that a user will be able to create a new application, on which he/she will name 8 Participants. When the Application is created, 8 new instances of Participants should also be created and linked such that each Participant has the newly created Application as its Foreign Key.
I am currently struggling to create a form/view that will handle this creation process. I want the user to be a presented a single webpage that presents input forms that allow the user to create a new Application (name, etc.), along with 8 new Participants (each having a name, grade, etc.)
My current forms.py has:
class ApplicationForm(forms.ModelForm):
"""
A form that edits an application and all of its participants.
"""
nationality = forms.CharField(disabled=True, required=False)
class Meta:
model = Application
fields = '__all__'
But I realize that this does not display to the user what is needed to create 8 new Participants with the creation of this Application. How can I modify my forms.py to include space for the user to create 8 Participants with the creation of an Application?
The only solution I can come up with is to manually list 8 Participant form calls in a single view, but I feel that there must be a better solution.
What you are looking for is django formsets
A formset is a layer of abstraction to work with multiple forms on the
same page. It can be best compared to a data grid. Let’s say you have
the following form:
There is also a ModelFormSet
Like regular formsets, Django provides a couple of enhanced formset
classes that make it easy to work with Django models.
These can be used to create several instances of a given model in a single page. The only trouble is that it has a bit of a learning curve and the user experience isn't as great as what you might get with Angular or React.

Django - order many to many relation on id of intermediary model without using through

I am facing issue while sorting many to many field.
I have many to many relationship on hobbies field.
I want to keep the order user adds the hobbies. This can be done by sorting the records on intermediate model id.
Many people suggested to use through and add some field for ordering.
But this creates problem while I create records using add function of related model.
Is there any way to provide meta ordering to intermediary model so it can sort by id when I access data.
My model is as -
class User(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
hobbies = models.ManyToManyField('UserHobby')
class UserHobby(models.Model):
hobby = models.CharField(max_length=100)
Meta ordering can be provided if you explicitly define a through model. If not, you can still use the order_by() method of the QuerySet object to provide the ordering that you want as below
user = Users.objects.get(id=1)
user.hobbies.all().order_by('id')

Model friends table in Django

I am trying to write a model for Contacts table (like on mobile phone) in Django.
My first idea was to create class Person which will have fields(name, phone, email, age, creation_date...), and to create class Contact that will have two fields (person1, person2). That means that person1 has person2 in contact list, but not vice versa.
But, now I read some more about Django, and I saw that I should better extend User model like this:
class Person(models.Model):
user = models.OneToOneField(User)
And then I am not sure should I have Contact class, that will have 2 persons as I planned, or I should add one more field to Person class, like this:
class Person(models.Model):
user = models.OneToOneField(User)
contacts = models.ManyToManyField('self', related_name='contact_of', symmetrical=False)
What do you think, which approach is better / more correct?
Thanks!
The approach with the ManyToMany field looks good enough. If you were to create another model to hold this manually you would need to add logic to avoid duplication (maybe other things too).
Also, with the ManyToMany you end up with users that have contacts...you can for example do this:
my_user.person.contacts.all()
my_user.person.contacts.add(another_user)
my_user.person.contacts.filter(phone='123456')
With the other approach you would need to run queries from Contact model:
Contact.objects.filter(user_1=pk1, user_2=pk2)
Contact.objects.create(user_1=pk1, user_2=pk2) # add logic or db constraints to prevent duplication
It is not that complicated, but the first one does make more sense for this case.

Categories