Пример #1
0
def export_schedule(request, pk, uidb64=None, token=None):
    '''
    Export the current schedule as an iCal file
    '''

    # Load the schedule
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            schedule = get_object_or_404(Schedule, pk=pk)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        schedule = get_object_or_404(Schedule, pk=pk, user=request.user)

    # Create the calendar
    calendar = get_calendar()

    # Create the events and add them to the calendar
    start_date = datetime.date.today()
    for step in schedule.schedulestep_set.all():
        get_events_workout(calendar, step.workout, step.duration, start_date)
        start_date = start_date + datetime.timedelta(weeks=step.duration)

    # Send the file to the user
    response = HttpResponse(content_type='text/calendar')
    response['Content-Disposition'] = \
        'attachment; filename=Calendar-schedule-{0}.ics'.format(schedule.pk)
    response.write(calendar.to_ical())
    response['Content-Length'] = len(response.content)
    return response
Пример #2
0
def workout_json(request, id, comments=False, uidb64=None, token=None):
    '''
    Generates a JSON with the contents of the given workout
    and allows user to download in browser
    '''

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=id, user=request.user)

    # package response and download file in browser
    response = HttpResponse(str(workout.canonical_representation),
                            content_type='application/json')
    response[
        'Content-Disposition'] = 'attachment; filename=Workout-{0}.json'.format(
            id)
    response['Content-Length'] = len(response.content)
    return response
Пример #3
0
def export(request, pk, uidb64=None, token=None):
    '''
    Export the current workout as an iCal file
    '''

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=pk)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=pk, user=request.user)

    # Create the calendar
    calendar = get_calendar()

    # Create the events and add them to the calendar
    get_events_workout(calendar, workout,
                       workout.user.userprofile.workout_duration)

    # Send the file to the user
    response = HttpResponse(content_type='text/calendar')
    response['Content-Disposition'] = \
        'attachment; filename=Calendar-workout-{0}.ics'.format(workout.pk)
    response.write(calendar.to_ical())
    response['Content-Length'] = len(response.content)
    return response
Пример #4
0
def export(request, pk, uidb64=None, token=None):
    '''
    Export the current workout as an iCal file
    '''

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=pk)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=pk, user=request.user)

    # Create the calendar
    calendar = get_calendar()

    # Create the events and add them to the calendar
    get_events_workout(calendar, workout, workout.user.userprofile.workout_duration)

    # Send the file to the user
    response = HttpResponse(content_type='text/calendar')
    response['Content-Disposition'] = \
        'attachment; filename=Calendar-workout-{0}.ics'.format(workout.pk)
    response.write(calendar.to_ical())
    response['Content-Length'] = len(response.content)
    return response
Пример #5
0
def export_schedule(request, pk, uidb64=None, token=None):
    '''
    Export the current schedule as an iCal file
    '''

    # Load the schedule
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            schedule = get_object_or_404(Schedule, pk=pk)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        schedule = get_object_or_404(Schedule, pk=pk, user=request.user)

    # Create the calendar
    calendar = get_calendar()

    # Create the events and add them to the calendar
    start_date = datetime.date.today()
    for step in schedule.schedulestep_set.all():
        get_events_workout(calendar, step.workout, step.duration, start_date)
        start_date = start_date + datetime.timedelta(weeks=step.duration)

    # Send the file to the user
    response = HttpResponse(content_type='text/calendar')
    response['Content-Disposition'] = \
        'attachment; filename=Calendar-schedule-{0}.ics'.format(schedule.pk)
    response.write(calendar.to_ical())
    response['Content-Length'] = len(response.content)
    return response
Пример #6
0
def export_pdf(request, pk, uidb64=None, token=None):
    '''
    Show the workout schedule
    '''
    user = request.user

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            schedule = get_object_or_404(Schedule, pk=pk)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        schedule = get_object_or_404(Schedule, pk=pk, user=user)

    # Create the HttpResponse object with the appropriate PDF headers.
    # and use it to the create the PDF using it as a file like object
    response = HttpResponse(content_type='application/pdf')
    doc = SimpleDocTemplate(response,
                            pagesize=A4,
                            leftMargin=cm,
                            rightMargin=cm,
                            topMargin=0.5 * cm,
                            bottomMargin=0.5 * cm,
                            title=_('Workout'),
                            author='wger Workout Manager',
                            subject='Schedule for {0}'.format(request.user.username))

    # container for the 'Flowable' objects
    elements = []

    # Set the title
    p = Paragraph(u'<para align="center">{0}</para>'.format(schedule), styleSheet["HeaderBold"])
    elements.append(p)
    elements.append(Spacer(10 * cm, 0.5 * cm))

    # Iterate through the Workout and render the training days
    for step in schedule.schedulestep_set.all():
        p = Paragraph(u'<para>{0} {1}</para>'.format(step.duration, _('Weeks')),
                      styleSheet["HeaderBold"])
        elements.append(p)
        elements.append(Spacer(10 * cm, 0.5 * cm))

        for day in step.workout.canonical_representation['day_list']:
            elements.append(render_workout_day(day, nr_of_weeks=7))
            elements.append(Spacer(10 * cm, 0.5 * cm))

    # Footer, date and info
    elements.append(Spacer(10 * cm, 0.5 * cm))
    url = reverse('manager:schedule:view', kwargs={'pk': schedule.id})
    elements.append(render_footer(request.build_absolute_uri(url)))

    # write the document and send the response to the browser
    doc.build(elements)
    response['Content-Disposition'] = 'attachment; filename=Schedule-{0}-log.pdf'.format(pk)
    response['Content-Length'] = len(response.content)
    return response
Пример #7
0
def export_pdf(request, pk, uidb64=None, token=None):
    '''
    Show the workout schedule
    '''
    user = request.user

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            schedule = get_object_or_404(Schedule, pk=pk)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        schedule = get_object_or_404(Schedule, pk=pk, user=user)

    # Create the HttpResponse object with the appropriate PDF headers.
    # and use it to the create the PDF using it as a file like object
    response = HttpResponse(content_type='application/pdf')
    doc = SimpleDocTemplate(response,
                            pagesize=A4,
                            leftMargin=cm,
                            rightMargin=cm,
                            topMargin=0.5 * cm,
                            bottomMargin=0.5 * cm,
                            title=_('Workout'),
                            author='wger Workout Manager',
                            subject='Schedule for {0}'.format(request.user.username))

    # container for the 'Flowable' objects
    elements = []

    # Set the title
    p = Paragraph(u'<para align="center">{0}</para>'.format(schedule), styleSheet["HeaderBold"])
    elements.append(p)
    elements.append(Spacer(10*cm, 0.5*cm))

    # Iterate through the Workout and render the training days
    for step in schedule.schedulestep_set.all():
        p = Paragraph(u'<para>{0} {1}</para>'.format(step.duration, _('Weeks')),
                      styleSheet["HeaderBold"])
        elements.append(p)
        elements.append(Spacer(10*cm, 0.5*cm))

        for day in step.workout.canonical_representation['day_list']:
            elements.append(render_workout_day(day, nr_of_weeks=7))
            elements.append(Spacer(10*cm, 0.5*cm))

    # Footer, date and info
    elements.append(Spacer(10*cm, 0.5*cm))
    url = reverse('manager:schedule:view', kwargs={'pk': schedule.id})
    elements.append(render_footer(request.build_absolute_uri(url)))

    # write the document and send the response to the browser
    doc.build(elements)
    response['Content-Disposition'] = 'attachment; filename=Schedule-{0}-log.pdf'.format(pk)
    response['Content-Length'] = len(response.content)
    return response
Пример #8
0
def workout_log(request,
                id,
                images=False,
                comments=False,
                uidb64=None,
                token=None):
    """
    Generates a PDF with the contents of the given workout

    See also
    * http://www.blog.pythonlibrary.org/2010/09/21/reportlab
    * http://www.reportlab.com/apis/reportlab/dev/platypus.html
    """
    comments = bool(int(comments))
    images = bool(int(images))

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=id, user=request.user)

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')

    # Create the PDF object, using the response object as its "file."
    doc = SimpleDocTemplate(
        response,
        pagesize=A4,
        # pagesize = landscape(A4),
        leftMargin=cm,
        rightMargin=cm,
        topMargin=0.5 * cm,
        bottomMargin=0.5 * cm,
        title=_('Workout'),
        author='wger Workout Manager',
        subject=_('Workout for %s') % request.user.username)

    # container for the 'Flowable' objects
    elements = []

    # Set the title
    p = Paragraph(
        '<para align="center"><strong>%(description)s</strong></para>' %
        {'description': workout}, styleSheet["HeaderBold"])
    elements.append(p)
    elements.append(Spacer(10 * cm, 0.5 * cm))

    # Iterate through the Workout and render the training days
    for day in workout.canonical_representation['day_list']:
        elements.append(
            render_workout_day(day, images=images, comments=comments))
        elements.append(Spacer(10 * cm, 0.5 * cm))

    # Footer, date and info
    elements.append(Spacer(10 * cm, 0.5 * cm))
    elements.append(
        render_footer(request.build_absolute_uri(workout.get_absolute_url())))

    # write the document and send the response to the browser
    doc.build(elements)

    # Create the HttpResponse object with the appropriate PDF headers.
    response[
        'Content-Disposition'] = 'attachment; filename=Workout-{0}-log.pdf'.format(
            id)
    response['Content-Length'] = len(response.content)
    return response
Пример #9
0
def export_pdf(request, id, uidb64=None, token=None):
    """
    Generates a PDF with the contents of a nutrition plan

    See also
    * http://www.blog.pythonlibrary.org/2010/09/21/reportlab
    * http://www.reportlab.com/apis/reportlab/dev/platypus.html
    """

    # Load the plan
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            plan = get_object_or_404(NutritionPlan, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous:
            return HttpResponseForbidden()
        plan = get_object_or_404(NutritionPlan, pk=id, user=request.user)

    plan_data = plan.get_nutritional_values()

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')

    # Create the PDF object, using the response object as its "file."
    doc = SimpleDocTemplate(
        response,
        pagesize=A4,
        title=_('Nutritional plan'),
        author='wger Workout Manager',
        subject=_('Nutritional plan for %s') % request.user.username,
        topMargin=1 * cm,
    )

    # container for the 'Flowable' objects
    elements = []
    data = []

    # Iterate through the Plan
    meal_markers = []
    ingredient_markers = []

    # Meals
    i = 0
    for meal in plan.meal_set.select_related():
        i += 1

        meal_markers.append(len(data))

        if not meal.time:
            p = Paragraph(
                '<para align="center"><strong>{nr} {meal_nr}</strong></para>'.
                format(nr=_('Nr.'), meal_nr=i), styleSheet["SubHeader"])
        else:
            p = Paragraph(
                '<para align="center"><strong>'
                '{nr} {meal_nr} - {meal_time}'
                '</strong></para>'.format(
                    nr=_('Nr.'),
                    meal_nr=i,
                    meal_time=meal.time.strftime("%H:%M")),
                styleSheet["SubHeader"])
        data.append([p])

        # Ingredients
        for item in meal.mealitem_set.select_related():
            ingredient_markers.append(len(data))

            p = Paragraph('<para>{0}</para>'.format(item.ingredient.name),
                          styleSheet["Normal"])
            if item.get_unit_type() == MEALITEM_WEIGHT_GRAM:
                unit_name = 'g'
            else:
                unit_name = ' × ' + item.weight_unit.unit.name

            data.append([
                Paragraph("{0:.0f}{1}".format(item.amount, unit_name),
                          styleSheet["Normal"]), p
            ])

        # Add filler
        data.append([Spacer(1 * cm, 0.6 * cm)])

    # Set general table styles
    table_style = []

    # Set specific styles, e.g. background for title cells
    for marker in meal_markers:
        # Set background colour for headings
        table_style.append(
            ('BACKGROUND', (0, marker), (-1, marker), header_colour))
        table_style.append(
            ('BOX', (0, marker), (-1, marker), 1.25, colors.black))

        # Make the headings span the whole width
        table_style.append(('SPAN', (0, marker), (-1, marker)))

    # has the plan any data?
    if data:
        t = Table(data, style=table_style)

        # Manually set the width of the columns
        t._argW[0] = 3.5 * cm

    # There is nothing to output
    else:
        t = Paragraph(
            _('<i>This is an empty plan, what did you expect on the PDF?</i>'),
            styleSheet["Normal"])

    # Add site logo
    elements.append(get_logo())
    elements.append(Spacer(10 * cm, 0.5 * cm))

    # Set the title (if available)
    if plan.description:

        p = Paragraph(
            '<para align="center"><strong>%(description)s</strong></para>' %
            {'description': plan.description}, styleSheet["HeaderBold"])
        elements.append(p)

        # Filler
        elements.append(Spacer(10 * cm, 1.5 * cm))

    # append the table to the document
    elements.append(t)
    elements.append(Paragraph('<para>&nbsp;</para>', styleSheet["Normal"]))

    # Create table with nutritional calculations
    data = []
    data.append([
        Paragraph(
            '<para align="center">{0}</para>'.format(_('Nutritional data')),
            styleSheet["SubHeaderBlack"])
    ])
    data.append([
        Paragraph(_('Macronutrients'), styleSheet["Normal"]),
        Paragraph(_('Total'), styleSheet["Normal"]),
        Paragraph(_('Percent of energy'), styleSheet["Normal"]),
        Paragraph(_('g per body kg'), styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Energy'), styleSheet["Normal"]),
        Paragraph(str(plan_data['total']['energy']), styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Protein'), styleSheet["Normal"]),
        Paragraph(str(plan_data['total']['protein']), styleSheet["Normal"]),
        Paragraph(str(plan_data['percent']['protein']), styleSheet["Normal"]),
        Paragraph(str(plan_data['per_kg']['protein']), styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Carbohydrates'), styleSheet["Normal"]),
        Paragraph(str(plan_data['total']['carbohydrates']),
                  styleSheet["Normal"]),
        Paragraph(str(plan_data['percent']['carbohydrates']),
                  styleSheet["Normal"]),
        Paragraph(str(plan_data['per_kg']['carbohydrates']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph("    " + _('Sugar content in carbohydrates'),
                  styleSheet["Normal"]),
        Paragraph(str(plan_data['total']['carbohydrates_sugar']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Fat'), styleSheet["Normal"]),
        Paragraph(str(plan_data['total']['fat']), styleSheet["Normal"]),
        Paragraph(str(plan_data['percent']['fat']), styleSheet["Normal"]),
        Paragraph(str(plan_data['per_kg']['fat']), styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Saturated fat content in fats'), styleSheet["Normal"]),
        Paragraph(str(plan_data['total']['fat_saturated']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Fibres'), styleSheet["Normal"]),
        Paragraph(str(plan_data['total']['fibres']), styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Sodium'), styleSheet["Normal"]),
        Paragraph(str(plan_data['total']['sodium']), styleSheet["Normal"])
    ])

    table_style = []
    table_style.append(('BOX', (0, 0), (-1, -1), 1.25, colors.black))
    table_style.append(('GRID', (0, 0), (-1, -1), 0.40, colors.black))
    table_style.append(('SPAN', (0, 0), (-1, 0)))  # Title
    table_style.append(('SPAN', (1, 2), (-1, 2)))  # Energy
    table_style.append(('BACKGROUND', (0, 3), (-1, 3), row_color))  # Protein
    table_style.append(
        ('BACKGROUND', (0, 4), (-1, 4), row_color))  # Carbohydrates
    table_style.append(('SPAN', (1, 5), (-1, 5)))  # Sugar
    table_style.append(('LEFTPADDING', (0, 5), (0, 5), 15))
    table_style.append(('BACKGROUND', (0, 6), (-1, 6), row_color))  # Fats
    table_style.append(('SPAN', (1, 7), (-1, 7)))  # Saturated fats
    table_style.append(('LEFTPADDING', (0, 7), (0, 7), 15))
    table_style.append(('SPAN', (1, 8), (-1, 8)))  # Fibres
    table_style.append(('SPAN', (1, 9), (-1, 9)))  # Sodium
    t = Table(data, style=table_style)
    t._argW[0] = 6 * cm
    elements.append(t)

    # Footer, date and info
    elements.append(Spacer(10 * cm, 0.5 * cm))
    elements.append(
        render_footer(request.build_absolute_uri(plan.get_absolute_url())))
    doc.build(elements)

    response[
        'Content-Disposition'] = 'attachment; filename=nutritional-plan.pdf'
    response['Content-Length'] = len(response.content)
    return response
Пример #10
0
def export_pdf(request, id, uidb64=None, token=None):
    '''
    Generates a PDF with the contents of a nutrition plan

    See also
    * http://www.blog.pythonlibrary.org/2010/09/21/reportlab
    * http://www.reportlab.com/apis/reportlab/dev/platypus.html
    '''

    # Load the plan
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            plan = get_object_or_404(NutritionPlan, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        plan = get_object_or_404(NutritionPlan, pk=id, user=request.user)

    plan_data = plan.get_nutritional_values()

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')

    # Create the PDF object, using the response object as its "file."
    doc = SimpleDocTemplate(response,
                            pagesize=A4,
                            title=_('Workout'),
                            author='wger Workout Manager',
                            subject=_('Nutritional plan %s') %
                            request.user.username)

    # Background colour for header
    # Reportlab doesn't use the HTML hexadecimal format, but has a range of
    # 0 till 1, so we have to convert here.
    header_colour = colors.Color(
        int('73', 16) / 255.0,
        int('8a', 16) / 255.0,
        int('5f', 16) / 255.0)

    # container for the 'Flowable' objects
    elements = []
    data = []

    # Iterate through the Plan
    meal_markers = []
    ingredient_markers = []

    # Meals
    i = 0
    for meal in plan.meal_set.select_related():
        i += 1

        meal_markers.append(len(data))

        if not meal.time:
            p = Paragraph(
                u'<para align="center"><strong>{nr} {meal_nr}</strong></para>'.
                format(nr=_('Nr.'), meal_nr=i), styleSheet["Normal"])
        else:
            p = Paragraph(
                u'<para align="center"><strong>'
                u'{nr} {meal_nr} - {meal_time}'
                u'</strong></para>'.format(
                    nr=_('Nr.'),
                    meal_nr=i,
                    meal_time=meal.time.strftime("%H:%M")),
                styleSheet["Normal"])
        data.append([p])

        # Ingredients
        for item in meal.mealitem_set.select_related():
            ingredient_markers.append(len(data))

            p = Paragraph(u'<para>{0}</para>'.format(item.ingredient.name),
                          styleSheet["Normal"])
            if item.get_unit_type() == MEALITEM_WEIGHT_GRAM:
                unit_name = 'g'
            else:
                unit_name = ' ' + item.weight_unit.unit.name

            data.append([
                Paragraph(u"{0}{1}".format(item.amount, unit_name),
                          styleSheet["Normal"]), p
            ])

    # Set general table styles
    table_style = []

    # Set specific styles, e.g. background for title cells
    for marker in meal_markers:
        # Set background colour for headings
        table_style.append(
            ('BACKGROUND', (0, marker), (-1, marker), header_colour))
        table_style.append(
            ('BOX', (0, marker), (-1, marker), 1.25, colors.black))

        # Make the headings span the whole width
        table_style.append(('SPAN', (0, marker), (-1, marker)))

    # has the plan any data?
    if data:
        t = Table(data, style=table_style)

        # Manually set the width of the columns
        t._argW[0] = 2.5 * cm

    # There is nothing to output
    else:
        t = Paragraph(
            _('<i>This is an empty plan, what did you expect on the PDF?</i>'),
            styleSheet["Normal"])

    # Set the title (if available)
    if plan.description:
        p = Paragraph(
            '<para align="center"><strong>%(description)s</strong></para>' %
            {'description': plan.description}, styleSheet["Bold"])
        elements.append(p)

        # Filler
        elements.append(Spacer(10 * cm, 0.5 * cm))

    # append the table to the document
    elements.append(t)
    elements.append(Paragraph('<para>&nbsp;</para>', styleSheet["Normal"]))

    # Create table with nutritional calculations
    data = []
    data.append([
        Paragraph(
            u'<para align="center">{0}</para>'.format(_('Nutritional data')),
            styleSheet["Bold"])
    ])
    data.append([
        Paragraph(_('Macronutrients'), styleSheet["Normal"]),
        Paragraph(_('Total'), styleSheet["Normal"]),
        Paragraph(_('Percent of energy'), styleSheet["Normal"]),
        Paragraph(_('g per body kg'), styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Energy'), styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['total']['energy']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Protein'), styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['total']['protein']),
                  styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['percent']['protein']),
                  styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['per_kg']['protein']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Carbohydrates'), styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['total']['carbohydrates']),
                  styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['percent']['carbohydrates']),
                  styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['per_kg']['carbohydrates']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Sugar content in carbohydrates'), styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['total']['carbohydrates_sugar']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Fat'), styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['total']['fat']),
                  styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['percent']['fat']),
                  styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['per_kg']['fat']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Saturated fat content in fats'), styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['total']['fat_saturated']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Fibres'), styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['total']['fibres']),
                  styleSheet["Normal"])
    ])
    data.append([
        Paragraph(_('Sodium'), styleSheet["Normal"]),
        Paragraph(six.text_type(plan_data['total']['sodium']),
                  styleSheet["Normal"])
    ])

    table_style = []
    table_style.append(('BOX', (0, 0), (-1, -1), 1.25, colors.black))
    table_style.append(('GRID', (0, 0), (-1, -1), 0.40, colors.black))
    table_style.append(('SPAN', (0, 0), (-1, 0)))  # Title
    table_style.append(('SPAN', (1, 2), (-1, 2)))  # Energy
    table_style.append(('SPAN', (1, 5), (-1, 5)))  # Sugar
    table_style.append(('SPAN', (1, 7), (-1, 7)))  # Saturated fats
    table_style.append(('SPAN', (1, 8), (-1, 8)))  # Fibres
    table_style.append(('SPAN', (1, 9), (-1, 9)))  # Sodium
    t = Table(data, style=table_style)
    t._argW[0] = 5 * cm
    elements.append(t)

    # Footer, date and info
    elements.append(Spacer(10 * cm, 0.5 * cm))
    created = datetime.date.today().strftime("%d.%m.%Y")
    url = reverse('nutrition-view', kwargs={'id': plan.id})
    p = Paragraph(
        '''<para align="left">
                        %(date)s -
                        <a href="%(url)s">%(url)s</a> -
                        %(created)s
                        %(version)s
                    </para>''' % {
            'date': _("Created on the <b>%s</b>") % created,
            'created': "wger Workout Manager",
            'version': get_version(),
            'url': request.build_absolute_uri(url),
        }, styleSheet["Normal"])
    elements.append(p)
    doc.build(elements)

    response[
        'Content-Disposition'] = 'attachment; filename=nutritional-plan.pdf'
    response['Content-Length'] = len(response.content)
    return response
Пример #11
0
def workout_log(request, id, images=False, comments=False, uidb64=None, token=None):
    '''
    Generates a PDF with the contents of the given workout

    See also
    * http://www.blog.pythonlibrary.org/2010/09/21/reportlab
    * http://www.reportlab.com/apis/reportlab/dev/platypus.html
    '''
    comments = bool(int(comments))
    images = bool(int(images))

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=id, user=request.user)

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')

    # Create the PDF object, using the response object as its "file."
    doc = SimpleDocTemplate(response,
                            pagesize=A4,
                            # pagesize = landscape(A4),
                            leftMargin=cm,
                            rightMargin=cm,
                            topMargin=0.5 * cm,
                            bottomMargin=0.5 * cm,
                            title=_('Workout'),
                            author='wger Workout Manager',
                            subject=_('Workout for %s') % request.user.username)

    # container for the 'Flowable' objects
    elements = []

    # Set the title
    p = Paragraph('<para align="center"><strong>%(description)s</strong></para>' %
                  {'description': workout},
                  styleSheet["HeaderBold"])
    elements.append(p)
    elements.append(Spacer(10 * cm, 0.5 * cm))

    # Iterate through the Workout and render the training days
    for day in workout.canonical_representation['day_list']:
        elements.append(render_workout_day(day, images=images, comments=comments))
        elements.append(Spacer(10 * cm, 0.5 * cm))

    # Footer, date and info
    elements.append(Spacer(10 * cm, 0.5 * cm))
    elements.append(render_footer(request.build_absolute_uri(workout.get_absolute_url())))

    # write the document and send the response to the browser
    doc.build(elements)

    # Create the HttpResponse object with the appropriate PDF headers.
    response['Content-Disposition'] = 'attachment; filename=Workout-{0}-log.pdf'.format(id)
    response['Content-Length'] = len(response.content)
    return response
Пример #12
0
def export_pdf(request, id, uidb64=None, token=None):
    '''
    Generates a PDF with the contents of a nutrition plan

    See also
    * http://www.blog.pythonlibrary.org/2010/09/21/reportlab
    * http://www.reportlab.com/apis/reportlab/dev/platypus.html
    '''

    # Load the plan
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            plan = get_object_or_404(NutritionPlan, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        plan = get_object_or_404(NutritionPlan, pk=id, user=request.user)

    plan_data = plan.get_nutritional_values()

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')

    # Create the PDF object, using the response object as its "file."
    doc = SimpleDocTemplate(response,
                            pagesize=A4,
                            title=_('Nutrition plan'),
                            author='wger Workout Manager',
                            subject=_('Nutritional plan %s') % request.user.username)

    # Background colour for header
    # Reportlab doesn't use the HTML hexadecimal format, but has a range of
    # 0 till 1, so we have to convert here.
    header_colour = colors.Color(int('73', 16) / 255.0,
                                 int('8a', 16) / 255.0,
                                 int('5f', 16) / 255.0)

    # container for the 'Flowable' objects
    elements = []
    data = []

    # Iterate through the Plan
    meal_markers = []
    ingredient_markers = []

    # Meals
    i = 0
    for meal in plan.meal_set.select_related():
        i += 1

        meal_markers.append(len(data))

        if not meal.time:
            p = Paragraph(u'<para align="center"><strong>{nr} {meal_nr}</strong></para>'
                          .format(nr=_('Nr.'), meal_nr=i),
                          styleSheet["Normal"])
        else:
            p = Paragraph(u'<para align="center"><strong>'
                          u'{nr} {meal_nr} - {meal_time}'
                          u'</strong></para>'
                          .format(nr=_('Nr.'), meal_nr=i, meal_time=meal.time.strftime("%H:%M")),
                          styleSheet["Normal"])
        data.append([p])

        # Ingredients
        for item in meal.mealitem_set.select_related():
            ingredient_markers.append(len(data))

            p = Paragraph(u'<para>{0}</para>'.format(item.ingredient.name), styleSheet["Normal"])
            if item.get_unit_type() == MEALITEM_WEIGHT_GRAM:
                unit_name = 'g'
            else:
                unit_name = ' ' + item.weight_unit.unit.name

            data.append([Paragraph(u"{0}{1}".format(item.amount, unit_name), styleSheet["Normal"]),
                         p])

    # Set general table styles
    table_style = []

    # Set specific styles, e.g. background for title cells
    for marker in meal_markers:
        # Set background colour for headings
        table_style.append(('BACKGROUND', (0, marker), (-1, marker), header_colour))
        table_style.append(('BOX', (0, marker), (-1, marker), 1.25, colors.black))

        # Make the headings span the whole width
        table_style.append(('SPAN', (0, marker), (-1, marker)))

    # has the plan any data?
    if data:
        t = Table(data, style=table_style)

        # Manually set the width of the columns
        t._argW[0] = 2.5 * cm

    # There is nothing to output
    else:
        t = Paragraph(_('<i>This is an empty plan, what did you expect on the PDF?</i>'),
                      styleSheet["Normal"])

    # Set the title (if available)
    if plan.description:
        p = Paragraph('<para align="center"><strong>%(description)s</strong></para>' %
                      {'description': plan.description},
                      styleSheet["Bold"])
        elements.append(p)

        # Filler
        elements.append(Spacer(10 * cm, 0.5 * cm))

    # append the table to the document
    elements.append(t)
    elements.append(Paragraph('<para>&nbsp;</para>', styleSheet["Normal"]))

    # Create table with nutritional calculations
    data = []
    data.append([Paragraph(u'<para align="center">{0}</para>'.format(_('Nutritional data')),
                 styleSheet["Bold"])])
    data.append([Paragraph(_('Macronutrients'), styleSheet["Normal"]),
                 Paragraph(_('Total'), styleSheet["Normal"]),
                 Paragraph(_('Percent of energy'), styleSheet["Normal"]),
                 Paragraph(_('g per body kg'), styleSheet["Normal"])])
    data.append([Paragraph(_('Energy'), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['total']['energy']), styleSheet["Normal"])])
    data.append([Paragraph(_('Protein'), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['total']['protein']), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['percent']['protein']), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['per_kg']['protein']), styleSheet["Normal"])])
    data.append([Paragraph(_('Carbohydrates'), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['total']['carbohydrates']),
                           styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['percent']['carbohydrates']),
                           styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['per_kg']['carbohydrates']),
                           styleSheet["Normal"])])
    data.append([Paragraph(_('Sugar content in carbohydrates'), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['total']['carbohydrates_sugar']),
                           styleSheet["Normal"])])
    data.append([Paragraph(_('Fat'), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['total']['fat']), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['percent']['fat']), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['per_kg']['fat']), styleSheet["Normal"])])
    data.append([Paragraph(_('Saturated fat content in fats'), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['total']['fat_saturated']),
                           styleSheet["Normal"])])
    data.append([Paragraph(_('Fibres'), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['total']['fibres']), styleSheet["Normal"])])
    data.append([Paragraph(_('Sodium'), styleSheet["Normal"]),
                 Paragraph(six.text_type(plan_data['total']['sodium']), styleSheet["Normal"])])

    table_style = []
    table_style.append(('BOX', (0, 0), (-1, -1), 1.25, colors.black))
    table_style.append(('GRID', (0, 0), (-1, -1), 0.40, colors.black))
    table_style.append(('SPAN', (0, 0), (-1, 0)))  # Title
    table_style.append(('SPAN', (1, 2), (-1, 2)))  # Energy
    table_style.append(('SPAN', (1, 5), (-1, 5)))  # Sugar
    table_style.append(('SPAN', (1, 7), (-1, 7)))  # Saturated fats
    table_style.append(('SPAN', (1, 8), (-1, 8)))  # Fibres
    table_style.append(('SPAN', (1, 9), (-1, 9)))  # Sodium
    t = Table(data, style=table_style)
    t._argW[0] = 5 * cm
    elements.append(t)

    # Footer, date and info
    elements.append(Spacer(10 * cm, 0.5 * cm))
    created = datetime.date.today().strftime("%d.%m.%Y")
    url = reverse('nutrition:plan:view', kwargs={'id': plan.id})
    p = Paragraph('''<para align="left">
                        %(date)s -
                        <a href="%(url)s">%(url)s</a> -
                        %(created)s
                        %(version)s
                    </para>''' %
                  {'date': _("Created on the <b>%s</b>") % created,
                   'created': "wger Workout Manager",
                   'version': get_version(),
                   'url': request.build_absolute_uri(url), },
                  styleSheet["Normal"])
    elements.append(p)
    doc.build(elements)

    response['Content-Disposition'] = 'attachment; filename=nutritional-plan.pdf'
    response['Content-Length'] = len(response.content)
    return response
Пример #13
0
def workout_view(request, id, uidb64=None, token=None):
    '''
    Generates a PDF with the contents of the workout, without table for logs
    '''

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=id, user=request.user)

    # Create the PDF object, using the response object as its "file."
    doc = SimpleDocTemplate(
        response,
        pagesize=A4,
        # pagesize = landscape(A4),
        leftMargin=cm,
        rightMargin=cm,
        topMargin=0.5 * cm,
        bottomMargin=0.5 * cm,
        title=_('Workout'),
        author='wger Workout Manager',
        subject=_('Workout for %s') % request.user.username)

    # container for the 'Flowable' objects
    elements = []

    # table data, here we will put the workout info
    data = []

    # Init several counters and markers, this will be used after the iteration to
    # set different borders and colours
    day_markers = []
    exercise_markers = {}
    group_exercise_marker = {}
    group_day_marker = {}

    # Background colour for days
    # Reportlab doesn't use the HTML hexadecimal format, but has a range of
    # 0 till 1, so we have to convert here.
    header_colour = colors.Color(
        int('73', 16) / 255.0,
        int('8a', 16) / 255.0,
        int('5f', 16) / 255.0)

    #
    # Iterate through the Workout
    #

    # Days
    for day in workout.canonical_representation['day_list']:
        set_count = 1
        day_markers.append(len(data))
        group_day_marker[day['obj'].id] = {
            'start': len(data),
            'end': len(data)
        }

        if not exercise_markers.get(day['obj'].id):
            exercise_markers[day['obj'].id] = []

        p = Paragraph(
            '<para align="center">%(days)s: %(description)s</para>' % {
                'days': day['days_of_week']['text'],
                'description': day['obj'].description
            }, styleSheet["Bold"])

        data.append([p])

        # Sets
        for set in day['set_list']:
            group_exercise_marker[set['obj'].id] = {
                'start': len(data),
                'end': len(data)
            }

            # Exercises
            for exercise in set['exercise_list']:
                group_exercise_marker[set['obj'].id]['end'] = len(data)

                # Note: '+1' here because there's an emtpy cell between days
                exercise_markers[day['obj'].id].append(len(data) + 1)
                data.append([
                    set_count,
                    Paragraph(exercise['obj'].name, styleSheet["Small"]),
                    exercise['setting_text']
                ])
            set_count += 1

        data.append([''])
        group_day_marker[day['obj'].id]['end'] = len(data)

        # Set the widths and heights of rows and columns
        # Note: 'None' is treated as 'automatic'. Either there is only one value for the whole list
        #       or exactly one for every row/column
        colwidths = None
        rowheights = [None] * len(data)

    table_style = [
        ('FONT', (0, 0), (-1, -1), 'OpenSans'),
        ('FONTSIZE', (0, 0), (-1, -1), 8),
        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),

        # Note: a padding of 3 seems to be the default
        ('LEFTPADDING', (0, 0), (-1, -1), 2),
        ('RIGHTPADDING', (0, 0), (-1, -1), 0),
        ('TOPPADDING', (0, 0), (-1, -1), 3),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 2),
    ]

    # Set specific styles, e.g. background for title cells
    for marker in day_markers:
        # Set background colour for headings
        table_style.append(
            ('BACKGROUND', (0, marker), (-1, marker), header_colour))
        table_style.append(
            ('BOX', (0, marker), (-1, marker), 1.25, colors.black))

        # Make the headings span the whole width
        table_style.append(('SPAN', (0, marker), (-1, marker)))

        # Manually set
        rowheights[marker - 1] = 5

    # Combine the cells for exercises on the same set
    counter = 1
    for marker in group_exercise_marker:
        counter += 1
        start_marker = group_exercise_marker[marker]['start']
        end_marker = group_exercise_marker[marker]['end']

        table_style.append(('SPAN', (0, start_marker), (0, end_marker)))
        table_style.append(
            ('BOX', (0, start_marker), (-1, end_marker), 0.25, colors.black))

        if counter % 2:
            table_style.append(('BACKGROUND', (0, start_marker),
                                (-1, end_marker), colors.lavender))

    for marker in group_day_marker:
        start_marker = group_day_marker[marker]['start']
        end_marker = group_day_marker[marker]['end']

        table_style.append(('BOX', (0, start_marker), (-1, end_marker - 2),
                            1.25, colors.black))

    # Set the table data
    if data:
        t = Table(data, colwidths, rowheights, style=table_style)

        # Manually set the width of the columns
        if len(t._argW) > 1:
            t._argW[0] = 0.6 * cm  # Numbering
            t._argW[1] = 9 * cm  # Exercise
            t._argW[2] = 4 * cm  # Repetitions

    # There is nothing to output
    else:
        t = Paragraph(
            _('<i>This is an empty workout, what did you expect on the PDF?</i>'
              ), styleSheet["Normal"])

    #
    # Add all elements to the document
    #

    # Set the title (if available)
    if workout.comment:
        p = Paragraph(
            '<para align="center"><strong>%(description)s</strong></para>' %
            {'description': workout.comment}, styleSheet["Bold"])
        elements.append(p)

        # Filler
        elements.append(Spacer(10 * cm, 0.5 * cm))

    # Append the table
    elements.append(t)

    # Footer, date and info
    elements.append(Spacer(10 * cm, 0.5 * cm))
    created = datetime.date.today().strftime("%d.%m.%Y")
    p = Paragraph(
        '''<para align="left">
                        %(date)s -
                        <a href="%(url)s">%(url)s</a> -
                        %(created)s
                        %(version)s
                    </para>''' % {
            'date': _("Created on the <b>%s</b>") % created,
            'created': "wger Workout Manager",
            'version': get_version(),
            'url': request.build_absolute_uri(workout.get_absolute_url()),
        }, styleSheet["Normal"])
    elements.append(p)

    # write the document and send the response to the browser
    doc.build(elements)

    # Create the HttpResponse object with the appropriate PDF headers.
    response[
        'Content-Disposition'] = 'attachment; filename=Workout-{0}-table.pdf'.format(
            id)
    response['Content-Length'] = len(response.content)
    return response
Пример #14
0
Файл: pdf.py Проект: itsdtr/wger
def workout_log(request, id, uidb64=None, token=None):
    '''
    Generates a PDF with the contents of the given workout

    See also
    * http://www.blog.pythonlibrary.org/2010/09/21/reportlab
    * http://www.reportlab.com/apis/reportlab/dev/platypus.html
    '''

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=id, user=request.user)

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')

    # Create the PDF object, using the response object as its "file."
    doc = SimpleDocTemplate(response,
                            pagesize=A4,
                            # pagesize = landscape(A4),
                            leftMargin=cm,
                            rightMargin=cm,
                            topMargin=0.5 * cm,
                            bottomMargin=0.5 * cm,
                            title=_('Workout'),
                            author='wger Workout Manager',
                            subject=_('Workout for %s') % request.user.username)

    # container for the 'Flowable' objects
    elements = []

    # table data, here we will put the workout info
    data = []

    # Init several counters and markers, this will be used after the iteration to
    # set different borders and colours
    day_markers = []
    exercise_markers = {}
    group_exercise_marker = {}
    group_day_marker = {}

    # Set the number of weeks for this workout
    # (sets number of columns for the weight/date log)
    nr_of_weeks = 7

    # Set the first column of the weight log, depends on design
    first_weight_column = 3

    # Background colour for days
    # Reportlab doesn't use the HTML hexadecimal format, but has a range of
    # 0 till 1, so we have to convert here.
    header_colour = colors.Color(int('73', 16) / 255.0,
                                 int('8a', 16) / 255.0,
                                 int('5f', 16) / 255.0)

    #
    # Iterate through the Workout
    #

    # Days
    for day in workout.canonical_representation['day_list']:
        set_count = 1
        day_markers.append(len(data))
        group_day_marker[day['obj'].id] = {'start': len(data), 'end': len(data)}

        if not exercise_markers.get(day['obj'].id):
            exercise_markers[day['obj'].id] = []

        P = Paragraph('<para align="center">%(days)s: %(description)s</para>' %
                      {'days': day['days_of_week']['text'],
                       'description': day['obj'].description},
                      styleSheet["Bold"])

        data.append([P])

        # Note: the _('Date') will be on the 3rd cell, but since we make a span
        #       over 3 cells, the value has to be on the 1st one
        data.append([_('Date') + ' ', '', ''] + [''] * nr_of_weeks)
        data.append([_('Nr.'), _('Exercise'), _('Reps')] + [_('Weight')] * nr_of_weeks)

        # Sets
        for set in day['set_list']:
            group_exercise_marker[set['obj'].id] = {'start': len(data), 'end': len(data)}

            # Exercises
            for exercise in set['exercise_list']:
                group_exercise_marker[set['obj'].id]['end'] = len(data)

                # Note: '+1' here because there's an emtpy cell between days
                exercise_markers[day['obj'].id].append(len(data) + 1)

                data.append([set_count,
                             Paragraph(exercise['obj'].name, styleSheet["Small"]),
                             exercise['setting_text']]
                            + [''] * nr_of_weeks)
            set_count += 1

        data.append([''])
        group_day_marker[day['obj'].id]['end'] = len(data)

        # Set the widths and heights of rows and columns
        # Note: 'None' is treated as 'automatic'. Either there is only one value for the whole list
        #       or exactly one for every row/column
        colwidths = None
        rowheights = [None] * len(data)

    # Set general table styles
    table_style = [('FONT', (0, 0), (-1, -1), 'OpenSans'),
                   ('FONTSIZE', (0, 0), (-1, -1), 8),
                   ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),

                   # Note: a padding of 3 seems to be the default
                   ('LEFTPADDING', (0, 0), (-1, -1), 2),
                   ('RIGHTPADDING', (0, 0), (-1, -1), 0),
                   ('TOPPADDING', (0, 0), (-1, -1), 3),
                   ('BOTTOMPADDING', (0, 0), (-1, -1), 2), ]

    # Set specific styles, e.g. background for title cells
    for marker in day_markers:
        # Set background colour for headings
        table_style.append(('BACKGROUND', (0, marker), (-1, marker), header_colour))
        table_style.append(('BOX', (0, marker), (-1, marker), 1.25, colors.black))
        table_style.append(('BOX', (0, marker), (-1, marker + 2), 1.25, colors.black))

        # Make the headings span the whole width
        table_style.append(('SPAN', (0, marker), (-1, marker)))

        # Make the space between days span the whole width
        table_style.append(('SPAN', (0, marker - 1), (-1, marker - 1)))

        # Manually set
        rowheights[marker - 1] = 5

        # Make the date span 3 cells and align it to the right
        table_style.append(('ALIGN', (0, marker + 1), (2, marker + 1), 'RIGHT'))
        table_style.append(('SPAN', (0, marker + 1), (2, marker + 1)))

    # Combine the cells for exercises on the same set
    for marker in group_exercise_marker:
        start_marker = group_exercise_marker[marker]['start']
        end_marker = group_exercise_marker[marker]['end']

        table_style.append(('VALIGN', (0, start_marker), (0, end_marker), 'MIDDLE'))
        table_style.append(('SPAN', (0, start_marker), (0, end_marker)))

    # Set an alternating background colour for rows
    for i in exercise_markers:
        counter = 1
        for j in exercise_markers[i]:
            if not j % 2:
                table_style.append(('BACKGROUND', (1, j - 1), (-1, j - 1), colors.lavender))
            counter += 1

    # Make the 'impression' span 3 cells and align it to the right
    for marker in group_day_marker:
        start_marker = group_day_marker[marker]['start']
        end_marker = group_day_marker[marker]['end']

        # There is an empty cell between the day blocks, set a border around them
        table_style.append(('INNERGRID',
                            (0, start_marker),
                            (- 1, end_marker - 2),
                            0.25,
                            colors.black))
        table_style.append(('BOX',
                            (0, start_marker),
                            (-1, end_marker - 2),
                            1.25,
                            colors.black))

    # Set the table data
    if data:
        t = Table(data, colwidths, rowheights, style=table_style)

        # Manually set the width of the columns
        for i in range(first_weight_column, nr_of_weeks + first_weight_column):
            t._argW[i] = 1.8 * cm  # Columns for entering the log

        t._argW[0] = 0.6 * cm  # Exercise numbering
        t._argW[1] = 3.5 * cm  # Name of exercise
        t._argW[2] = 2 * cm  # Repetitions

    # There is nothing to output
    else:
        t = Paragraph(_('<i>This is an empty workout, what did you expect on the PDF?</i>'),
                      styleSheet["Normal"])

    #
    # Add all elements to the document
    #

    # Set the title (if available)
    if workout.comment:
        P = Paragraph('<para align="center"><strong>%(description)s</strong></para>' %
                      {'description': workout.comment},
                      styleSheet["Bold"])
        elements.append(P)

        # Filler
        elements.append(Spacer(10*cm, 0.5*cm))

    # Append the table
    elements.append(t)

    # Footer, date and info
    elements.append(Spacer(10*cm, 0.5*cm))
    created = datetime.date.today().strftime("%d.%m.%Y")
    url = reverse('workout-view', kwargs={'id': workout.id})
    P = Paragraph('''<para align="left">
                        %(date)s -
                        <a href="%(url)s">%(url)s</a> -
                        %(created)s
                        %(version)s
                    </para>''' %
                  {'date': _("Created on the <b>%s</b>") % created,
                   'created': "wger Workout Manager",
                   'version': get_version(),
                   'url': request.build_absolute_uri(url), },
                  styleSheet["Normal"])
    elements.append(P)

    # write the document and send the response to the browser
    doc.build(elements)

    # Create the HttpResponse object with the appropriate PDF headers.
    response['Content-Disposition'] = 'attachment; filename=Workout-{0}-log.pdf'.format(id)
    response['Content-Length'] = len(response.content)
    return response
Пример #15
0
Файл: pdf.py Проект: drkarl/wger
def workout_view(request, id, uidb64=None, token=None):
    '''
    Generates a PDF with the contents of the workout, without table for logs
    '''

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(content_type='application/pdf')

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=id, user=request.user)

    # Create the PDF object, using the response object as its "file."
    doc = SimpleDocTemplate(response,
                            pagesize=A4,
                            # pagesize = landscape(A4),
                            leftMargin=cm,
                            rightMargin=cm,
                            topMargin=0.5 * cm,
                            bottomMargin=0.5 * cm,
                            title=_('Workout'),
                            author='wger Workout Manager',
                            subject=_('Workout for %s') % request.user.username)

    # container for the 'Flowable' objects
    elements = []

    # table data, here we will put the workout info
    data = []

    # Init several counters and markers, this will be used after the iteration to
    # set different borders and colours
    day_markers = []
    exercise_markers = {}
    group_exercise_marker = {}
    group_day_marker = {}

    # Background colour for days
    # Reportlab doesn't use the HTML hexadecimal format, but has a range of
    # 0 till 1, so we have to convert here.
    header_colour = colors.Color(int('73', 16) / 255.0,
                                 int('8a', 16) / 255.0,
                                 int('5f', 16) / 255.0)

    #
    # Iterate through the Workout
    #

    # Days
    for day in workout.canonical_representation['day_list']:
        set_count = 1
        day_markers.append(len(data))
        group_day_marker[day['obj'].id] = {'start': len(data), 'end': len(data)}

        if not exercise_markers.get(day['obj'].id):
            exercise_markers[day['obj'].id] = []

        p = Paragraph('<para align="center">%(days)s: %(description)s</para>' %
                      {'days': day['days_of_week']['text'],
                       'description': day['obj'].description},
                      styleSheet["Bold"])

        data.append([p])

        # Sets
        for set in day['set_list']:
            group_exercise_marker[set['obj'].id] = {'start': len(data), 'end': len(data)}

            # Exercises
            for exercise in set['exercise_list']:
                group_exercise_marker[set['obj'].id]['end'] = len(data)

                # Note: '+1' here because there's an emtpy cell between days
                exercise_markers[day['obj'].id].append(len(data) + 1)

                # Process the settings
                if exercise['has_weight']:
                    setting_out = []
                    for i in exercise['setting_text'].split(u'–'):
                        setting_out.append(Paragraph(i, styleSheet["Small"], bulletText=''))
                else:
                    setting_out = Paragraph(exercise['setting_text'], styleSheet["Small"])

                data.append([set_count,
                             Paragraph(exercise['obj'].name, styleSheet["Small"]),
                             setting_out])
            set_count += 1

        data.append([''])
        group_day_marker[day['obj'].id]['end'] = len(data)

        # Set the widths and heights of rows and columns
        # Note: 'None' is treated as 'automatic'. Either there is only one value for the whole list
        #       or exactly one for every row/column
        colwidths = None
        rowheights = [None] * len(data)

    table_style = [('FONT', (0, 0), (-1, -1), 'OpenSans'),
                   ('FONTSIZE', (0, 0), (-1, -1), 8),
                   ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),

                   # Note: a padding of 3 seems to be the default
                   ('LEFTPADDING', (0, 0), (-1, -1), 2),
                   ('RIGHTPADDING', (0, 0), (-1, -1), 2),
                   ('TOPPADDING', (0, 0), (-1, -1), 3),
                   ('BOTTOMPADDING', (0, 0), (-1, -1), 2), ]

    # Set specific styles, e.g. background for title cells
    for marker in day_markers:
        # Set background colour for headings
        table_style.append(('BACKGROUND', (0, marker), (-1, marker), header_colour))
        table_style.append(('BOX', (0, marker), (-1, marker), 1.25, colors.black))

        # Make the headings span the whole width
        table_style.append(('SPAN', (0, marker), (-1, marker)))

        # Manually set
        rowheights[marker - 1] = 5

    # Combine the cells for exercises on the same set
    counter = 1
    for marker in group_exercise_marker:
        counter += 1
        start_marker = group_exercise_marker[marker]['start']
        end_marker = group_exercise_marker[marker]['end']

        table_style.append(('SPAN', (0, start_marker), (0, end_marker)))
        table_style.append(('BOX',
                            (0, start_marker),
                            (-1, end_marker),
                            0.25,
                            colors.black))

        if counter % 2:
            table_style.append(('BACKGROUND',
                                (0, start_marker),
                                (-1, end_marker),
                                colors.lavender))

    for marker in group_day_marker:
        start_marker = group_day_marker[marker]['start']
        end_marker = group_day_marker[marker]['end']

        table_style.append(('BOX',
                            (0, start_marker),
                            (-1, end_marker - 2),
                            1.25,
                            colors.black))

    # Set the table data
    if data:
        t = Table(data, colwidths, rowheights, style=table_style)

        # Manually set the width of the columns
        if len(t._argW) > 1:
            t._argW[0] = 0.6 * cm  # Numbering
            t._argW[1] = 10 * cm  # Exercise
            t._argW[2] = 2.5 * cm  # Repetitions

    # There is nothing to output
    else:
        t = Paragraph(_('<i>This is an empty workout, what did you expect on the PDF?</i>'),
                      styleSheet["Normal"])

    #
    # Add all elements to the document
    #

    # Set the title (if available)
    if workout.comment:
        p = Paragraph('<para align="center"><strong>%(description)s</strong></para>' %
                      {'description': workout.comment},
                      styleSheet["Bold"])
        elements.append(p)

        # Filler
        elements.append(Spacer(10 * cm, 0.5 * cm))

    # Append the table
    elements.append(t)

    # Footer, date and info
    elements.append(Spacer(10 * cm, 0.5 * cm))
    created = datetime.date.today().strftime("%d.%m.%Y")
    p = Paragraph('''<para align="left">
                        %(date)s -
                        <a href="%(url)s">%(url)s</a> -
                        %(created)s
                        %(version)s
                    </para>''' %
                  {'date': _("Created on the <b>%s</b>") % created,
                   'created': "wger Workout Manager",
                   'version': get_version(),
                   'url': request.build_absolute_uri(workout.get_absolute_url()), },
                  styleSheet["Normal"])
    elements.append(p)

    # write the document and send the response to the browser
    doc.build(elements)

    # Create the HttpResponse object with the appropriate PDF headers.
    response['Content-Disposition'] = 'attachment; filename=Workout-{0}-table.pdf'.format(id)
    response['Content-Length'] = len(response.content)
    return response
Пример #16
0
def workout_log(request,
                id,
                images=False,
                comments=False,
                uidb64=None,
                token=None):
    '''
    Generates a PDF with the contents of the given workout

    See also
    * http://www.blog.pythonlibrary.org/2010/09/21/reportlab
    * http://www.reportlab.com/apis/reportlab/dev/platypus.html
    '''
    comments = bool(int(comments))
    images = bool(int(images))

    # Load the workout
    if uidb64 is not None and token is not None:
        if check_token(uidb64, token):
            workout = get_object_or_404(Workout, pk=id)
        else:
            return HttpResponseForbidden()
    else:
        if request.user.is_anonymous():
            return HttpResponseForbidden()
        workout = get_object_or_404(Workout, pk=id, user=request.user)

    if len(workout.canonical_representation['day_list']) > 0:

        exercise_set = workout.canonical_representation['day_list'][0][
            'set_list']

        workout_details = {
            'description':
            workout.canonical_representation['day_list'][0]['obj'].description,
            'workout_days':
            workout.canonical_representation['day_list'][0]['days_of_week']
            ['text']
        }

        set_list = []

        for set in exercise_set:
            set_dict = {}
            exercise_list = []
            holder = {}
            set_dict['set_id'] = set['obj'].id

            for item in set['exercise_list']:
                holder['name_of_exercise'] = item['obj'].name
                holder['setting_list'] = item['setting_list']
                holder['comments'] = item['comment_list']
                exercise_list.append(holder)

            set_dict['exercise_list'] = exercise_list

            set_list.append(set_dict)

        workout_details['set_list'] = set_list
    else:
        workout_details = []

    json_data = json.dumps(workout_details)

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(json_data, content_type='application/json')

    # Create the HttpResponse object with the appropriate PDF headers.
    response[
        'Content-Disposition'] = 'attachment; filename=Workout-{0}.json'.format(
            id)
    response['Content-Length'] = len(response.content)
    return response