Filtering query inside ForeignKey - django

Let's say I have 100 players and 10 teams how can I remove any player from FroreignKey drop-down chooser that is already was chosen for another team?
inside SpielerTeamRelationshipModel I have player = models.ForeignKey(Spieler) and I would like it not to show players who have already been selected for another teams. Is this possible?
class Spieler(models.Model):
name = models.CharField(max_length=128)
vorname = models.CharField(max_length=128)
panels = [
FieldPanel('name', classname="col6"),
FieldPanel('vorname', classname="col6"),
]
class SpielerTeamRelationshipModel(models.Model):
player = models.ForeignKey(Spieler)
in_team_seit = models.DateField()
page = ParentalKey('TeamRooster',
related_name='spieler_in_team')
panels = [
FieldPanel('player', classname="col6"),
FieldPanel('in_team_seit', classname="col6")
]
class TeamRooster(Page):
content_panels = [
FieldPanel('title'),
InlinePanel(
'spieler_in_team', label="Spieler",
panels=None)
]
One Player can be only in one Team. One Team can have one or more players. Very convenient for this is InlinePanel, but every time to choose one player from 100, it's excruciating.
Or maybe I'm not doing the right thing and there's a smarter way to solve this problem?

Strange but no one have mentioned unique_together. It will help you to create unique relations between team and player.
class Player(models.Model):
name = models.CharField(max_length=128)
team = models.ForeignKey(Team, blank=True, null=True)
class Meta:
...
unique_together = ("id", "team")
or sometimes you will need this
class Meta:
...
unique_together = ("name", "team")
Good luck!

Instead of having a player as FK in team
You can solve the problem by having team as FK in Player table

Related

How to set initial value for all students to present in College management system | django admin inline

I am building College management system in django including features such as quiz, lms and attendance and so on.
I want list all students with status=True by default in django admin inline. So teacher dont have to hammer the status checkbox for every student, every student should be present(status=True)by default and teacher only have to uncheck the status for whom who are absent. I have googled a lot but having hard time figuring out the solution. This is what I want:
As you can see all the students are present Status=True, this should be the default behaviour
My model:
class Attendance(models.Model):
course = models.ForeignKey(settings.COURSE_MODEL, on_delete=models.CASCADE)
date = models.DateField(default=datetime.now)
class AttendanceStatus(models.Model):
attendance = models.ForeignKey(Attendance, on_delete=models.CASCADE)
student = models.ForeignKey(settings.STUDENT_MODEL, on_delete=models.CASCADE)
status = models.BooleanField()
And here is the admin.
class AttendanceStatusInline(admin.TabularInline):
model = AttendanceStatus
can_delete = False
fields = [ 'student', 'status' ]
autocomplete_fields = [ 'student' ]
#admin.register(Attendance)
class AttendanceAdmin(admin.ModelAdmin):
list_display = [ 'course', 'date']
autocomplete_fields = ['course']
inlines = [ AttendanceStatusInline ]
Thanks in advance.
As others have commented, adding the argument "default='True'" to your model field will do the trick. In the case where you find you need more than a "yes or no" but still want a default, you could do something like:
ATTENDANCE_CHOICES = [
('Present', 'Present'),
('Absent', 'Absent'),
('Late', 'Late'),
('Excused Absence', 'Excused Absence'),
]
class AttendanceStatus(models.Model):
attendance = models.ForeignKey(Attendance, on_delete=models.CASCADE)
student = models.ForeignKey(settings.STUDENT_MODEL, on_delete=models.CASCADE)
status = models.CharField(max_length=100, choices=ATTENDANCE_CHOICES, default=ATTENDANCE_CHOICES[0][0])
This will create a dropdown for your field with a default set as the first choice in the list, in this case 'Present'. The first string in each tuple of the choices list will be saved to the database. The second string is visible to the user, so you could change these if there is a use case.

How to retrieve related instances without FK using one query in django

Imagine there are three models named Movie, Actor, and Participation.
class Movie(models.Model):
identifier = models.CharField()
class Actor(models.Model):
name = models.CharField()
class Participation(models.Model):
movie_identifier = models.CharField()
actor = models.ForgeinKey(Actor, on_delete=models.CASCADE)
Let's assume that I can't use ForgeinKey for the movie in the Participation model.
how can I retrieve all the participation records of a movie with only one query?
Here is the solution if I had a foreign key for the movie in the participation table:
qs = Movie.objects.filter(identifier="an_identiier").prefetch_related("participations_set")
How can I do this without having a Movie foreign key in the Participation model?
Thanks!
One of the most important things when designing a database (hence when designing your models) is database normalization [Wikipedia].
You talk about Participation being related to multiple models like Movie, Series, Episode, etc. this means that Movie, Series, Episode all can be said to have something in common or they can be said to be a specialization of another entity let us say Participatable for the lack of a better word, or we can say Participatable is a generalization of Movie, Series, Episode, etc.
How do we model these? Well we will just have an extra model that our other models will have a OneToOneField with:
class Participatable(models.Model):
# Any common fields here
MOVIE = 'M'
SERIES = 'S'
TYPE_CHOICES = [
(MOVIE, 'Movie'),
(SERIES, 'Series'),
]
subject = models.CharField(max_length=1, choices=TYPE_CHOICES)
class Movie(models.Model):
# uncommon fields
participatable = models.OneToOneField(
Participatable,
on_delete=models.CASCADE,
related_name='movie',
)
class Series(models.Model):
# uncommon fields
participatable = models.OneToOneField(
Participatable,
on_delete=models.CASCADE,
related_name='series',
)
class Participation(models.Model):
participatable = models.ForgeinKey(Participatable, on_delete=models.CASCADE)
actor = models.ForgeinKey(Actor, on_delete=models.CASCADE)
Other than this solution which I find is the best for such modelling you can go with using the content-types framework which will essentially do what you do currently. That is it will use a field that stores the related id and also a foreign key that points to an entry in a table that will simply describe which table this id is for.

Django model select players to play

i have Match and Game table, i want to choose players who will play in this match (bacause a team include more than 5 players. However a match play 5vs5)
class Match(models.Model):
name=models.CharField(max_length=255)
slug=models.SlugField(unique=True,max_length=255)
team1=models.ForeignKey('Team',related_name='team1',on_delete=models.PROTECT)
team2=models.ForeignKey('Team',related_name='team2',on_delete=models.PROTECT)
class Game(models.Model):
name = models.CharField(max_length=255)
match = models.ForeignKey(Match, on_delete=models.CASCADE)
team1players=models.ManyToManyField(match.team1.player.all())
team2players=models.ManyToManyField(match.team1.player.all())
Error: 'ForeignKey' object has no attribute 'team1'
Instead of having team1players and team2players in your Game model, you can add a ForeignKey field called something like current_game in your Player model and dynamically assign the current Game object to each 5 players from a team. Here is an example:
# models.py, Player model
class Player(models.Model):
name = models.CharField(max_length=255)
team = models.ForeignKey(Team)
# ... other fields ...
current_game = models.ForeignKey(Game, blank=True, null=True, related_name='current_players')
# ------------------------------------------------
# views.py
game = Game(name='Sample game')
# some operations
player1.current_game = game
player1.save()
game.save()
# You can access for current players in the game in team order like:
current_players_in_game = game.current_players.values('team', 'name').order_by('team')

django - how do i make a drop down field that is tied to the database?

i just want a dropdown field - kind like below:
Sex: | Male |v|
| Female |
you know, a very very standard drop down.
I've created this to that end:
class Relationship(models.Model):
SEX = [
("M","Male"),
("F","Female")
]
title = models.CharField(max_length=100)
sex = models.ChoiceField(label='', choices=SEX)
i will handle the label in the template on my own, hence the label=""
The problem is this: when i run syncdb, django freaks out, because below all this is:
class RelationshipForm(forms.ModelForm):
class Meta:
model = Relationship
ordering = ['create_date']
fields = ('title','sex')
Sadly, this causes me to get this exception:
django.core.exceptions.FieldError: Unknown field(s) (sex) specified for Relationship
What the heck am i meant to do? To be clear:
i want the relationship database table created to have a "sex" field that holds, well, either Male or Female
i want the wee dropdown to show up when you make a new relationship.
I'm sure this is super simple, any ideas?
There is no ChoiceField in models. You want CharField with choices as below.
sex = models.CharField(max_length=1, label='', choices=SEX)
Alternatively:
class Profile(models.Modell):
"""
User profile model
"""
PROF = 1
DR = 2
MR = 3
MRS = 4
MS = 5
PROFESSION_TITLE = ((PROF, 'Prof.'),
(DR, 'Dr.'),
(MR, 'Mr'),
(MRS, 'Mrs'),
(MS, 'Ms'),)
# personal details
user = models.ForeignKey(User, unique=True)
title = models.IntegerField('Title', choices=PROFESSION_TITLE,
max_length=25, blank=True, null=True)
See this link: http://www.b-list.org/weblog/2007/nov/02/handle-choices-right-way/
Argh. I see what i was doing wrong - elementary mistake. I'll keep this up here for now, unless everyone here thinks that this is the sort of elementary thing that is unnecessary # SO
In the Model:
class Relationship(models.Model):
title = models.CharField(max_length=100)
sex = models.CharFieldField(max_length=100)
in the Form:
class RelationshipForm(forms.ModelForm):
class Meta:
model = Relationship
ordering = ['create_date']
fields = ('title','sexField')
SEX = [
("M","guy"),
("F","girl")
]
sexField = ChoiceField(label='', choices=SEX)
def clean(self):
cleaned_data = super(RelationshipForm, self).clean()
self.instance.sex = (self.cleaned_data.get('sexField',None) )

Pre-Populating Model-Formsets With Multiple Model Instances

I am building a football predictions app whilst learning django and have the following models:
class Team(models.Model):
Name = models.CharField(max_length=30)
class Fixture(models.Model):
HomeTeam = models.ForeignKey(Team, related_name='HomeTeamRef')
AwayTeam = models.ForeignKey(Team, related_name='AwayTeamRef')
HomeTeamScore = models.IntegerField(null=True, blank=True)
AwayTeamScore = models.IntegerField(null=True, blank=True)
Date = models.DateField()
class Player(models.Model):
User = models.ForeignKey(User)
DefaultHomeScore = models.IntegerField()
DefaultAwayScore = models.IntegerField()
class Prediction(models.Model):
Fixture = models.ForeignKey(Fixture)
HomeTeamScore = models.IntegerField()
AwayTeamScore = models.IntegerField()
Date = models.DateTimeField()
Player = models.ForeignKey(Player)
I have many fixture objects populated and have been using model formsets based on the Prediction model to render a view which allows the user to enter scores.
The problem is that they must choose which fixture the prediction relates to. I would like to pre-populate this so they get a list of fixtures and just enter the hometeamscore and awayteamscore. This involves pre-poulating the Prediction.Fixture field and Prediction.Player field but I am unsure on how to go about this?
Any help is much appreciated.
Edit: The problems seems to be how to pass multiple instances of Fixture into a Prediction model formset, I have seen examples of passing one but would like to do this all in one go.
I also would like the user to be able to make one Prediction per Fixture.
I think this is what you are looking for:
https://docs.djangoproject.com/en/1.7/topics/forms/formsets/#using-initial-data-with-a-formset
Your code would look something like this:
initial_data = []
for fixture in fixtures:
initial_data.append({'Player':player,'Fixture':fixture})
formset = MyPredictionFormset(initial=initial_data)
P.S. Not to be pedantic, but your field names are not PEP 8 compliant. They should be lowercase with underscores, but it's your call. (http://www.python.org/dev/peps/pep-0008/)