正常情况,我们都是应该采用 django 的表单处理 form 数据,有时候为了方便会直接 从 前端表单 获取 form 数据而不使用 django 的 表单验证。
一. 使用了 django 表单 处理数据
# forms.py(以本站 添加友情链接 为例子)
from django import forms
from django.forms.widgets import TextInput
from blog.models import FriendsURL
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4549.400 QQBrowser/9.7.12900.400"
}
web_error_status = [500, 502, 503, 400, 404]
class FriendsURLForm(forms.ModelForm):
signer_value = forms.CharField()
def clean_site_link(self):
site_link = self.cleaned_data.get("site_link").strip()
try:
req = requests.get(site_link, headers=headers, timeout=5)
if req.status_code in web_error_status:
logger.info("友情链接打开失败:%s" % site_link)
raise forms.ValidationError("网站链接无法连接,请检查网站链接填写是否正确")
else:
logger.info("友情链接打开成功:%s" % site_link)
return site_link
except Exception as e:
logger.error(e)
raise forms.ValidationError("网站链接无法连接,请检查网站链接填写是否正确")
class Meta:
model = FriendsURL
fields = ['name', 'contact', 'site_name', 'site_link', 'site_description']
widgets = {
'name': TextInput(attrs={'placeholder': '怎么称呼您'}),
'contact': TextInput(attrs={'placeholder': '邮箱和网站链接与上次一致时可以修改其他信息'}),
'site_name': TextInput(attrs={'placeholder': '友情链接显示名称,认真填写哦'}),
'site_link': TextInput(attrs={'placeholder': '邮箱和网站链接与上次一致时可以修改其他信息'}),
'site_description': TextInput(attrs={'placeholder': '介绍您或者您的网站'}),
}
# friend_url_add.html
<form method="post" action="{% url "blog:friendUrlAdd" %}" class="am-form am-g">
{% csrf_token %}
<fieldset id="form">
{% for error,values in form.errors.items %}
<span class="am-text-danger">{{ values }}</span>
{% endfor %}
<div class="am-form-group">
<label for="{{ form.name.id_for_label }}">{{ form.name.help_text }}</label>
{{ form.name }}
<small class="am-text-danger">{{ form.name.errors }}</small>
</div>
<div class="am-form-group">
<label for="{{ form.contact.id_for_label }}">{{ form.contact.help_text }}
<small>【为您保密】</small>
</label>
{{ form.contact }}
<small class="am-text-danger">{{ form.contact.errors }}</small>
</div>
<div class="am-form-group">
<label for="{{ form.site_name.id_for_label }}">{{ form.site_name.help_text }}</label>
{{ form.site_name }}
<small class="am-text-danger">{{ form.site_name.errors }}</small>
</div>
<div class="am-form-group">
<label for="{{ form.site_name.id_for_label }}">{{ form.site_link.help_text }}</label>
{{ form.site_link }}
<small class="am-text-danger">{{ form.site_link.errors }}</small>
</div>
<div class="am-form-group">
<label for="{{ form.site_description.id_for_label }}">{{ form.site_description.help_text }}</label>
{{ form.site_description }}
<small class="am-text-danger">{{ form.site_description.errors }}</small>
</div>
{# <div class="am-form-group">#}
{# <input type="hidden" name="signer_value" value="{{ signer_value }}" placeholder="">#}
{# </div>#}
<div class="am-form-group">
<button type="submit" class="am-btn am-btn-default">提交友链</button>
</div>
</fieldset>
</form>
# views.py (name = form.cleaned_data['name'], name 是前端表单 input 类型的 name 属性)
from blog.forms import FriendsURLForm
from ipware.ip import get_ip
def friend_url_add(request):
ip = get_ip(request)
logger.info("IP: %s 访问添加友链页面" % ip)
ip_encrypt = calc_md5(ip, str(int(time.time())))
signer = MyTimestampSigner()
signer_value = signer.sign(ip_encrypt)
friend_url_count_today = FriendsURL.objects.filter(time_create__year=datetime.now().year,
time_create__month=datetime.now().month,
time_create__day=datetime.now().day).count()
if friend_url_count_today >= 5:
return HttpResponse("今日新增友链已达上限,请明日再来!如还需添加请发邮件至:yin@zhuoqun.info")
# if this is a POST request we need to process the form data
if request.method == 'POST':
logger.info(request.POST)
# return HttpResponseForbidden() # post 请求时被拒
# create a form instance and populate it with data from the request:
form = FriendsURLForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
signer_value = form.cleaned_data['signer_value']
signer.unsign(signer_value, min_age=10, max_age=60 * 10)
name = form.cleaned_data['name']
contact = form.cleaned_data['contact']
site_name = form.cleaned_data['site_name']
site_link = form.cleaned_data['site_link']
site_description = form.cleaned_data['site_description']
# 更新的部分
defaults = {
'name': name,
'site_name': site_name,
'site_description': site_description,
'ip': ip
}
friend_url_ip_count = FriendsURL.objects.filter(ip=ip).count()
friend_url_single_ip_max_num = 1 # 单个 IP 注册的最大友链数量
if friend_url_ip_count < friend_url_single_ip_max_num:
# 先查 site_link 是否存在,存在就更新 defaults, 不存在就创建新的
FriendsURL.objects.update_or_create(site_link=site_link, contact=contact, defaults=defaults)
return HttpResponseRedirect(reverse('blog:friendUrlAll'))
else:
friend_url_exist = FriendsURL.objects.filter(site_link=site_link).filter(contact=contact).exists()
if friend_url_exist:
FriendsURL.objects.update_or_create(site_link=site_link, contact=contact, defaults=defaults)
return HttpResponseRedirect(reverse('blog:friendUrlAll'))
else:
logger.warning("IP: %s 提交了友链数据超单个 IP 限制" % ip)
return HttpResponse("新增友链已达上限!如还需添加请发邮件至:yin@zhuoqun.info")
# if a GET (or any other method) we'll create a blank form
else:
form = FriendsURLForm()
return render(request, "friend_url_add.html", locals())
# models.py (顺手把 友链 model 也贴一下)
class FriendsURL(models.Model):
"""
友情链接
"""
category_choice = (
("0", "友链未审"),
("1", "友情链接"),
('2', "常用网站"),
)
name = models.CharField(max_length=20, verbose_name="用户名称", help_text="您的昵称")
contact = models.EmailField(max_length=250, verbose_name="用户邮箱", help_text="您的邮箱")
site_name = models.CharField(max_length=20, verbose_name="网站名称", help_text="您的网站名称")
site_link = models.URLField(max_length=256, verbose_name="网站链接", help_text="您的网站链接")
site_description = models.CharField(max_length=50, verbose_name="您的描述", default="",
help_text="一句话介绍您或您的网站")
show_status = models.BooleanField(default=True, verbose_name="显示状态")
show_priority = models.IntegerField(default=1, verbose_name="显示权重", help_text="权重值越大越靠前")
category = models.CharField(max_length=32, choices=category_choice, default="0", verbose_name="链接类别")
ip = models.GenericIPAddressField(default="0.0.0.0", verbose_name="保存 IP")
notes = models.CharField(max_length=50, blank=True, null=True, verbose_name="备注")
time_create = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
time_update = models.DateTimeField(blank=True, null=True, auto_now=True, verbose_name="更新时间")
class Meta:
# unique_together = (('contact', 'site_link'),) # 如果存在,数据重复时就不能通过 form.is_valid()
verbose_name = "友情链接"
verbose_name_plural = "友情链接列表"
def __str__(self):
return self.site_name
二. 未使用 django 表单
# clipboard.html (一个保存文本内容的中转页面)
<form class="form-inline" method='post' action='' enctype="multipart/form-data" id="myForm">
{% csrf_token %}
<div class="form-group">
<label for="exampleInputName2">Text Paste </label>
<a id="url" href="#">→</a>
<input name="content" type="text" class="form-control" placeholder="Text input" required="required">
</div>
<button type="submit" class="btn btn-info">Save</button>
</form>
# views.py (request.POST.get("content", None),content 是前端表单 input 标签的 name 属性)
from .models import Clipboard
def clipboard(request):
contents = Clipboard.objects.filter(is_show=True).order_by("-update_time")
order = request.GET.get("order", None)
title = "Clipboard"
if request.method == "POST" and request.POST:
content = request.POST.get("content", None)
if content:
clipboards = Clipboard.objects.filter(text=content)
clipboards_exists = clipboards.exists() # 布尔值
if not clipboards_exists:
if order == "1":
Clipboard(text=content, is_order=True).save()
else:
Clipboard(text=content).save()
else:
clipboards.update(update_time=timezone.now())
return render(request, "clipboard_error.html", locals())
if order == "1":
contents = Clipboard.objects.filter(is_order=True).order_by("-update_time")
title = "清单"
return render(request, "clipboard.html", locals())