Reputation:
I have a ManytoMany field in my model called 'games' :
class Team(models.Model):
name = models.CharField(max_length=15, null=False)
tag = models.CharField(max_length=4, null=False)
description = HTMLField(blank=True, null=True)
logo = models.FileField(upload_to=user_directory_path, validators=[validate_file_extension], blank=True, null=True)
games = models.ManyToManyField(Games, verbose_name="Jeu", null=False)
owner = models.ForeignKey(User, verbose_name="Créateur")
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name="Date de création")
update = models.DateTimeField(auto_now=True, verbose_name="Dernière modification")
def __str__(self):
return self.name
I feed my model thanks to a form :
class TeamForm(forms.ModelForm):
game = Games.objects.all()
games = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, required=True, queryset=game)
logo = forms.ImageField(required=False, widget=forms.FileInput)
class Meta:
model = Team
fields = ('name', 'tag', 'description', 'logo', 'games' )
In my other Model 'Games', I have a field 'logo'. I can show you :
class Games(models.Model):
guid = models.CharField(max_length=100, unique=True, null=False, verbose_name="GUID")
title = models.CharField(max_length=100, null=False, verbose_name="Titre")
logo = models.FileField(upload_to='media/games/', validators=[validate_file_extension], blank=True, null=True, verbose_name="Logo du jeu")
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name="Date de création")
update = models.DateTimeField(auto_now=True, verbose_name="Dernière modification")
def __str__(self):
return self.title
So, in my template I can render the ManytoMany field by calling {{form.games}}. It works fine, I have a lots of checkbox just next to the name of any games.
Now, to make more cool, I also want to display the logo of the game. The problem is that the ModelMultipleChoiceField only return the game.id and the game.title. It only returns a tuple by default.
So I am blocked...
If you have any idea, or if someone already had the same issue, please give me a solution.
Many thanks
For more details, I add my views.py and my template :
def view_team_index(request, id_team):
if request.user.is_authenticated():
media = settings.MEDIA
try:
team = Team.objects.get(id=id_team)
if team.owner == request.user:
owner = True
except:
messages.add_message(request, messages.INFO, 'Désolé, cette équipe est inconnue.')
return redirect(view_wall)
if request.method == 'POST':
#Modifier les champs de bases
if 'request_base' in request.POST:
request_base = True
form = TeamForm(instance=Team.objects.get(owner=request.user))
if 'edit_base' in request.POST:
form = TeamForm(request.POST, request.FILES, instance=Team.objects.get(owner=request.user))
if form.is_valid():
form.save()
#Modifier la description
if 'request_description' in request.POST:
request_description = True
form = TeamForm()
if 'edit_description' in request.POST:
form = TeamForm(request.POST)
return render(request, 'team_index.html', locals())
else:
messages.add_message(request, messages.INFO, 'Vous devez être connecté pour accéder à cette page.')
return redirect(view_logon)
template :
<div class="w3-row-padding margin_bottom_10">
<div class="w3-col m12">
<div class="w3-card-2 w3-round w3-white">
<div class="w3-container w3-padding container">
<div class="text_align_center">
<div><img src="{{media}}{{team.logo|default:"media/images/avatar-default-blue.png"}}" class="w3-circle logo_team" alt="Logo"></div>
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
<hr>
{{form.logo}}
<hr>
<h4>{{form.name}}</h4>
{{form.tag}}
<hr>
<div class="list">{{form.games}}</div>
<hr>
<input type="submit" value="Sauvegarder" name="edit_base" class="w3-button w3-theme-d2 w3-margin-bottom">
</form>
</div>
</div>
</div>
</div>
</div>
I tried to override the choice field, but I have an error :
games = forms.GamesChoiceField(widget=forms.CheckboxSelectMultiple, required=True, queryset=game)
AttributeError: module 'django.forms' has no attribute 'GamesChoiceField'
This is what I tried :
from django.forms import ModelMultipleChoiceField
class GamesChoiceField(ModelMultipleChoiceField):
def label_from_instance(self, obj):
logo = '<img src="{url}"/>'.format(url=obj.logo.url)
return "{title} {logo}".format(title=obj.title, logo=logo)
class TeamForm(forms.ModelForm):
game = Games.objects.all()
games = forms.GamesChoiceField(widget=forms.CheckboxSelectMultiple, required=True, queryset=game)
logo = forms.ImageField(required=False, widget=forms.FileInput)
class Meta:
model = Team
fields = ('name', 'tag', 'description', 'logo', 'games' )
Let's see my current working situation. I just want to add games.logo next to each checkbox.
Upvotes: 1
Views: 878
Reputation:
You can try to override ModelMultipleChoiceField
from django.forms import ModelMultipleChoiceField
class GamesChoiceField(ModelMultipleChoiceField):
def label_from_instance(self, obj):
logo = '<img src="{url}"/>'.format(url=obj.logo.url)
return "{title} {logo}".format(title=obj.title, logo=logo)
class TeamForm(forms.ModelForm):
game = Games.objects.all()
games = GamesChoiceField(widget=forms.CheckboxSelectMultiple, required=True, queryset=game)
more details fields-which-handle-relationships
hope it help
extra info replace
games = forms.GamesChoiceField
# ^^^^
to
games = GamesChoiceField
# ^^^^
Upvotes: 2
Reputation: 134
You have to render the choice field manually. Replacing {{form.games}}
by this:
<select name="games">
{% for game in form.games_set.all %}
<option value="{{ game.id }}">{{ game.logo }}</option>
{% endfor %}
</select>
The code is aprox. But the concept is that. Perhaps you want to use jquery/bootstrap to beautify.
Another subject it's the related name in your ManyToManyField, if you want to custom your reverse lookup, set it up.
Upvotes: -1