python - 限制/限制在python django(梦幻体育网站)中可以选择model.foreignkey选项的次数
问题描述
在此处输入图片描述我正在制作一个梦幻体育网站。django 开箱即用的用户等于团队所有者。在我的 blog/models.py 文件中,我创建了一个类Player
(又名 NBA 球员),其外键字段player_owner
指向User
:
# blog/models.py
class Player(models.Model):
player_full = models.CharField(max_length=50)
player_owner = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
image = models.ImageField(default='default_player.jpg', upload_to='player_pics')
player_unit_value = models.PositiveSmallIntegerField(default=1, validators=[MinValueValidator(1),
MaxValueValidator(1)])
如您所见,我在 Player 类上还有一个字段,称为player_unit_value
永久设置为 1。我认为,这将与我的问题有关。我设置了很多网站:自由球员页面、团队仪表板、球员资料、财务等都建立了表单验证,以确保球员被授权登录User
(又名球队所有者) “签署”和“放弃” .
# blog/views.py
class PlayersUpdateView(LoginRequiredMixin, UpdateView, Player):
model = Player
fields = []
template_name = 'blog/player_form.html' # <app>/<model>_<viewtype>.html
context_object_name = 'guys'
def form_valid(self, form):
form.instance.player_owner = self.request.user
return super().form_valid(form)
因此,当您在我的网站上单击“添加播放器”时,该播放器的player_owner
字段会从“无”更新为User
. 而“Drop Player”按钮则相反。
所以这是我的问题:如何创建一个逻辑来限制User
(又名所有者)可以选择为player_owner
15 的次数?理想情况下,我希望有某种形式的验证——当由一个User
已经有 15 名球员的人发起时——显示一个无效的警告,上面写着“对不起,你的名单上已经有最大数量的球员了”
这是另一个可能有用的部分:我在我的 Users/models.py Profile 类上创建了一个字段,名为players_owned
:
# users/models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
players_owned = models.PositiveSmallIntegerField(default=0,
validators=[MinValueValidator(0),
MaxValueValidator(15)]
)
players_owned
我怀疑每次将 aPlayer
添加到用户的团队时(也就是每次 Player.player_owner 字段从 None 更新为 a (aka Owner)时,可能有一种方法可以将用户字段 += 1。User
但是这两个类都在不同的模型文件。
我是 python 和 django 的新手,所以如果这有点疯狂,我提前道歉。
更新代码:
博客/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from django.contrib import messages
from django.db.models import Sum, Q
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView)
from users.forms import ProfileUpdateForm
from .models import Post, Player
class PlayersUpdateView(LoginRequiredMixin, UpdateView, Player):
model = Player
fields = []
template_name = 'blog/player_form.html' # <app>/<model>_<viewtype>.html
def get(self, request, *args, **kwargs):
form = ProfileUpdateForm()
return render(request=request, template_name=self.template_name, context={
"form": form
})
def post(self, request, *args, **kwargs):
form = ProfileUpdateForm(request.POST)
if form.is_valid():
if request.user.players_owned <= 5:
form.instance.player_owner = self.request.user
request.user.players_owned = request.user.players_owned + 1
request.user.save()
return redirect("players-update")
else:
messages.error(request, "Sorry, you already have the max number of players on your roster")
return render(request, self.template_name, {'form': form})
问题:我应该Profile
从 users/models.py 导入模型吗?也许这个def不属于PlayerUpdateView
?
博客/models.py:没有改变
博客/player_form.html
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<head>
<script>
{% if messages %}
{% for message in messages %}
alert(message);
{% endfor %}
{% endif %}
</script>
</head>
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Adding {{ object.player_full }}</legend>
<img class="rounded-circle article-img" src="{{ object.image.url }}">
{{ form|crispy }}
<h4>Are you sure you want to add <kbd>{{ object.player_full }}</kbd> to your team?</h4>
</fieldset>
<div class="form-group">
<button class="btn btn-outline-success" type="submit">Add Player</button>
<a class="btn btn-outline-secondary" href="{% url 'players-detail' object.id %}">Cancel</a>
</div>
</form>
</div>
{% endblock content %}
用户/模型.py
from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
players_owned = models.PositiveSmallIntegerField(default=0,
validators [MinValueValidator(0), MaxValueValidator(15)])
用户/forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
# when submitted creates ...user
model = User
# these are the fields we want on our form
fields = ['username', 'email', 'password1', 'password2']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
# when submitted updates ...user
model = User
# these are the fields we want on our form
fields = ['username', 'email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image', 'players_owned']
问题:我应该UserUpdateForm
改用吗?
顺便说一句,这是我得到的最新错误:
NoReverseMatch at /players/529/update/
Reverse for 'players-detail' with arguments '('',)' not found. 1
pattern(s) tried: ['players/(?P<pk>[0-9]+)/$']
Request Method: GET
Request URL: http://127.0.0.1:8000/players/529/update/
Django Version: 3.0.7
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'players-detail' with arguments '('',)' not found. 1
pattern(s) tried: ['players/(?P<pk>[0-9]+)/$']
解决方案
只需修改视图的 form_valid 元素以检查 player_owned:
- - -编辑
这是我喜欢使用 get 和 post 请求创建基于类的视图的方式,然后您可以访问请求对象。如果这与您的原始代码相差太大,并且您想保留该form_valid
功能,请告诉我,我可以尝试将其更改为更接近您当前的功能。
from django.contrib import messages
类 PlayersUpdateView(LoginRequiredMixin, UpdateView, Player):
template_name = "template_name.html"
def get(self, request):
form = FORM_NAME()
return render(request=request, template_name=self.template_name, context={
"form": form
})
def post(self, request):
form = FORM_NAME(request.POST)
if form.is_valid():
if request.user.players_owned <= 15:
form.instance.player_owner = self.request.user
request.user.players_owned = request.user.players_owned + 1
request.user.save()
return redirect("wherever you want to go on success")
else:
messages.error(request, "Sorry, you already have your max number of players on your roster")
return render(request, self.template_name, {'form': form})
---编辑结束
然后在您的模板中添加它以显示消息,在这种情况下这是一个错误。如果要再次显示表单,请使用{{form.as_p}}
:
<html>
<head>
<script>
{% if messages %}
{% for message in messages %}
alert(message);
{% endfor %}
{% endif %}
</script>
</head>
<body>
{{form.as_p}}
</body>
</html>
推荐阅读
- node.js - Heroku 和 multer
- wix - 在 WiX 中将 Zip 文件添加到 TARGETDIR
- ignite - Ignet查询本地节点潜在问题?
- mysql - 用户创建时的 Mysql 错误 - 字段没有默认值
- clojure - 我可以从 uberjar 启动 Gorilla REPL 吗?
- swift - 如果这个类是通用的,如何检查一个对象是否是给定类的实例?
- python - 如何使用 to_clipboard() 提供 DataFrame 的可复制副本
- javascript - Chai 期望列表包含字符串类型的项目
- python - 使用 boto3 更新 route53 记录集的问题
- javascript - 防止点击事件在自定义事件后触发