偶尔会用到的内容

119 阅读1分钟

“反向” 关联

若模型有 ForeignKey,外键关联的模型实例将能访问 Manager,后者会返回第一个模型的所有实例。默认情况下,该 Manager 名为 FOO_set, FOO 即源模型名的小写形式。 Manager 返回 QuerySets,后者能以 “检索对象” 章节介绍的方式进行筛选和操作。 eg:

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains='Lennon')
>>> b.entry_set.count()

分页

# 引入分页模块
from django.core.paginator import Paginator

# 取出所有对象到list
model_object_list = Project.objects.all()  

# 分页器,每页5个
paginator = Paginator(model_object_list,5)

# 获取 url 中的页码
page = request.GET.get('page')

#将导航对象响应的页码内容返回给model_objects
model_objects = paginator.get_page(page)

 # 传递给 模板 的对象
context = {'model_objects': model_objects}

return render(request, 'url', context)
<!-- 如果不是第一页,则显示上翻按钮 -->
{% if model_objects.has_previous() %}
<a href="?page=1&search={{search}}" class="btn btn-success"> &laquo; 1 </a>
<span>...</span>
<a
    href="?page={{model_objects.previous_page_number()}}&search={{search}}"
    class="btn btn-secondary"
>
    {{ model_objects.previous_page_number() }}
</a>
{% endif %}

<!-- 当前页面 -->
<span class="current btn btn-danger btn-lg">
    {{ model_objects.number }}
</span>

<!-- 如果不是最末页,则显示下翻按钮 -->
{% if model_objects.has_next() %}
<a
    href="?page={{ model_objects.next_page_number() }}&search={{search}}"
    class="btn btn-secondary"
>
    {{ model_objects.next_page_number() }}
</a>
<span>...</span>
<a
    href="?page={{ model_objects.paginator.num_pages }}&search={{search}}"
    class="btn btn-success"
>
    {{ model_objects.paginator.num_pages }} &raquo;
</a>
{% endif %}
>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2)

>>> p.count
4
>>> p.num_pages
2
>>> type(p.page_range)
<class 'range_iterator'>
>>> p.page_range
range(1, 3)

>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']

>>> page2 = p.page(2)
>>> page2.object_list
['george', 'ringo']
>>> page2.has_next()
False
>>> page2.has_previous()
True
>>> page2.has_other_pages()
True
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number()
1
>>> page2.start_index() # The 1-based index of the first item on this page
3
>>> page2.end_index() # The 1-based index of the last item on this page
4

>>> p.page(0)
Traceback (most recent call last):
...
EmptyPage: That page number is less than 1
>>> p.page(3)
Traceback (most recent call last):
...
EmptyPage: That page contains no results

多项查询

#引入Q对象 对多个参数进行查询
from django.db.models import Q
search = request.GET.get('search')
Project.objects.filter(Q(name__icontains=search)|Q(detail__icontains=search))

表单渲染时 ForeignKey可用选择限制 ForeignKey.limit_choices_to

可以使用字典、 Q 对象,或者返回字典或 Q 对象的可调用对象。 eg:

staff_member = models.ForeignKey(
    User,
    on_delete=models.CASCADE,
    limit_choices_to={'is_staff': True},
)

Django限制表单中ForeignKey对应下拉菜单选项数量的两种经典方法

更多参考

form.fields['category'].queryset = Category.objects.filter(author=request.user)

@login_required
def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save(commit=False)
            article.author = request.user  # Set the user object here
            article.save()  # Now you can send it to DB
 
       return HttpResponseRedirect("/blog/")
       else:
        form = ArticleForm()
        form.fields['category'].queryset = Category.objects.filter(author=request.user)
    return render(request, 'blog/article_create_form.html', {'form': form, })