今日概要:
背景:某个公司后台管理项目。
垃圾
def register(request):
""" 用户注册 """
# 1.获取提交数据
mobile = request.POST.get("mobile")
sms = request.POST.get("sms")
name = request.POST.get("name")
age = request.POST.get("age")
email = request.POST.get("email")
password = request.POST.get("password")
# 2.校验判断(10行)
# all([mobile,sms])
# 正则表达式
# 3.业务逻辑代码
框架(内置+第三方表单验证组件)
<form method="post">
<input type="text" name="mobile1" />
{{form.mobile1}}
<input type="text" name="sms" />
{{form.sms}}
<input type="submit" value="提交" />
</form>
class MyForm(Form):
mobile1 = forms.CharField(reg="\d{11}", required=True)
sms = forms.CharField(required=True)
def register(request):
""" 用户注册 """
if request.method == "GET":
# form = MyForm(instance={"mobile1":"18766666666","sms":"999"})
form = MyForm()
return render(request, "xxxxx.html",{"form":form})
# 1.获取提交数据
form = MyForm(request.POST)
if form.is_valid():
print(form.cleared_data)
else:
print(form.errors)
# 3.业务逻辑代码
return render(request, "xxxxx.html",{"form":form})
关于组件:表单验证、自动生成HTML标签、数据初始化(新建按钮、编辑按钮)、保持原来的数据。
基于注册为例来进行测试。
详细见示例:1-form组件.zip
对象和可迭代对象。
手动操作
class RegisterForm(forms.Form):
v1 = forms.CharField(
label="手机号",
required=True,
# max_length=19,
# min_length=6,
initial="武沛齐",
validators=[RegexValidator(r'^\d{11}$', "手机号格式错误"), ],
widget=forms.TextInput(attrs={"class":"form-control"}) # <input type="text" class="form-control"/>
)
v2 = forms.CharField(
label="备注",
required=True,
widget=forms.Textarea(attrs={"class":"form-control"}) # <textarea class="form-control"/></textarea>
)
...
....
.....
{% for field in form %}
<p>{{ field.label }} {{ field }} {{ field.errors.0 }} </p>
{% endfor %}
自动操作(找到每个字段中的widget插件,再找到插件中的attrs属性,给他每个赋值**{“class”:“form-control”}**
class RegisterForm(forms.Form):
v1 = forms.CharField(...,widget=forms.TextInput)
v2 = forms.CharField(...,widget=forms.TextInput(attrs={"v1":"123"}))
def __init__(self,*args,**kwargs):
super().__init__(self,*args,**kwargs)
for name,field in self.fields.items():
if name == "v1":
continue
if field.widget.attrs:
field.widget.attrs.update({"class":"form-control"})
else:
field.widget.attrs = {"class":"form-control"}
form = RegisterForm() # __init__
form = RegisterForm(data=request.POST) # __init__
class BootStrapForm(object):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs = {"class": "form-control"}
class LoginForm(BootStrapForm, forms.Form):
user = forms.CharField(label="用户名", widget=forms.TextInput)
pwd = forms.CharField(label="密码", widget=forms.TextInput)
def login(request):
form = LoginForm()
return render(request, "login.html", {"form": form})
class BootStrapForm(forms.Form):
def __init__(self, *args, **kwargs):
# 不是找父类
# 根据类的mro(继承关系),去找上个类
# super().__init__(*args, **kwargs)
for name, field in self.fields.items():
field.widget.attrs = {"class": "form-control"}
class LoginForm(BootStrapForm):
user = forms.CharField(label="用户名", widget=forms.TextInput)
pwd = forms.CharField(label="密码", widget=forms.TextInput)
def login(request):
form = LoginForm()
return render(request, "login.html", {"form": form})
类的内部继承关系,是继续c3算法。
class A:
pass
class B:
pass
class C(B,A):
pass
# [<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
print(C.mro())
老师 假如我们通过继承BootStrapForm实现批量给field对象添加{'class': 'form-control'}属性,那还能添加判断是否存在属性,若存在则更新;不存在再进行添加吗
使用Form
创建Form类 + 定义字段
class LoginForm(forms.Form):
user = forms.CharField(label="用户名", widget=forms.TextInput)
pwd = forms.CharField(label="密码", widget=forms.TextInput)
视图
def login(request):
if request.method == "GET":
form = LoginForm()
return render(request, "login.html", {"form": form})
form = LoginForm(data=request.POST)
if not form.is_valid():
# 校验失败
return render(request, "login.html", {"form": form})
print(form.cleaned_data)
# ...
return HttpRespon("OK")
前端
<form>
{% for field in form %}
<p>{{ field.label }} {{ field }} {{ field.errors.0 }}</p>
{% endfor %}
</form>
使用ModelForm
models.py
class UserInfo(models.Model):
name = models.CharField(verbose_name="用户名", max_length=32)
age = models.IntegerField(verbose_name="年龄")
email = models.CharField(verbose_name="邮箱", max_length=128)
创建ModelForm
class LoginForm(forms.ModelForm):
mobile = forms.CharFiled(label="手机号")
class Meta:
model = models.UserInfo
fileds = ["name","age", "mobile"]
视图使用
def login(request):
form = LoginModelForm()
return render(request, "login.html", {"form": form})
页面
<form>
{% for field in form %}
<p>{{ field.label }} {{ field }} {{ field.errors.0 }}</p>
{% endfor %}
</form>
注意:
后续进行增伤改查是基于数据库Models中的某个表,推荐使用:ModelForm;
如果要进行表单校验是与数据库的表无关直接使用Form。
Form
class LoginForm(BootStrapForm, forms.Form):
user = forms.CharField(label="用户名", widget=forms.TextInput)
pwd = forms.CharField(label="密码", widget=forms.TextInput)
def login(request):
form = LoginForm(initial={"user": "武沛齐", "pwd": "123"})
return render(request, "login.html", {"form": form})
ModelForm
class LoginModelForm(BootStrapForm, forms.ModelForm):
mobile = forms.CharField(label="手机号", widget=forms.TextInput)
class Meta:
model = models.UserInfo
fields = ["name", "age", "mobile"]
widgets = {
"age": forms.TextInput,
}
labels = {
"age": "x2",
}
def clean_name(self):
value = self.cleaned_data['name']
# raise ValidationError("....")
return value
def login(request):
user_object = models.UserInfo.objects.filter(id=1).first()
form = LoginModelForm(instance=user_object, initial={"mobile": "武沛齐"})
return render(request, "login.html", {"form": form})
Form组件
def login(request):
if request.method == "GET":
form = LoginForm(initial={"user": "武沛齐", "pwd": "123"})
return render(request, "login.html", {"form": form})
form = LoginForm(data=request.POST)
if not form.is_valid():
return render(request, "login.html", {"form": form})
# form.cleaned_data
# 手动读取字典,保存至数据库
# models.UserInfo.objects.create(name=form.cleaned_data['xx'], pwd=form.cleaned_data['yy'])
return HttpResponse("成功")
ModelForm组件
def login(request):
if request.method == "GET":
form = LoginForm()
return render(request, "login.html", {"form": form})
form = LoginForm(data=request.POST)
if not form.is_valid():
return render(request, "login.html", {"form": form})
form.save() # 自动将数据新增到数据库
return HttpResponse("成功")
Form组件
def login(request):
if request.method == "GET":
form = LoginForm(initial={"user": "武沛齐", "pwd": "123"})
return render(request, "login.html", {"form": form})
form = LoginForm(data=request.POST)
if not form.is_valid():
return render(request, "login.html", {"form": form})
# form.cleaned_data
# 手动读取字典,保存至数据库
# models.UserInfo.objects.create(name=form.cleaned_data['xx'], pwd=form.cleaned_data['yy'])
# models.UserInfo.objects.filter(id=1).update(name=form.cleaned_data['xx'], pwd=form.cleaned_data['y'])
return HttpResponse("成功")
ModelForm组件
def login(request):
if request.method == "GET":
form = LoginModelForm()
return render(request, "login.html", {"form": form})
user_object = model.UserInfo.object.filter(id=1).first()
form = LoginModelForm(data=request.POST, instance=user_object)
if not form.is_valid():
return render(request, "login.html", {"form": form})
form.save() # 更新id=1
return HttpResponse("成功")
def login(request):
# 1.打开login2.html文件读取内容 + 参数进行“替换” => 渲染 ==> 得到被替换完的字符串
# 2.将字符串封装HttpReponse对象中,等待给用户返回。
return render(request, 'login2.html', {"v1": "wupeiqi"})
def render(request, template_name, context=None, content_type=None, status=None, using=None):
content = loader.render_to_string(template_name, context, request, using=using)
# template = get_template(template_name, using=using)
# content = template.render(context, request)
return HttpResponse(content, content_type, status)
from django.shortcuts import HttpResponse
from django.template.loader import get_template
def v1(request):
template = get_template("v1.html")
text = template.render({"text": "张开"}, request)
print(text)
return HttpResponse("OK")
class Widget(metaclass=MediaDefiningClass):
def __init__(self, attrs=None):
self.attrs = {} if attrs is None else attrs.copy()
def render(self, name, value, attrs=None, renderer=None):
# name="user" value="zhangkai" attrs=None self.attrs={'class': "c1", "id": "xx1"}
context = self.get_context(name, value, attrs)
return self._render(self.template_name, context, renderer)
def get_context(self, name, value, attrs):
return {
"widget": {
"name": name, # "user"
"value": self.format_value(value), # "zhangkai"
"attrs": self.build_attrs(self.attrs, attrs), # {'class': "c1", "id": "xx1"}
"template_name": self.template_name, # "django/forms/widgets/text.html"
# "type":"text"
},
}
class Input(Widget):
input_type = None # Subclasses must define this.
template_name = "django/forms/widgets/input.html"
def __init__(self, attrs=None):
if attrs is not None:
attrs = attrs.copy()
self.input_type = attrs.pop("type", self.input_type)
super().__init__(attrs)
def get_context(self, name, value, attrs):
# {"widget":{"name":} }
context = super().get_context(name, value, attrs)
context["widget"]["type"] = self.input_type
return context
class TextInput(Input):
input_type = "text"
template_name = "django/forms/widgets/text.html"
class PasswordInput(Input):
input_type = "password"
template_name = "django/forms/widgets/password.html"
def __init__(self, attrs=None, render_value=False):
super().__init__(attrs)
self.render_value = render_value
def get_context(self, name, value, attrs):
if not self.render_value:
value = None
return super().get_context(name, value, attrs)
from django.shortcuts import HttpResponse
from django.template.loader import get_template
from django import forms
def v1(request):
template = get_template("v1.html")
text = template.render({"text": "张开"}, request)
print(text)
return HttpResponse("OK")
def v2(request):
# 1.执行 TextInput的 __init__方法
obj = forms.TextInput(attrs={'class': "c1", "id": "xx1"})
data_string = obj.render(name="user", value="张开")
print(data_string) # <input type='text' name='user' value="张开" class="c1" id="xx1" />
obj2 = forms.PasswordInput(attrs={'class': "c2"}, render_value=True)
data_string = obj2.render(name="user", value="张开")
print(data_string)
return HttpResponse("OK")
class Foo(object):
def __init__(self,name):
self.name = name
# 1. __new__ 去创建空对象 {} -> 构造方法(创建对象)
# 2. __init__在对象中进行初始化 {"name":"武沛齐"} -> 初始化方法
obj = Foo("武沛齐")
class Foo(object):
def __init__(self, name):
print("init初始化", self)
self.name = name
def __new__(cls, *args, **kwargs):
obj = super().__new__(cls)
print("new创建对象", obj)
return obj
instance = Foo("wupeiqi")
print("得到对象", instance)
说两句:
默认情况下,类都是由type创建;
class Info(object):
city = "背景"
def show(self):
print("123")
# Info = type("Info", (object,), {"city": "背景", "show": lambda self: print(123)})
obj = Info()
print(obj.city)
obj.show()
想要由其他的东西创建类,就可以使用metaclass进行指定。
class Info(object,metaclass=其他):
city = "背景"
def show(self):
print("123")
class MyType(type):
pass
class Info(object, metaclass=MyType):
city = "背景"
def show(self):
print("123")
类是有type创建的,类又可以进行实例化,去创建对象。
class MyType(type):
# def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
def __new__(cls, *args, **kwargs):
clazz = super().__new__(cls, *args, **kwargs)
clazz.base_declare = [11, 22, 33]
return clazz
class Info(object, metaclass=MyType):
city = "背景"
def show(self):
print("123")
print(Info.base_declare)
判断某个对象是否是某个类或其子类创建的对象。
class Foo(object):
pass
class Info(object):
pass
obj1 = Foo()
obj2 = Foo()
print(isinstance(obj1, Foo))
print(isinstance(obj2, Info))
class Field(object):
pass
class CharField(Field):
pass
class EmailField(Field):
pass
class ImageField(Field):
pass
obj1 = CharField()
obj2 = EmailField()
obj3 = ImageField()
print(isinstance(obj1, Field))
print(isinstance(obj2, Field))
print(isinstance(obj3, Field))
功能:很多对象可以判断这些对象,都是我Field的子类创建的对象。
class DeclarativeFieldsMetaclass(MediaDefiningClass):
"""Collect Fields declared on the base classes."""
def __new__(mcs, name, bases, attrs):
# Collect fields from current class and remove them from attrs.
attrs["declared_fields"] = {
key: attrs.pop(key)
for key, value in list(attrs.items())
if isinstance(value, Field)
}
new_class = super().__new__(mcs, name, bases, attrs)
# Walk through the MRO.
declared_fields = {}
for base in reversed(new_class.__mro__):
# Collect fields from base class.
if hasattr(base, "declared_fields"):
declared_fields.update(base.declared_fields)
# Field shadowing.
for attr, value in base.__dict__.items():
if value is None and attr in declared_fields:
declared_fields.pop(attr)
new_class.base_fields = declared_fields
new_class.declared_fields = declared_fields
return new_class
from django import forms
class Form(BaseForm, metaclass=DeclarativeFieldsMetaclass):
pass
class LoginForm(forms.Form):
username = forms.CharField(label="用户名", required=True, widget=forms.TextInput)
pwd = forms.CharField(label="密码", required=True, widget=forms.PasswordInput)
LoginForm类其实是由DeclarativeFieldsMetaclass
创建的【new】【init】。
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(label="用户名", required=True, widget=forms.TextInput)
pwd = forms.CharField(label="密码", required=True, widget=forms.PasswordInput)
form = LoginForm() # __new__ __init__
class BaseForm(RenderableFormMixin):
field_order = None
def __init__(self,data=None,files=None,auto_id="id_%s",prefix=None,initial=None,....,field_order=None,renderer=None):
self.fields = copy.deepcopy(self.base_fields)
self.order_fields( self.field_order if field_order is None else field_order )
self.initial = initial or {}
renderer = get_default_renderer()
self.renderer = renderer
def order_fields(self, field_order):
if field_order is None:
return
fields = {}
for key in field_order:
try:
fields[key] = self.fields.pop(key)
except KeyError: # ignore unknown fields
pass
fields.update(self.fields) # add remaining fields in original order
self.fields = fields
class Form(BaseForm, metaclass=DeclarativeFieldsMetaclass):
pass
class LoginForm(forms.Form):
username = forms.CharField(label="用户名", required=True, widget=forms.TextInput)
pwd = forms.CharField(label="密码", required=True, widget=forms.PasswordInput)
form = LoginForm(initial={})
class LoginForm(forms.Form):
username = forms.CharField(label="用户名", required=True, widget=forms.TextInput)
pwd = forms.CharField(label="密码", required=True, widget=forms.PasswordInput)
def v3(request):
form = LoginForm()
print(form['username']) # form.username <input type="text" name="username" required id="id_username">
return HttpResponse("OK")
class Foo(object):
def __getitem__(self, item):
return 999
obj = Foo()
print(obj)
print(obj['xxxx'])
class BoundField:
"A Field plus data"
def __init__(self, form, field, name):
self.form = form # Form对象
self.field = field # forms.CharField(label="用户名", required=True, widget=forms.TextInput)
self.name = name # "username"
self.html_name = form.add_prefix(name)
self.html_initial_name = form.add_initial_prefix(name)
self.html_initial_id = form.add_initial_prefix(self.auto_id)
if self.field.label is None:
self.label = pretty_name(name)
else:
self.label = self.field.label
self.help_text = field.help_text or ""
def __str__(self):
"""Render this field as an HTML widget."""
return self.as_widget() # <input type="text" name="username" required id="id_username">
def as_widget(self, widget=None, attrs=None, only_initial=False):
# 插件对象
widget = widget or self.field.widget
if self.field.localize:
widget.is_localized = True
attrs = attrs or {}
attrs = self.build_widget_attrs(attrs, widget)
if self.auto_id and "id" not in widget.attrs:
attrs.setdefault(
"id", self.html_initial_id if only_initial else self.auto_id
)
if only_initial and self.html_initial_name in self.form.data:
# Propagate the hidden initial value.
value = self.form._widget_data_value(
self.field.hidden_widget(),
self.html_initial_name,
)
else:
value = self.value()
# 字符串= 插件forms.TextInput对象.render 《input name='?' class=".."/>
return widget.render(
name=self.html_initial_name if only_initial else self.html_name,
value=value,
attrs=attrs,
renderer=self.form.renderer,
)
class MyForm(object):
def __iter__(self):
return iter([11, 22, 33, 44])
obj = MyForm()
for item in obj:
print(item)