Django 中巧用 F 和 Q 对象,解锁“模糊查询搜索”与“喜欢”功能

一、项目定位:

        本人以团队小组开发的项目功能为例,为大家分享"智能鸟类识别平台"的搜索功能和喜欢功能;博客内容侧重于后端业务逻辑的实现,前端页面由于内容过多,只展示部分关键代码;如有问题,欢迎沟通交流!后续可能会跟进更多功能的分享。

        智能鸟类识别平台在于模拟鸟类爱好者/学者等用户使用toC平台时的场景, 用户可以直观的通过平台,观察和记录鸟类保护动物的照片和信息, 以甄别分类、实况分析鸟类保护动物,与全世界各地的用户沟通交流。

        模糊查询搜索对应了鸟类档案馆中的功能,用户可以模糊查询档案馆中所有录入的鸟类信息(如下图所示):

        此外,对于用户观察到的鸟类数据,在识别出结果后(CNN卷积神经网络实现),点击科普知识后,可以选择喜欢/不喜欢,以此针对档案馆中的人气值数据,实现增加或减少的统计:

        点击科普知识跳转到上面的页面时,涉及关联查询的功能实现,有兴趣了解的朋友可以看这篇文章:提升 Django ORM 的查询效率:关联查询与普通查询的实战对比)。

二 、模型构建:

        在应用birds中的models.py中编写实体鸟类的数据模型代码:

class Bird(models.Model):
    id = models.AutoField(primary_key=True)
    images = models.CharField(verbose_name='鸟类图片', max_length=255)
    name = models.CharField(verbose_name='鸟类名称', max_length=50)
    order = models.CharField(verbose_name='目', max_length=50)  # 鸟类所属的目
    family = models.CharField(verbose_name='科', max_length=50)  # 鸟类所属的科
    genus = models.CharField(verbose_name='科', max_length=50)  # 鸟类所属的属
    size = models.CharField(verbose_name='体型描述', max_length=100)  # 鸟类的体型描述,如长度、翼展、重量等
    plumage = models.CharField(verbose_name='羽毛描述', max_length=255)  # 羽毛的颜色和图案
    habitat = models.CharField(verbose_name='栖息地分布', max_length=100)  # 鸟类的栖息地,如森林、湿地、草原等
    distribution = models.CharField(verbose_name='地理分布', max_length=255)  # 鸟类的地理分布范围
    iucn_status = models.CharField(verbose_name='保护等级', max_length=50)  # 根据IUCN(国际自然保护联盟)的评估,鸟类的保护等级。
    love_number = models.IntegerField()  # 人气值
    observations_number = models.IntegerField()  # 观察数
    date = models.DateField(auto_now_add=True, verbose_name='添加时间')

    class Meta:
        verbose_name = '鸟类数据'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

        在应用observations中的models.py中编写实体观察的数据模型代码: 

class Observation(models.Model):
    id = models.AutoField(primary_key=True)
    date = models.DateTimeField(auto_now=True, verbose_name='观察时间')
    location = models.CharField(verbose_name='观察地点', max_length=255)
    description = models.TextField(verbose_name='观察现象')
    additional_notes = models.TextField(verbose_name='备注信息', blank=True, null=True)
    observation_data = models.CharField(verbose_name='观察数据', max_length=255)
    tags = models.CharField(verbose_name='预测结果', max_length=255, blank=True)
    bird = models.ForeignKey(Bird, on_delete=models.CASCADE, blank=True, null=True)

    class Meta:
        verbose_name = '观察数据'
        verbose_name_plural = verbose_name

三、 模糊查询搜索功能:

        1.路由层:

path('search/', search, name='search')

        2.搜索框(前端):

<form action="{% url 'birds:search' %}" style="padding-left: 900px ;margin-top: 10px;margin-bottom: 5px" method="get">
   <input type="text" name='text' id="searchInput" placeholder="输入搜索内容...">
   <input type="submit" value="搜索">
</form>

        3.views层: 

def search(reqeust):
    text = reqeust.GET.get('text')
    res = Bird.objects.filter(Q(name__icontains=text) | Q(order__icontains=text) | Q(family__icontains=text)
                              | Q(size__icontains=text) | Q(plumage__icontains=text) | Q(habitat__icontains=text)
                              | Q(distribution__icontains=text) | Q(iucn_status__contains=text))
    context = {'res': res}
    return render(reqeust, 'birds/search_result.html', context)

        4.查询结果(前端): 

<tbody>
 {% for r in res %}
	 <tr>
		 <th>{{ r.id}}</th>
		 <th><img width="100" height="100" src="{% static r.images %}"/></th>
		 <th>{{ r.name}}</th>
		 <th>{{ r.order}}</th>
		 <th>{{ r.family}}</th>
		 <th>{{ r.genus}}</th>
		 <th>{{ r.size}}</th>
		 <th>{{ r.plumage}}</th>
		 <th>{{ r.habitat}}</th>
		 <th>{{ r.distribution}}</th>
		 <th>{{ r.iucn_status}}</th>
		 <th>{{ r.love_number}}</th>
		 <th>{{ r.observations_number}}</th>
		 <th>{{ r.date}}</th>
	 </tr>
 {% endfor %}
</tbody>

四、 喜欢功能:

        1.路由层:

path('love/<int:id>/<str:tags>/', love, name='love'),
path('nolove/<int:id>/<str:tags>/', nolove, name='nolove'),

        2.views层:

def love(request, id, tags):
    user_id = request.session.get('user_id')
    observations = Observation.objects.filter(id=id).first()
    user = UserInfo.objects.filter(user_id=user_id).first()
    user.love.add(observations)
    Bird.objects.filter(id=observations.bird_id).update(love_number=F('love_number') + 1)
    return redirect('/observations/knowledge/' + str(id) + '/' + str(tags) + '/')

def nolove(request, id, tags):
    user_id = request.session.get('user_id')
    observations = Observation.objects.filter(id=id).first()
    user = UserInfo.objects.filter(user_id=user_id).first()
    user.love.remove(observations)
    Bird.objects.filter(id=observations.bird_id).update(love_number=F('love_number') - 1)
    return redirect('/observations/knowledge/' + str(id) + '/' + str(tags) + '/')

        3.前端代码: 

{% if love %}
 <th>
	 <a href="{% url 'observations:nolove' id tags%}">
		 <span style="font-size: 30px">&#128148;</span>
	 </a>
 </th>
 {% else %}
 <th>
	 <a href="{% url 'observations:love' id tags%}" >
	   <span style="font-size: 30px">&#128149;</span>
	 </a>
	 <br>
 </th>
{% endif %}

五、总结:

        F 对象用于在数据库查询中进行字段之间的比较和操作,它允许在查询中使用字段的值进行计算和比较,而无需将数据提取到 Python 中进行处理,这对于处理大量数据和优化查询非常有用。

        Q 对象则用于在获取查询结果集时,使用复杂的逻辑或、逻辑与、逻辑非等操作,当涉及一个或多个查询条件时可以使用 Q 对象进行操作。

        由于项目中的表关系比较复杂,本博客不再过度赘述,望大家见谅;博客只是给大家分享一种使用F对象和Q对象实现“模糊查询搜索”与“喜欢”功能的方法。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜辰hxh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值