【问题标题】:Django Dynamic Forms ManyToManyFieldDjango 动态表单多对多字段
【发布时间】:2019-08-12 08:35:15
【问题描述】:

我有一个问题,我想制作一个可以提交首发 XI 名单的足球联赛页面。

但我不知道如何构建动态表单。

用户(即球队所有者)可以登录以选择比赛以上传首发 XI。 网站会显示球队的球员名单,让用户选择 Max of 11 并提交。

重要的是

  1. 如何生成包含“球员所属球队”的表单。
  2. 如何让用户上传 Home / Away(球队属于用户)仅从 XI 开始。

Model.py

class Schedule(models.Model):
    schedule_name = models.CharField(max_length=7, choices=LEAGUE_CHOICES, default='nil')
    schedule_home = models.ForeignKey(Team, on_delete=models.CASCADE,default='',related_name='schedule_home')
    schedule_away = models.ForeignKey(Team, on_delete=models.CASCADE,default='',related_name='schedule_away')

class Player(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE)
    player_name = models.CharField('Player Name', max_length=30, unique=True)
    player_team = models.ForeignKey(Team ,on_delete=models.SET_DEFAULT, default=1)

class Team(models.Model):
    team_name = models.CharField('Team Name', max_length=30, unique=True)
    team_owner = models.OneToOneField(User,on_delete=models.CASCADE,related_name='owner')

class Match_Starting(models.Model):
    starting_schedule = models.OneToOneField(Schedule,on_delete=models.CASCADE)
    home_starting = models.ManyToManyField(Player,blank=True,related_name='home_starting')
    away_starting = models.ManyToManyField(Player,blank=True,related_name='away_starting')

@receiver(post_save, sender=Schedule)
    def create_match_stat(sender, instance, created, **kwargs):
        if created:
            Match_Starting.objects.create(starting_schedule=instance)

Forms.py

class MatchStartingForm(forms.ModelForm):
    class Meta:
        model = Match_Starting
        fields = '__all__'

Views.py

@login_required
def update_starting(request):
    if request.user.is_authenticated:
        try:
            selected_team = Team.objects.get(team_owner=request.user)
        except:
            return HttpResponseRedirect('/')
    if request.method == 'GET':
        selected_player = Player.objects.filter(player_team=selected_team).order_by('player_name')
        team_schedule_list = Schedule.objects.filter(schedule_time__lte=datetime.datetime.now() + datetime.timedelta(weeks=1),schedule_time__gte=datetime.datetime.now() + datetime.timedelta(minutes=30)).filter(Q(schedule_home__team_name=selected_team)|Q(schedule_away__team_name=selected_team))
        return render(request, 'update_starting/update_starting.html',{"user":request.user,"team":selected_team,"player":selected_player,"schedule":team_schedule_list})
    if request.method == 'POST':
        selected_match= get_object_or_404(Match_Starting, starting_schedule__id=request.POST.get("schedule_id"))
        request.POST = request.POST.copy()
        if selected_team == selected_match.starting_schedule.schedule_home:
            request.POST['home_starting'] = request.POST['starting']
            form = MatchStartingForm(request.POST, instance=selected_match)
            if form.is_valid():
                selected_match = form.save(commit=False)
                selected_match.save()
                form.save_m2m()
        elif selected_team == selected_match.starting_schedule.schedule_away:
            request.POST['away_starting'] = request.POST['starting']
            form = MatchStartingForm(request.POST, instance=selected_match)
            if form.is_valid():
                selected_match = form.save(commit=False)
                selected_match.save()
                form.save_m2m()
        return HttpResponseRedirect('/')

update_starting.html

<div>
    <form action="" method="post">
        {% csrf_token %}
        <select name="schedule_id">
            {% for x in schedule %}
            <option value="{{x.id}}">{{x.get_schedule_name_display}} {{x.schedule_home}} - {{x.schedule_away}}</option>
            {% endfor %}
        </select>
        {% for x in player %}
            <input type="checkbox" name="starting" value="{{x.id}}">{{x.player_name}}<br>
        {% endfor %}
        <input type="submit" class="button" value="Save">
    </form>
</div>

【问题讨论】:

  • 表单需要的是一个formset:docs.djangoproject.com/en/2.1/topics/forms/formsets
  • home/away 是在您的视图中简单检查用户是否属于您正在为其呈现视图的团队。
  • 我刚刚更新了视图表单和 html。似乎不起作用。我不知道如何保存 manytomanyfield

标签: django django-models django-forms django-views


【解决方案1】:

我怎样才能生成球员属于球队的表格。

您首先需要一个玩家表格:

class PlayerForm(forms.ModelForm):
    class Meta:
        model = Player
        fields = '__all__'

然后将其付诸实践:Django Formsets

如何让用户上传 Home / Away(球队属于用户)仅从 XI 开始。

您在这里也需要一个表格,这次也需要Schedule 模型。

@rchurch4 说:他们只是想知道如何确保用户只能为他的团队上传名册

如果是这种情况,您只需确保在您的Team 列表视图中您只列出属于经过身份验证的User 的团队。

【讨论】:

  • 第二部分你想多了。他们只想知道如何确保用户只能为他的团队上传名册。无需表格,只需查看一下即可。
  • 我刚刚更新了视图表单和 html。似乎不起作用。我不知道如何保存 manytomanyfield