我有一个数据库,里面有用户、图片和评论(用户可以评论图片)。我正在尝试在数据库中查询当前登录用户尚未评论的第一张图片。我让它在原始 SQL 中工作,但更愿意正确地做到这一点。
如何将原始 SQL 转换为常规 Django 代码?
相关代码
模型.py
from django.contrib.auth.models import User
from django.db import models
class Comment(models.Model):
user = models.ForeignKey(User)
picture = models.ForeignKey('Picture')
body = models.TextField()
def __unicode__(self):
return u'%s: %s' % (self.user.get_full_name(), self.picture.title)
class Picture(models.Model):
title = models.CharField(max_length=100)
order = models.PositiveIntegerField()
class Meta:
ordering = ('order',)
def __unicode__(self):
return self.title
网址.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
from core import views
urlpatterns = patterns('',
url(r'^$', views.Home.as_view(), name='home'),
url(r'^admin/', include(admin.site.urls)),
)
视图.py
from django.views.generic.base import TemplateView
from .models import Picture
class Home(TemplateView):
template_name = 'core/first_picture_without_comment.html'
def get_context_data(self, **kwargs):
sql = '''
SELECT `core_picture`.`id`, COUNT(`comments_made`.`id`) AS `count`
FROM `core_picture`
LEFT OUTER JOIN (
SELECT `core_comment`.`id`, `core_comment`.`picture_id`
FROM `core_comment`
WHERE `core_comment`.`user_id` = %s
) AS `comments_made` ON (`core_picture`.`id` = `comments_made`.`picture_id`)
GROUP BY `core_picture`.`id`
HAVING `count` = 0
ORDER BY `core_picture`.`order`
LIMIT 1
'''
sql_params = [
self.request.user.pk,
]
picture = Picture.objects.raw(sql, sql_params)[0]
return {
'picture': picture,
}
first_picture_without_comment.html
<h1>The First Picture You Have Not Commented On</h1>
<p>{{ picture.title }}</p>
如何测试
将测试应用程序命名为“核心”。运行syncdb
(一定要创建一个超级用户!)然后将此数据插入数据库:
INSERT INTO `auth_user` VALUES(2, 'john_doe', 'John', 'Doe', 'john_doe@example.com', '', 1, 1, 0, '2013-06-11 02:23:23', '2013-06-11 02:01:07');
INSERT INTO `auth_user` VALUES(3, 'jane_doe', 'Jane', 'Doe', 'jane_doe@example.com', '', 1, 1, 0, '2013-06-11 02:01:21', '2013-06-11 02:01:21');
INSERT INTO `core_picture` VALUES(1, 'Foo', 4);
INSERT INTO `core_picture` VALUES(2, 'Bar', 3);
INSERT INTO `core_picture` VALUES(3, 'Baz', 2);
INSERT INTO `core_picture` VALUES(4, 'Qux', 1);
INSERT INTO `core_comment` VALUES(1, 2, 1, 'This picture is great!');
INSERT INTO `core_comment` VALUES(2, 2, 4, 'I like this picture!');
INSERT INTO `core_comment` VALUES(3, 3, 4, 'I like this picture too!');
INSERT INTO `core_comment` VALUES(4, 2, 4, 'I like it more!');
INSERT INTO `core_comment` VALUES(5, 3, 2, 'This picture is awesome!');
INSERT INTO `core_comment` VALUES(6, 3, 3, 'I love this!');
进入 Django admin 并为两个普通用户设置密码。之后,您可以登录每个人进行测试。John Doe 应该说“Baz”,而 Jane Doe 应该说“Foo”。这是对的; 我只想知道如何在不使用原始 SQL 的情况下做到这一点。