Stackoverflow上有不少有趣的关于Django的问答,摘录一些分享给大家,里面有不少技巧和知识值得我们学习。如果觉得有用,就点个赞吧?如果能搜集超过50个赞,我将出下期。
问:Django 2.0以后设置单对多关系使用ForeignKey时必需设置on_delete选项,如下所示。请问on_delete和models.CASCADE是做什么的?还有其它选项吗?
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
答: 这是删除引用对象时数据库采取的行为。它不是特定于Django的,而是一个SQL标准。发生此类事件时,Django提供了有七种可能的操作:
CASCADE
:删除引用的对象时,还请删除对其具有引用的对象(例如,删除博客文章时,您可能还希望删除注释)。SQL等效项:CASCADE
。PROTECT
:禁止删除引用的对象。要删除它,您将必须删除所有手动引用它的对象。SQL等效项:RESTRICT
。RESTRICT
:(在Django 3.1中引入)PROTECT
与SQLRESTRICT
更精确匹配的相似行为。(请参阅django文档示例)SET_NULL
:将引用设置为NULL(要求该字段可为空)。例如,当删除用户时,您可能希望保留他在博客文章中发布的评论,但说该评论是由匿名(或已删除)用户发布的。SQL等效项:SET NULL
。SET_DEFAULT
:设置默认值。SQL等效项:SET DEFAULT
。SET(...)
:设置给定值。这不是SQL标准的一部分,完全由Django处理。DO_NOTHING
:这可能是一个非常糟糕的主意,因为这会在数据库中创建完整性问题(引用实际上不存在的对象)。SQL等效项:NO ACTION
。
问:如何在Django查询中执行OR过滤器?我基本上需要选择:
item.creator = owner or item.moderated = False
我将如何在Django中执行此操作?(最好使用过滤器或查询集)。
答:使用Q表达式可以进行复杂的查询,实现这个需求。
from django.db.models import Q
Item.objects.filter(Q(creator=owner) | Q(moderated=False))
问:如何在Django模板中获取当前URL?目前的网址是:
.../user/profile/
如何将此返回模板?
答:Django 1.9以后可以在模板中按如下方式获取当前页面URL。
## template
{{ request.path }} # 不带GET请求参数
{{ request.get_full_path }} # 完整路径,包括GET请求参数
问:如何在Django模板中添加注释?我想在模板中添加一句评论,如下所示:
{% if something.property %}
<table>
<tr>...
{% # 这是一条评论 %}
{% if something.property %}
<table>
<tr>...
答:作为Miles的答案,{% comment %}
...
{% endcomment %}
它用于多行注释,但是您也可以像这样在同一行上注释掉文本:
{# some text #}
问:如何在Django中一次将多个对象添加到ManyToMany关系?传递Queryset或ValuesListQueryset似乎也失败,有没有比使用for循环更好的方法?
答:如object.m2mfield.add(*items)如文档中所述,add()
可接受任意数量的参数,而不是列表。
add(obj1, obj2, obj3, ...)
要将列表扩展为参数,请使用*,该方法适用于查询集。
add(*[obj1, obj2, obj3])
示范代码如下所示:
# Returns a queryset
permissions = Permission.objects.all()
# Add the results to the many to many field (notice the *)
group = MyGroup.objects.get(name='test')
group.permissions.add(*permissions)
问:如何在Django中访问数组元素? 我正在将数组arr
传递给我的Django模板。我要访问的阵列中的阵列的各个元素(例如arr[0]
,arr[1]
)等等,而不是通过整个阵列循环。
有没有办法在Django模板中做到这一点?
答:请记住,Django模板中的点符号用于Python中的四种不同符号。在模板中,foo.bar
可以表示以下任何一项:
foo[bar] # dictionary lookup
foo.bar # attribute lookup
foo.bar() # method call
foo[bar] # list-index lookup
它按此顺序尝试它们,直到找到匹配项。因此foo.3
,您将获得列表索引,因为您的对象不是以3为键的dict,没有名为3的属性,也没有名为3的方法。
模板中正确获取数组元素方式如下所示:
arr.0
arr.1
问:在Django中,如何使用动态字段查找过滤QuerySet?给定一个Person模型:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=20)
是否有可能(如果有的话)拥有一个基于动态参数进行过滤的QuerySet?例如:
# Instead of:
Person.objects.filter(name__startswith='B')
# ... and:
Person.objects.filter(name__endswith='B')
# ... is there some way, given:
filter_by = '{0}__{1}'.format('name', 'startswith')
filter_value = 'B'
# ... that you can run the equivalent of this?
Person.objects.filter(filter_by=filter_value)
答:Python的参数扩展可用于解决此问题:
kwargs = {
'{0}__{1}'.format('name', 'startswith'): 'A',
'{0}__{1}'.format('name', 'endswith'): 'Z'
}
Person.objects.filter(**kwargs)
这是一个非常常见且有用的Python习惯用法。请注意一下:请确保kwarg中的字符串类型为str而不是unicode,否则filter()会发牢骚
问:如何建立多个提交按钮Django表单?我有一个带有一个电子邮件输入和两个提交按钮的表单,用于订阅和取消订阅新闻通讯:
<form action="" method="post">
{{ form_newsletter }}
<input type="submit" name="newsletter_sub" value="Subscribe" />
<input type="submit" name="newsletter_unsub" value="Unsubscribe" />
</form>
表单如下所示:
class NewsletterForm(forms.ModelForm):
class Meta:
model = Newsletter
fields = ('email',)
我必须编写自己的clean_email方法,并且我需要知道表单是通过哪个按钮提交的,但是提交按钮的值不在self.cleaned_data
字典中。我该怎么办?
答:您可以self.data
在clean_email
方法中使用来在验证之前访问POST数据。它应包含一个称为newsletter_sub
或newsletter_unsub
取决于所按下按钮的键。
# 表单验证
def clean(self):
if 'newsletter_sub' in self.data:
# do subscribe 订阅
elif 'newsletter_unsub' in self.data:
# do unsubscribe 取消订阅
你还可以在视图中操作,如下所示:
if 'newsletter_sub' in request.POST:
# do subscribe 订阅
elif 'newsletter_unsub' in request.POST:
# do unsubscribe 取消订阅
喜欢就点赞吧,超过50个才会有下期哦?
大江狗
2020.10.19
相关阅读
2020年最新Django经典面试问题与答案汇总(上)-大江狗整理