Django - 同一查询

时间:2017-08-01 10:39:21

标签: python django django-models

我有Book,Profile,Book_stat模型如下。我正在尝试最小化Book模型和prefetch_related方法中的字段以从Book_stat模型获取数据。

models.py

class Book(models.Model):
    title = models.CharField(max_length=200)
    image = models.FileField(upload_to="mp/", blank=True)

    def __str__(self):
        return self.title

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    full_name = models.CharField(max_length=150)

    def __str__(self):
        return self.full_name

class Book_stat(models.Model):
    user = models.ForeignKey(User)
    book = models.ForeignKey(Book)
    rating = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal('0.00'))
    like = models.BooleanField(default=False)

    def __str__(self):
        return self.book.title + ' by: ' + self.user.profile.full_name  

views.py

def books(request):
    books = books = Book.objects.prefetch_related('book_stat_set').values('id','title', 'image')
    for book in books:
        for book_stat in book.book_stat_set.all(): # error: 'dict' object has no attribute 'book_stat_set'
            book.stats = book_stat
            pprint(vars(book_stat))
    return HttpResponse(books, content_type= 'json')

1)我想将json response发送到前端,如下所示 2)如果可能,我想使用book_stat_set.values('like', 'rating')代替book_stat_set.all(),以便我仅查询likerating

books = [
    {
        id: 1,
        title: 'some title1',
        image: 'image1.jpg',
        stats: {
            like: true,
            rating: 3.50
        }
    },
    {
        id: 2,
        title: 'some title2',
        image: 'image1.jpg',
        stats: {
            like: true,
            rating: 3.50
        }
    }
]

2 个答案:

答案 0 :(得分:2)

相反,values方法可以使用only并手动序列化:

from django.db.models import Prefetch
from django.forms import model_to_dict
from django.http import JsonResponse

def books(request):
    prefetch = Prefetch('book_stat_set', queryset=Book_stat.objects.only('like', 'rating'))
    qs = Book.objects.prefetch_related(prefetch).only('id','title', 'image')
    result = []
    for book in qs:
        row = model_to_dict(book, fields=['id','title', 'image'])
        row['image'] = row['image'].url
        stats = []
        for book_stat in book.book_stat_set.all():
            stat = model_to_dict(book_stat, fields=['like', 'rating'])
            stat['rating'] = str(stat['rating'])  # or float(stat['rating']) - depends on your purposes
            stats.append(stat)
        # you can calculate an average rating here
        row['stats'] = stats
        result.append(row)
    return JsonResponse(result)

答案 1 :(得分:1)

如果您只需要手动序列化它就可以使用它。

books = Book.objects.prefetch_related('book_stat_set')

books_json = [{
    'id': book.id,
    'title': book.title,
    'image': book.image.url,
    'stats': [
        {
            'like': stat.like, 'rating': str(stat.rating)
        } for stat in book.book_stat_set.all()
        ]
} for book in books]