【问题标题】:Python Django return unique save dates and filter model objectsPython Django 返回唯一的保存日期并过滤模型对象
【发布时间】:2016-09-05 22:15:41
【问题描述】:

我有两个模型

房间和房间日志

每个单独的 Room 对象可以有多个 RoomLog 对象。 它的目的是房间对象有一个属性:值和方法save()。每次用户保存任何特定 Room 对象的更改属性并保存它时,我都会创建一个新的相关 RoomLog 对象。

RoomLog 对象具有值属性和日期属性。 日期与房间保存方法有关,因此它为房间更改值保存日期。

我的问题是:

Q1:如何从所有 RoomLog 对象返回所有唯一日期,以便我知道何时进行了任何保存?

Q2:假设我们知道如何返回唯一日期。所以,问题是:如何从这些独特的日子中选择任何一天并按所选日期显示所有 Room 对象值?我想为每个 Room 对象返回所选日期最后保存的值。

我目前解决这两个问题的方式(我正在寻找更多 Pythonic、更快、性能更好的解决方案)是:

我创建了表单,在其中迭代 RoomLog 对象:

class MyForm(forms.Form):
    roomdates = []
    roomextracted = []
    for r in RoomLog.objects.all():
        if r not in roomdates:
            roomdates.append(r.update_date)
    for i in roomdates:
        if i not in roomextracted:
            roomextracted.append(i)

    ROOMDATA = [(r, r) for r in roomextracted]
    my_choice_field = forms.ChoiceField(choices=ROOMDATA)

然后我有一个视图将选定的日期传递给另一个视图,在该视图中我按选定的日期过滤 Room.objects.all():

def choices(request):

    form = RoomLogChoices()
    form.fields['choice'].choices = list()
    testlist = []
    for rl in RoomLog.objects.all():
        if rl.update_date not in testlist:
            testlist.append(rl.update_date)
    for d in testlist:
        form.fields['choice'].choices.append(
                (
                    d,d
                )
        )


    return render(request, 'prostats/choices.html', {'form':form})

接下来我有choicesform.html,我在其中从下拉菜单中选择日期:

{% extends "base.html" %}
{% block content %}

<form action="" method="post" >
{% csrf_token %}

<ul>
{% for choice in form.my_choice_field.field.choices %}
  <li>
    <input type="radio" name="my_choice_field" value="{{choice.0}}"
      {% if equal form.my_choice_field.data choice.0 %}
         checked="checked"
      {% endifequal %}/>
    <label for="">{{choice.1}}</label>
  </li>
{% endfor %}
</ul>

<input type="submit" value="Submit" />
</form>

{% endblock %}

这是我处理 POST 数据的视图

class AllRoomsView(ListView):
    template_name = 'prostats/roomsdetail.html'
    queryset = Room.objects.all()

    def get_context_data(self, **kwargs):


        context = super(AllRoomsView, self).get_context_data(**kwargs)

        context['rooms'] = Room.objects.all()
        context['rlog'] = RoomLog.objects.all()



        roomsdates = []

        for r in context['rlog']:
            if r not in roomsdates:
                roomsdates.append(r.update_date)

        roomextracted = []
        for i in roomsdates:
            if i not in roomextracted:
                roomextracted.append(i)

        context['roomextracted'] = roomextracted
        choicedate = self.request.GET.get('choice')
        if choicedate != None:
            choosend = choicedate
        else:
            choosend = '2016-02-01'



        #filtered rlogs
        rlfilteredempty = []
        for r in context['rooms']:
            i = RoomLog.objects.filter(room=r.id, update_date__lte = choosend).order_by('-update_date')[:1]
            if i:
                rlfilteredempty.append(i[0])
            else:
                rlfilteredempty.append(r)
        context['rlfiltered'] = rlfilteredempty




        context['choicedate'] = self.request.GET.get('choice')
        #context['roomfiltersettime'] = RoomLog.objects.filter(update_date__lte = choosend)
        context['roomfiltersettime'] = RoomLog.objects.filter(update_date__lte = choosend)

        rslice = []
        for r in context['rooms']:
            i = RoomLog.objects.filter(room=r.id, update_date__lte = choosend).order_by('-update_date')[:1]
            if i:
                for rsobject in i:
                    rs = (r.flat.flat_number,r.flat.block.block_name,r.room_name)
                    rl = rsobject.id
                    rv = rsobject.room_value
                    rslice.append((rs,rl,rv))
            else:
                rs = (r.flat.flat_number,r.flat.block.block_name,r.room_name)
                r = r.id
                rslice.append((rs,r))

        context['rslice'] = rslice

所以,我所做的一切我都觉得不是很好,也许有人可以为我提供一些关于如何更好地解决这个问题的好主意?


编辑:使用我的 Room 和 RoomLog 模型更新帖子:

class Room(models.Model):
    room_name = models.CharField(max_length= 10)
    room_value = models.PositiveSmallIntegerField(default=0)
    flat = models.ForeignKey(Flat)
    created_date = models.DateField(auto_now_add= True)
    created_time = models.TimeField(auto_now_add= True)
    substage_name = models.CharField(max_length=50,default="")

    def __init__(self, *args, **kwargs):
        super(Room, self).__init__(*args, **kwargs)
        self.value_original = self.room_value

    def save(self, **kwargs):
        with transaction.atomic():
            response = super(Room, self).save(**kwargs)
            if self.value_original != self.room_value:
                room_log = RoomLog()
                room_log.room = self
                room_log.room_value = self.value_original
                room_log.save()
            return response



class RoomLog(models.Model):
    room = models.ForeignKey(Room)
    room_value = models.PositiveSmallIntegerField(default=0)
    update_date = models.DateField(auto_now_add= True)
    update_time = models.TimeField(auto_now_add= True)

【问题讨论】:

    标签: python django filter save models


    【解决方案1】:

    要返回所有唯一日期,请在您的 created_date 字段中使用 distinct()。当然,这只有在 created_date 实际上是一个 date 而不是 datetime 值时才有效!

    RoomLog.objects.all().distinct('created_date')
    

    如果您的created 值是datetime,您需要先将其设为日期,使用Django 的func()F() 函数。这使用了DATE() SQL 函数,这些函数可能不适用于所有数据库,但它适用于 Postgres 和可能的许多其他数据库。

    RoomLog.objects.all()\
           .annotate(created_date=Func(F('created'), function='DATE'))\
           .order_by('-created_date')\
           .distinct('created_date')
    

    只是部分答案。第二个问题取决于您未发布的模型的布局。

    【讨论】:

    • 嗨,一切正常(我的意思是 .distinct() 不需要 .annotate().order_by().disctinct。谢谢 PS。我刚刚编辑了帖子并添加了模型。
    猜你喜欢
    • 2021-02-26
    • 2020-08-10
    • 2021-04-02
    • 1970-01-01
    • 2021-03-24
    • 2013-03-16
    • 2021-01-26
    • 2017-09-06
    相关资源
    最近更新 更多