django 获取 前端 form 的文本数据

2023-02-18 10:39:13 浏览数 (1)

正常情况,我们都是应该采用 django 的表单处理 form 数据,有时候为了方便会直接 从 前端表单 获取 form 数据而不使用 django 的 表单验证。

一. 使用了 django 表单 处理数据

# forms.py(以本站 添加友情链接 为例子)

代码语言:javascript复制
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

代码语言:javascript复制
            <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 属性)

代码语言:javascript复制
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 也贴一下)

代码语言:javascript复制
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 (一个保存文本内容的中转页面)

代码语言:javascript复制
    <form class="form-inline" method='post' action='' enctype="multipart/form-data" id="myForm">
        {% csrf_token %}
        <div class="form-group">
            <label for="exampleInputName2">Text Paste&nbsp;</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 属性)

代码语言:javascript复制
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())

0 人点赞