• Django基本篇-2

    一、多表操作

    现有的表包括导航表 Nav 和文章表 Articles,Articles 中的数据会保存对应的 nav_id,意思为,找到导航栏中某个菜单下的所有文章,通用的方法是先在 Nav 表中查到这个导航的 id,再根据其 id 在 Articles 表中找具有这个 nav_id 的文章。代码如下:

    1 nav = models.Nav.objects.get(我的博客)
    2 result = models.Article.objects.filter(nav=nav) #这里也可以写nav_id=nav.id

    以上需要在两个表中查询的数据可以在一个表中实现

    通过外键反向查询:

    1 nav = models.Nav.objects.get(我的博客)
    2 result = nav.article_set.all()    #查询导航下面所有的文章

    二、分页

    目的:根据导航 id 显示对应的文章

    样式:前端带上参数 127.0.0.1:8000/index/?limit=10&page=2

    1. 首先要获取到传过来的参数,即对前端的部分进行处理

    1 limit = request.GET.get(limit,page_limit) #20为默认值
    2 page = request.GET.get(page,1)

    此处的 page_limit 是配置在一个放常量的文件中,方便日后更改

    另外,post 请求取参数的方式与 get 相同,即: demo = request.POST.get() 

    2. 前端写到这里再看下分页的一些方法

     1 import django,os
     2 from django.core.paginator import Paginator
     3 
     4 # 分页怎么用
     5 l = list(range(100))
     6 page_obj = Paginator(l,20)
     7 
     8 print(page_obj.count) #总共多少数据
     9 page1 = page_obj.get_page(1)
    10 print(list(page1)) #获取第几页的数据
    11 print(page_obj.num_pages) #总共分了几页
    12 print(page_obj.page_range) #分页范围
    13 print(page_obj.page_range[0])
    14 print(page_obj.page_range[-1])

    以上用法为:

    a. 给 Paginator 传两个参数,第一个是所有要分页的内容,第二个是每页的显示条数

    b. 目前 page_obj 是一个含有所有分页信息的对象,它的用法有以上几种

    c. 其中 page1 是具体到某一页的内容,它的用法如下:

     1 page1 = page_obj.get_page(1)
     2 print(page1.number)   #当前的页码
     3 page1.has_next() #是否有下一页
     4 page1.has_other_pages() #是否有其他页
     5 page1.has_previous() #是否有上一页
     6 page1.next_page_number() #下一页的页码,如果没有下一页,则报错
     7 page1.previous_page_number() #上一页的页码
     8 page1.end_index()   #末页
     9 page1.start_index() #首页
    10 obj = page1.paginator #获取分页的对象

    根据以上的这些用法,我们可以对前端页面的页码和翻页展示进行操作,首先,views 中定义 index 上面展示了获取浏览器传过来的参数的方法(limit 和 page),然后再根据这两个参数拿到具体要显示的内容返回给前端,以下是整个 index 的内容:

    def index(request): #格式要求写request
        limit = request.GET.get(limit,page_limit) #默认值
        page = request.GET.get(page,1)
        # post请求获取参数
        # request.POST.get()
        # article = models.Article.objects.all()
        page_obj = Paginator(models.Article.objects.all().order_by(id),limit)
        page_data = page_obj.get_page(page)
        dic = {articles:page_data}
        return render(request,index.html,dic)

    获取到的 article 返回到 index 页面,这样就能在这个页面直接用这个数据。

    然后在 index 页面对当前页面拿到的数据进行判断来展示翻页部分的功能,以下为翻页部分的逻辑,有个问题是 start_index 和 end_index 并不起作用,也就是首页喝末尾页用自带方法并未很好的实现

    (调试过程中发现末尾页还好,首页内容不准,我改成了拿返回的第一个的方式,但是末页还不会写)用首尾页这个方法的问题表现在,点了之后在 URL 一栏中 limit 和 page 的信息是错的

     1 <ul class="pagination">
     2 {% if articles.has_other_pages %}
     3 {#            <li><a href="/index/?limit={{ page_limit }}&page={{ articles.start_index }}">?</a></li>  start_index end_index不起作用#}
     4     <li><a href="/index/?limit={{ page_limit }}&page={{ articles.paginator.page_range.0 }}">?</a></li>
     5 {% endif %}
     6 
     7 {% if articles.has_previous %}
     8     <li><a href="/index/?limit={{ page_limit }}&page={{ articles.previous_page_number }}"><?</a></li>
     9 {% endif %}
    10 
    11     {% for num in articles.paginator.page_range %}
    12         {% if articles.number == num %}
    13             <li><a class="active" href="/index/?limit={{ page_limit }}&page={{ num }}">{{ num }}</a></li>
    14         {% else %}
    15             <li><a href="/index/?limit={{ page_limit }}&page={{ num }}">{{ num }}</a></li>
    16         {% endif %}
    17     {% endfor %}
    18 
    19 {% if articles.has_next %}
    20     <li><a href="/index/?limit={{ page_limit }}&page={{ articles.next_page_number }}">></a></li>
    21 {% endif %}
    22 
    23 {% if articles.has_other_pages %}
    24     <li><a href="/index/?limit={{ page_limit }}&page={{ articles.end_index }}">?</a></li>
    25 {% endif %}
    26 </ul>

     三、Django 后台管理

    通过 127.0.0.1:8000/admin 即可访问,为后台添加管理员的操作:python manage.py createsuperuser

    之后的用户可以在后台直接创建。

    1.配表

    Django 创建的工程中自带的一些东西就包含后台,相关内容在 admin.py 中,而初次打开后台的时候并不会把我们现有的表展示出来,这时候需要在前面提到的 python 文件中配置一下:

     1 from django.contrib import admin
     2 from . import models
     3 # Register your models here.
     4 
     5 # admin.site.register(models.Nav) #与下方的class二选一
     6 # admin.site.register(models.Article)
     7 
     8 
     9 class NavAdmin(admin.ModelAdmin):
    10     list_display = [id,name,create_time]
    11 
    12 class ArticleAdmin(admin.ModelAdmin):
    13     list_display = [id,title,img,create_time] #显示几列
    14     search_fields = [title,content]
    15     list_per_page = 5
    16 
    17 class StudentAdmin(admin.ModelAdmin):
    18     list_display = [name,phone,money]
    19 
    20 admin.site.register(models.Article,ArticleAdmin)
    21 admin.site.register(models.Nav,NavAdmin)
    22 admin.site.register(models.Student,StudentAdmin)

    以上配置包含了显示表中的哪些列,配好了表之后,就可以在后台很方便地对数据库表进行操作啦。

    但是随之而来的还有另外一个问题,就是在后台这样的前端界面输入的数据其实是没有经过校验的,如何保证数据填写符合我们的要求,就需要在前端增加校验。

    四、前端数据的校验

    之前学 Python 的时候,要做这件事可能就是对挨个的数据进行判断,如先非空检验,再各个字段去校验,这里的要简单许多,先简单罗列一下。

     1 class StudentForm(forms.Form):
     2     name = forms.CharField(min_length=2,max_length=10,required=True) #required=True表示必填,默认必填
     3     phone = forms.CharField(min_length=11,max_length=11)
     4     money = forms.FloatField(required=False,default=0,null=True)
     5 #     自定义函数校验是否字段重复
     6     def clean_phone(self):
     7         ‘‘‘钩子‘‘‘
     8         phone = self.cleaned_data[phone]
     9         if models.Student.objects.filter(phone=phone):
    10             return self.errors.add(手机号错误,手机号已经存在)
    11         return phone
    12 
    13 
    14 def student(request):
    15     stu_form = StudentForm(request.POST)
    16     if stu_form.is_valid():
    17         models.Student.objects.create(**stu_form.cleaned_data)
    18         data = {"msg":"成功"}
    19     else:
    20         data = {"msg":"检验失败"}
    21     return HttpResponse(json.dumps(data,ensure_ascii=False))

    理解上还需要再回看视频。

    五、同一页面不同请求方法访问时的处理(前端向后端写数据)

    以在后台添加文章为例,我们需要两个 URL,一个用来展示添加文章的页面,另一个用来向后端发送请求添加数据。

    这时候可以写成两个 URL,但也可以写成一个,只需要在定义的时候将请求方法区分开即可。

     1 def add_article(request):
     2     if request.method == GET:
     3         return render(request,add.html)
     4     else:
     5         title = request.POST.get(title)
     6         content = request.POST.get(content)
     7         nav_id = request.POST.get(nav_id)
     8         img = request.FILES.get(img)
     9         models.Article.objects.create(title=title,content=content,nav_id=nav_id,img=img)
    10         return HttpResponseRedirect(/index)

    正常访问 add 页面时,是 get 请求,展示的是添加文章数据的页面,在 add.html 中,我们定义了向后端发送请求为 post 方法。这样就可以实现各自的功能了。

    不过这里 add.htnl 中写的是 form 表单的形式,周六有时间自己要尝试用 ajax 写一下。

     

    文章待完善:

    • 后台校验数据的方法理解(四)
    • 前端向后端发送请求使用 ajax 重写(五)
    相关文章
    相关标签/搜索
    每日一句
      每一个你不满意的现在,都有一个你没有努力的曾经。
    公众号推荐
       一个历史类的公众号,欢迎关注
    一两拨千金
    王中王蓝月亮930三肖三码 吉林市| 堆龙德庆县| 平原县| 堆龙德庆县| 旅游| 高唐县| 兴国县| 小金县| 凭祥市| 清涧县| 东源县| 马龙县| 兰州市| 宜兴市| 札达县| 梨树县| 杭锦旗| 庆城县| 大洼县| 鄄城县| 女性| 扎兰屯市| 那曲县| 湾仔区| 岐山县| 蓬安县| 菏泽市| 沙雅县| 东莞市| 五家渠市| 日土县| 夏津县| 四会市| 丘北县| 溧水县| 连平县| 酒泉市| 涞水县| 大连市| 贞丰县| 株洲县| 泰顺县| 安龙县| 体育| 泾川县| 扎鲁特旗| 西吉县| 灵寿县| 北安市| 利津县| 积石山| 财经| 常山县| 娱乐| 武穴市| 景谷| 顺昌县| 福建省| 颍上县| 桂东县| 广南县| 潍坊市| 广昌县| 东莞市| 孝感市| 运城市| 英吉沙县| 新乡县| 镇雄县| 河北省| 宜丰县| 富顺县| 阿克陶县| 内乡县| 彝良县| 云龙县| 辉县市| 特克斯县| 怀安县| 九寨沟县| 诸城市| 汉阴县| 九龙县| 兰州市| 桦川县| 大埔县| 清镇市| 彝良县| 新津县| 武汉市| 松江区| 波密县| 新田县| 诸暨市| 岳阳县| 涟水县| 栾川县| 竹北市| 奉化市| 资阳市| 措美县| 环江| 赣州市| 六安市| 宿松县| 广河县| 江油市| 鞍山市| 南阳市| 平定县| 广南县| 贡山| 德惠市| 二连浩特市| 长沙市| 汕头市| 旺苍县| 东明县| 宣城市| 抚远县| 韩城市| 延边| 房产| 靖西县| 体育| 阳江市| 察雅县| 双辽市| 鄂伦春自治旗| 阿合奇县| 海兴县| 屯留县| 临猗县| 子长县| 庐江县| 垫江县| 博湖县| 长垣县| 吉安县| 临桂县| 固始县| 中方县| 若尔盖县| 襄樊市| 安仁县| 铁力市| 积石山| 平舆县| 宽甸| 四川省| 兴和县| 四会市| 卓尼县| 磐安县| 泌阳县| 祥云县| 佛冈县| 惠安县| 阿巴嘎旗| 枣阳市| 阳谷县| 五指山市| 大关县| 六枝特区| 沙湾县| 新乡市| 锦州市| 松滋市| 伊宁市| 揭阳市| 会东县| 达州市| 宣威市| 长顺县| 错那县| 雅江县| 雅江县| 扶沟县| 象山县| 友谊县| 苗栗县| 太康县| 阿拉善左旗| 阿巴嘎旗| 锡林郭勒盟| 衡阳市| 成安县| 建昌县| 扬中市| 泰安市| 新乡市| 汤阴县| 开化县| 临安市| 怀来县| 松潘县| 大悟县| 乐亭县| 宜城市| 南郑县| 文登市| 台北市| 平度市| 当阳市| 永城市| 金堂县| 黄冈市| 济宁市| 江川县| 邛崃市| 婺源县| 四平市| 龙陵县| 福安市| 芷江| 拉萨市| 诸暨市| 威信县| 彰化市| 军事| 新野县| 罗山县| 保靖县| 开平市| 扬中市| 河津市| 吉木乃县| 望谟县| 宿州市| 岳池县| 综艺| 革吉县| 诸暨市| 封开县| 健康| 金堂县| 海晏县| 襄垣县| 山阳县| 汶川县| 南召县| 旌德县| 开化县| 鸡泽县| 板桥市| 盐边县| 辽宁省| 建始县| 洛浦县| 太仆寺旗| 偏关县| 新沂市| 彭山县| 黄石市| 淮滨县| 梁山县| 沭阳县| 张家口市| 田林县| 城市| 图片| 八宿县| 武清区| 友谊县| 荆门市| 宁强县| 页游| 双桥区| 信阳市| 柳州市| 庆云县| 河南省| 孝义市| 静宁县| 稻城县| 连城县| 密云县| 唐河县| 黔西| 中宁县| 安溪县| 海宁市| 库尔勒市| 林甸县| 长汀县| 盐城市| 大安市| 宜黄县| 大同市| 谢通门县| 兰溪市| 马边| 辉南县| 海口市| 吉林省| 武定县| 景宁| 乐业县| 横山县| 华阴市| 玛沁县| 汉源县| 昭通市| 潮州市| 奉化市| 崇礼县| 井研县| 长乐市| 乌什县| 上犹县| 邵东县| 西盟| 五家渠市| 寿宁县| 昆明市| 务川| 常宁市| 札达县| 林周县| 蓝田县| 阆中市| 开封市| 崇阳县| 旅游| 马公市| 青神县| 庆云县| 奉贤区| 电白县| 库尔勒市| 齐齐哈尔市| 甘洛县| 都兰县| 称多县| 高邑县| 神池县| 康保县| 沁源县| 富蕴县| 阿瓦提县| 鹰潭市| 长阳| 天长市| 堆龙德庆县| 黄石市| 兴仁县| 孟连| 射洪县| 秦安县| 岱山县| 南宁市| 广东省| 利辛县| 友谊县| 深州市| 定日县| 东明县| 阿荣旗| 工布江达县| 文登市| 宕昌县| 深泽县| 大石桥市| 鞍山市| 宝丰县| 海南省| 赤水市| 阜康市| 子洲县| 宁陕县| 疏附县| 天全县| 嘉兴市| 游戏| 临猗县| 桃园县| 全南县| 固原市| 连江县| 嘉黎县| 肃宁县| 孝义市| 密山市| 西华县| 江陵县| 周口市| 岢岚县| 沙田区| 天柱县| 英山县| 封丘县| 新晃| 镇赉县| 民乐县| 泰州市| 龙州县| 微博| 视频| 八宿县| 微博| 张北县| 无极县| 房产| 临洮县| 吉木萨尔县| 尉犁县| 久治县| 福泉市| 驻马店市| 唐山市| 安顺市| 泰来县| 织金县| 张家口市| 会昌县| 卓尼县| 临猗县| 井冈山市| 南漳县| 班戈县| 锦屏县| 玉林市| 河源市| 沂源县| 海宁市| 天祝| 葫芦岛市| 自贡市| 金塔县| 奉新县| 准格尔旗| 恩施市| 金川县| 苗栗县| 天气| 独山县| 辉县市| 巴林右旗| 遵化市| 壶关县| 买车| 太和县| 宜川县| 开平市| 饶阳县| 湖南省| 岳阳市| 饶阳县| 定陶县| 周至县| 安义县| 湖南省| 丹江口市| 洛宁县| 东阿县| 三门峡市| 漠河县| 麦盖提县| 壤塘县| 南靖县| 时尚| 阿拉善左旗| 承德市| 噶尔县| 漳浦县| 宾阳县| 聂拉木县| 灵武市| 博野县| 利辛县| 青岛市| 淮滨县| 惠安县| 宁德市| 广宗县| 大新县| 铁岭县| 金秀| 门源| 宜良县| 屯留县| 英山县| 平罗县| 万载县| 内乡县| 武汉市| 正阳县| 永定县| 高安市| 庄河市| 左权县| 崇左市| 肥西县| 西畴县| 正宁县| 博兴县| 九龙县| 花莲市| 虹口区| 自贡市| 曲靖市| 台中市| 九龙城区| 宁城县| 五大连池市| 丹江口市| 日土县| 钟山县| 绩溪县| 玉环县| 桦川县| 隆尧县| 彭州市| 轮台县| 芮城县| 凌云县| 合肥市| 新泰市| 大悟县| 石棉县| 衡南县| 普宁市| 北海市| 团风县| 大庆市| 三原县| 个旧市| 厦门市| 房产| 鹰潭市| 西和县| 宝山区| 宜州市| 永吉县| 三门县| 永丰县| 昌邑市| 昌都县| 永登县| 讷河市| 崇文区| 沧源| 抚州市| 沿河| 克山县| 轮台县| 隆德县| 丰城市| 伊宁县| 原阳县| 兴安盟| 南川市| 嘉义县| 靖江市| 乐昌市| 大新县| 紫阳县| 瑞丽市| 美姑县| 阿拉善右旗| 邮箱| 惠安县| 宣化县| 庄浪县| 东乡县| 临沧市| 轮台县| 大庆市| 东兰县| 梧州市| 金昌市| 敖汉旗| 隆化县| 台东县| 锦州市| 安平县| 正定县| 定州市| 海口市| 通化县| 阿勒泰市| 黄石市| 斗六市| 琼海市| 清河县| 靖江市| 武穴市| 崇义县| 郁南县| 吉木萨尔县| 平和县| 邵阳县| 武陟县| 漳平市| 邹平县| 修水县| 灵石县| 洛川县| 大新县| 绥滨县| 财经| 鹤山市| 司法| 卫辉市| 白银市| 交城县| 鸡东县| 连云港市| 郧西县| 漯河市| 桃源县| 新津县| 明溪县| 浙江省| 仁布县| http://hz0j3r7vo.fun http://jx1870featurev.fun http://jx1870harryv.fun http://www.jx1870financev.fun http://wap.jx1870fitv.fun http://jx1870enhancev.fun http://www.jx1870findv.fun http://hz0j2r3vo.fun http://m.jx1870influencev.fun http://wap.jx1870izagev.fun http://www.jx1870graduatev.fun http://www.jx1870exportv.fun http://www.jx1870groundv.fun http://www.jx1870joinv.fun http://www.jx1870firzv.fun http://wap.jx1870headv.fun http://jx1870forwardv.fun http://hz0j4r9vo.fun