Django开发项目遇到的一些问题的总结

安装项目的包:
在项目目录下创建一个txt文件,在txt文件中写要安装的包的名字
pip install -r 装包的.txt文件 --- 安装txt文件中的包
例如:
pillow
djangorestframework==3.4.6
django-filter

如果不知道自己需要安装的包的版本,可以在指定版本的时候随便输入,当它找不到版本的时候就会列出当前能安装的所有版本
pip install Django==1.11xxxxxxxxx

在前端也可以通过下标拿到对应的对象

Queryset.下标 --- 拿到传过来的Query的对应下标的对象
mainshops.0 --- 拿到第一个对象

# 拿到Query对象的第一个和第二个对象
{% for mainshop in mainshops %}
    {% if forloop.counter > 0 and forloop.counter < 3 %}
    
    {% endif %}
{% endfor %}

forloop.counter 是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。
forloop.last 是一个布尔值;在最后一次执行循环时被置为True
forloop.first
forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。 第一次执行循环时这个变量会被设置为0。
forloop.revcounter 是表示循环中剩余项的整型变量。 在循环初次执行时 forloop.revcounter 将被设置为序列中项的总数。 最后一次循环执行中,这个变量将被置1。
forloop 变量仅仅能够在循环中使用。 在模板解析器碰到{% endfor %}标签后,forloop就不可访问了。
 # 如果参数有空则为false,如果都存在则为true
all([username, password, email, icon])

数据的加密和解密
from django.contrib.auth.hashers import make_password, check_password

加密:
password=make_password(password)

解密:
check_password(明文,密文)
check_password(password,user.password)
思路:当我们点击进入一个页面的时候,如果我们需要在刚进页面的时候就传一个默认参数,可以考虑建立一个views做跳转,用来传参给真正处理数据的视图传参(例如,刚进购物页面时,一般会有显示热销物品,此时就可以通过跳板视图的HttpResponseRedirect方法将默认数据传入进行数据处理的视图中)

# (?P\d+)当有参数的时候接受参数
url(r'^market_params/(?P\d+)/(?P\d+)/(?P\d+)/',views.market_params,name='market_params'),

def market(request):
    if request.method == 'GET':
        # 跳转并传值
        return HttpResponseRedirect(reverse('home:market_params',
                                            kwargs={'typeid': 104749,
                                                    'cid': 0, 'sort': 0}))
此时跳转到的视图中就可以接受到参数:
def market_params(request, typeid, cid, sort):
    if request.method == 'GET':
        # 分类
        foodtypes = FoodType.objects.all()
        # 分类对应的商品信息
        if cid == '0':
            goods = Goods.objects.filter(categoryid=typeid)
        else:
            goods = Goods.objects.filter(categoryid=typeid,
                                         childcid=cid)

        if sort == '0':
            pass
        elif sort == '1':
            goods = Goods.objects.order_by('-productnum')
        elif sort == '2':
            goods = Goods.objects.order_by('-price')
        elif sort == '3':
            goods = Goods.objects.order_by('price')
        # 获取某个分类的全部类型
        types = FoodType.objects.filter(typeid=typeid).first()
        childtypes = [i.split(':') for i in types.childtypenames.split('#')]
        data = {
            'foodtypes': foodtypes,
            'goods':goods,
            'typeid': typeid,
            'cid':cid,
            'childtypes':childtypes,
        }
        return render(request,'market/market.html',data)
        
注意:此时的html中需要注意href的地址传值问题,必须要对应
html中:
{{ types.typename }}



如果想在ajax中知道自己点击的是具体的那哪一个标签可以使用以下两个方法:
1、给标签一个id或者class,让其值是动态变化的,例子如下:
在绑定事件的函数中传一个当前标签相关的参数,

{{ cart.c_num }}
function addToCart(good_id){
# 此时可以在js中通过$('#num_'+good_id)获得当前点击的标签
     $('#num_'+good_id)
}
2、将任意属性的值设置为动态产生的数据,
在js中可以通过标签对象.attr(属性名),拿到属性的值。


get请求的ajax会自动执行,所以可以让页面刚刷新时就请求到数据库的数据,然后显示在页面上
$.get('/home/refresh_goods/',function(data){
//    alert('dsfasfd')
    if (data.code == '200'){
        console.log(data)

        for(var i=0; i

Django中通过URL传值的4中方法

1、无参数的情况
URL是:
url(r’^hello/$’, hello)
视图中:
def hello(request):
    return HttpResponse("Hello World")

访问http://127.0.0.1:8000/hello,输出结果为“Hello World”

2、传递一个参数
URL中通过正则指定一个参数:
url(r’^plist/(.+)/$’, helloParam)
视图中:
def helloParam(request,param1):
    return HttpResponse("The param is : " + param1)
访问http://127.0.0.1:8000/plist/china,输出结果为”The param is : china”

3、传递多个参数
URL中通过正则指定两个参数:
url(r’^plist/p1(\w+)p2(.+)/$’, helloParams)
视图中:
def helloParams(request,param1,param2):
    return HttpResponse("p1 = " + param1 + "; p2 = " + param2)
访问http://127.0.0.1:8000/plist/p1chinap22012/ 
输出为”p1 = china; p2 = 2012″

总结:上述的视图的参数是根据URL的正则式,按顺序并自动赋值的。虽然实现了多个参数的传递,但是不够灵活,URL看起来比较混乱,而且由于是正则匹配的,有些情况下容易出错。

4、通过'?'传递参数
http://127.0.0.1:8000/plist/?p1=china&p2=2012
url中的?之后表示传递的参数,这里传递了p1和p2两个参数。
通过这个方式传递参数,就不会出现因为正则匹配错误而导致的问题,在Django中,此类参数的解析是通过request.GET.get()方法获取的。
配置的URL为:
url(r’^plist/$’, helloParams1)
视图中:
def helloParams(request):
    p1 = request.GET.get('p1')
    p2 = request.GET.get('p2')
    return HttpResponse("p1 = " + p1 + "; p2 = " + p2)
输出结果为”p1 = china; p2 = 2012″


5、通过关键字参数
在 Python 正则表达式中,命名的正则表达式组的语法是 (?Ppattern) ,这里 name 是组的名字,而pattern 是匹配的某个模式。 
无名组URL的例子:
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^articles/(\d{4})/$', views.year_archive),
(r'^articles/(\d{4})/(\d{2})/$', views.month_archive),
)

命名组URLconf
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns('',
(r'^articles/(?P\d{4})/$', views.year_archive),
(r'^articles/(?P\d{4})/(?P\d{2})/$', views.month_archive),
)

区别:
命名组的以关键字参数的方式而不是以位置参数的方式传递给视图函数
例如,如果不带命名组,请求/articles/2006/03/将会是以的函数调用:
month_archive(request, '2006', '03')
而带命名组,同样的请求就会变成这样的函数调用:
month_archive(request, year='2006', month='03')
或者
month_archive(request, month='03',ear='2006')

使用名米组可以让URL更加清晰,减少参数混乱导致的BUG,还可以在函数汇定义中对参数重新排序。如果我们想修改URL把月份放到 年份的 前面 ,而不使用命名组的话,我们就不得不去修改视图 month_archive 的参数次序。 如果我们使用命名组的话,修改URL里提取参数的次序对视图没有影响。 

注意:如果在URL中使用命名组,那么命名组合肥命名组是不能同时存在在同一个URL的模式中的,虽然这样并不会报错,但是匹配到URL可能不会和预计的那样正确。

URLconf解释器有关正则表达式中命名组和 非命名组所遵循的算法:
1、如果有任何命名的组,Django会忽略非命名组而直接使用命名组
2、如果有非命名组,Django会把所有的非命名组以位置参数的形式传递。
在以上两种情况,Djano同时会以关键字参数的方式传递一些额外的参数。

下列是几种常用的url传值方式
{{ types.typename }}

{{ types.typename }}

{{ types.typename }}
locatoin.reload() --- 强制刷新页面
round()方法:
语法:round(number,digits)
number是要四舍五入的数,digits是要小数点后保留的位数。
如果 digits 大于 0,则四舍五入到指定的小数位。 
如果 digits 等于 0,则四舍五入到最接近的整数。 
如果 digits 小于 0,则在小数点左侧进行四舍五入。
举例:
round(3.1415926,2)=3.14;
round(3.1415926,3)=3.142;
select round(193,-2)from dual; 200
select round(193,-1)from dual;190
select round(193,-3)from dual;0

也可以使用a = "%.2f"%(float(a*b))
{{ item.num|default:0 }} --- 当对象拥有num属性,这展示num的值,如果没有num属性则显示0


思路:当你使用ajax时,如果想要在请求成功跳转至另一个页面,可以在success对应的函数中中使用location.href=""进行跳转,并且可以在地址后通过?传递ajax请求回来的或者绑定的事件函数传递的数据值,此时你就可以在跳转的地址中通过request.GET.get('键')拿到?后的值

html中:
下单

js中:
function place_order(){
    $.post('/home/place_order/',function(data){
        if (data.code == '200'){
            if (data.msg == '请求成功'){

                location.href = '/home/order_info/?order_id='+ data.order_id
            }else{
             alert(data.msg)
            }

        }
    })

}

视图中:
def place_order(request):
    if request.method == 'POST':
        # 创建订单
        # 创建订单和商品的详情表
        # 将购物车中被选中的商品删除
        user=request.user.first().user
        data= {}
        data['code'] = 200
        data['msg'] = '请求成功'
        # 1、获取购物车中已经选中的商品
        carts = CartModel.objects.filter(is_select=True,user=user)
        if not carts:
            data['msg'] = '没有选中商品'
            return JsonResponse(data)
        # 2、创建订单
        o_num = get_order_number()
        order = OrderModel.objects.create(user_id=user.id,o_num=o_num)
        # 3、创建订单和商品的详情表
        for cart in carts:
            OrderGoodsModel.objects.create(order=order,goods=cart.goods,
                                           goods_num=cart.c_num)
        # 4、将购物车中已经下单的商品删除
        carts.delete()
        data['order_id'] = o_num
        return JsonResponse(data)
        
aja跳转的视图中:
def order_info(request):
    if request.method == 'GET':
        order_id = request.GET.get('order_id')
        order = OrderModel.objects.filter(o_num=order_id).first()
        return render(request,'order/order_info.html',{'order': order})

存在以下形式的模型:
class OrderGoodsModel(models.Model):
    goods = models.ForeignKey(Goods)  # 关联的商品
    order = models.ForeignKey(OrderModel)  # 关联的订单
    goods_num = models.IntegerField(default=1)  # 商品的个数

    class Meta:
        db_table = 'axf_order_goods'
        
如果想要创建模型的实例可以通过以下方法:

for cart in carts:
    OrderGoodsModel.objects.create(order_id=order.id,goods_id=cart.goods.id,
           goods_num=cart.c_num)

for cart in carts:
    OrderGoodsModel.objects.create(order=order,goods=cart.goods,
           goods_num=cart.c_num)
其中,order是一个对象,cart.goods也是一个对象

创建订单

import random

from datetime import datetime


def get_order_number():
    s='1237979823423453'
    o_num = ''
    for i in range(20):
        o_num += random.choice(s)
    o_num += datetime.now().strftime('%Y%m%d%H%M%S')
    return o_num
Python time strftime()函数接收以时间元组,并返回可以可读字符串表示的当地时间,格式由参数format决定。
在添加中间件后,会出现图片加载不出来的情况,这是因为图片路径也是一个地址,中间件没有将其放过,需要在中间件中将其放过

你可能感兴趣的:(Django)