Пример #1
0
def processor(request):

    language = load_language()
    full_path = request.get_full_path()
    i18n_path = {}
    for lang in settings.LANGUAGES:
        i18n_path[lang[0]] = '/{0}{1}'.format(lang[0], full_path[3:])

    context = {
        # Application version
        'version': get_version(),

        # User language
        'language': language,

        # Available application languages
        'languages': settings.LANGUAGES,

        # The current path
        'request_full_path': full_path,

        # Translation links
        'i18n_path': i18n_path,

        # Translation links
        'datepicker_i18n_path': 'js/bootstrap-datepicker/locales/bootstrap-datepicker.{0}.js'.
        format(language.short_name),

        # Flag for guest users
        'has_demo_data': request.session.get('has_demo_data', False),

        # Don't show messages on AJAX requests (they are deleted if shown)
        'no_messages': request.META.get('HTTP_X_WGER_NO_MESSAGES', False),

        # Default cache time for template fragment caching
        'cache_timeout': settings.CACHES['default']['TIMEOUT']
    }

    # Pseudo-intelligent navigation here
    if '/software/' in request.get_full_path() \
       or '/contact' in request.get_full_path() \
       or '/api/v2' in request.get_full_path():
            context['active_tab'] = constants.SOFTWARE_TAB

    elif '/exercise/' in request.get_full_path():
        context['active_tab'] = constants.EXERCISE_TAB

    elif '/nutrition/' in request.get_full_path():
        context['active_tab'] = constants.NUTRITION_TAB

    elif '/weight/' in request.get_full_path():
        context['active_tab'] = constants.WEIGHT_TAB

    elif '/workout/' in request.get_full_path():
        context['active_tab'] = constants.WORKOUT_TAB

    else:
        context['active_tab'] = constants.USER_TAB

    return context
Пример #2
0
Файл: main.py Проект: qbig/wger
def process_options(argv=None):
    if argv is None:
        argv = sys.argv[1:]

    parser = optparse.OptionParser(
        description="Run wger Workout Manager using django's builtin server")
    parser.add_option("-a", "--address", help="IP Address to listen on.")
    parser.add_option("-p", "--port", type="int", help="Port to listen on.")
    parser.add_option(
        "--syncdb",
        action="store_true",
        help="Update/create database before starting the server.")
    parser.add_option(
        "--reset-admin",
        action="store_true",
        help="Make sure the user 'admin' exists and uses 'admin' as password.")
    parser.add_option("-s",
                      "--settings",
                      help="Path to the wger configuration file.")
    parser.add_option("--no-reload",
                      action="store_true",
                      help="Do not reload the development server.")
    parser.add_option("--migrate-db",
                      action="store_true",
                      help="Runs all database migrations (safe operation).")
    parser.add_option("--version",
                      action="store_true",
                      help="Show version and exit.")
    parser.add_option("--show-config",
                      action="store_true",
                      help="Show configuration paths and exit.")

    opts, args = parser.parse_args(argv)
    if opts.version:
        print get_version()
        exit(0)
    if opts.show_config:
        print "Settings file: %s" % get_user_config_path('wger', 'settings.py')
        print "Database file: %s" % get_user_data_path('wger',
                                                       'database.sqlite')
        exit(0)
    if args:
        sys.stderr.write("This command does not take arguments!\n\n")
        parser.print_help()
        sys.exit(1)

    return opts
Пример #3
0
def get_calendar():
    """
    Creates and returns a calendar object

    :return: Calendar
    """
    calendar = Calendar()
    calendar.add("prodid", "-//wger Workout Manager//wger.de//")
    calendar.add("version", get_version())
    return calendar
Пример #4
0
def get_calendar():
    '''
    Creates and returns a calendar object

    :return: Calendar
    '''
    calendar = Calendar()
    calendar.add('prodid', '-//wger Workout Manager//wger.de//')
    calendar.add('version', get_version())
    return calendar
Пример #5
0
def get_calendar():
    '''
    Creates and returns a calendar object

    :return: Calendar
    '''
    calendar = Calendar()
    calendar.add('prodid', '-//wger Workout Manager//wger.de//')
    calendar.add('version', get_version())
    return calendar
Пример #6
0
def process_options(argv=None):
    if argv is None:
        argv = sys.argv[1:]

    parser = optparse.OptionParser(
        description="Run wger Workout Manager using django's builtin server")
    parser.add_option("-a", "--address", help="IP Address to listen on.")
    parser.add_option("-p", "--port", type="int", help="Port to listen on.")
    parser.add_option(
        "--syncdb", action="store_true",
        help="Update/create database before starting the server.")
    parser.add_option(
        "--reset-admin", action="store_true",
        help="Make sure the user 'admin' exists and uses 'admin' as password.")
    parser.add_option(
        "-s", "--settings", help="Path to the wger configuration file.")
    parser.add_option(
        "--no-reload", action="store_true",
        help="Do not reload the development server.")
    parser.add_option(
        "--migrate-db", action="store_true",
        help="Runs all database migrations (safe operation).")
    parser.add_option(
        "--version", action="store_true",
        help="Show version and exit.")
    parser.add_option(
        "--show-config", action="store_true",
        help="Show configuration paths and exit.")

    opts, args = parser.parse_args(argv)
    if opts.version:
        print get_version()
        exit(0)
    if opts.show_config:
        print "Settings file: %s" % get_user_config_path('wger', 'settings.py')
        print "Database file: %s" % get_user_data_path('wger', 'database.sqlite')
        exit(0)
    if args:
        sys.stderr.write("This command does not take arguments!\n\n")
        parser.print_help()
        sys.exit(1)

    return opts
Пример #7
0
def processor(request):

    full_path = request.get_full_path()

    context = {
        # Application version
        'version': get_version(),

        # User language
        'language': load_language(),

        # The current path
        'request_full_path': full_path,

        # Translation links
        'i18n_path': {
            'de': '/de' + full_path[3:],
            'en': '/en' + full_path[3:]
        },

        # Contact email
        'contact_email': 'roland @ geider.net',

        # Flag for guest users
        'has_demo_data': request.session.get('has_demo_data', False),

        # Don't show messages on AJAX requests (they are deleted if shown)
        'no_messages': request.META.get('HTTP_X_WGER_NO_MESSAGES', False),
    }

    # Pseudo-intelligent navigation here
    if '/software/' in request.get_full_path() \
       or '/contact' in request.get_full_path():
        context['active_tab'] = constants.SOFTWARE_TAB

    elif '/exercise/' in request.get_full_path():
        context['active_tab'] = constants.EXERCISE_TAB

    elif '/nutrition/' in request.get_full_path():
        context['active_tab'] = constants.NUTRITION_TAB

    elif '/weight/' in request.get_full_path():
        context['active_tab'] = constants.WEIGHT_TAB

    elif '/workout/' in request.get_full_path():
        context['active_tab'] = constants.WORKOUT_TAB

    else:
        context['active_tab'] = constants.USER_TAB

    return context
Пример #8
0
def processor(request):

    full_path = request.get_full_path()

    context = {
        # Application version
        'version': get_version(),

        # User language
        'language': load_language(),

        # The current path
        'request_full_path': full_path,

        # Translation links
        'i18n_path': {'de': '/de' + full_path[3:],
                      'en': '/en' + full_path[3:]},

        # Contact email
        'contact_email': 'roland @ geider.net',

        # Flag for guest users
        'has_demo_data': request.session.get('has_demo_data', False),

        # Don't show messages on AJAX requests (they are deleted if shown)
        'no_messages': request.META.get('HTTP_X_WGER_NO_MESSAGES', False),
    }

    # Pseudo-intelligent navigation here
    if '/software/' in request.get_full_path() \
       or '/contact' in request.get_full_path():
            context['active_tab'] = constants.SOFTWARE_TAB

    elif '/exercise/' in request.get_full_path():
        context['active_tab'] = constants.EXERCISE_TAB

    elif '/nutrition/' in request.get_full_path():
        context['active_tab'] = constants.NUTRITION_TAB

    elif '/weight/' in request.get_full_path():
        context['active_tab'] = constants.WEIGHT_TAB

    elif '/workout/' in request.get_full_path():
        context['active_tab'] = constants.WORKOUT_TAB

    else:
        context['active_tab'] = constants.USER_TAB

    return context
Пример #9
0
def render_footer(url, date=None):
    '''
    Renders the footer used in the different PDFs
    :return: a Paragraph object
    '''
    if not date:
        date = datetime.date.today().strftime("%d.%m.%Y")
        p = Paragraph('''<para>
                            {date} -
                            <a href="{url}">{url}</a> -
                            wger Workout Manager
                            {version}
                        </para>'''.format(date=date,
                                          url=url,
                                          version=get_version()),
                      styleSheet["Normal"])
    return p
Пример #10
0
def render_footer(url, date=None):
    '''
    Renders the footer used in the different PDFs
    :return: a Paragraph object
    '''
    if not date:
        date = datetime.date.today().strftime("%d.%m.%Y")
        p = Paragraph('''<para>
                            {date} -
                            <a href="{url}">{url}</a> -
                            wger Workout Manager
                            {version}
                        </para>'''.format(date=date,
                                          url=url,
                                          version=get_version()),
                      styleSheet["Normal"])
    return p
Пример #11
0
def export_pdf(request, id):
    '''
    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 workout
    plan = get_object_or_404(NutritionPlan, pk=id, user=request.user)

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

    # Translators: translation can only have ASCII characters
    response['Content-Disposition'] = 'attachment; filename=%s.pdf' % _('nutritional-plan')

    # 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('<para align="center"><strong>%(meal_nr)s</strong></para>' %
                          {'meal_nr': i},
                          styleSheet["Normal"])
        else:
            P = Paragraph('<para align="center"><strong>%(meal_nr)s - '
                          '%(meal_time)s</strong></para>' %
                          {'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('<para>%s</para>' % 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(["{0}{1}".format(item.amount, unit_name), P])

    # Set general table styles

    #('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
    #('BOX', (0,0), (-1,-1), 0.25, colors.black)
    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 * 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["Normal"])
        elements.append(P)

        # Filler
        P = Paragraph('<para> </para>', styleSheet["Normal"])
        elements.append(P)

    # append the table to the document
    elements.append(t)

    # Footer, add filler paragraph
    P = Paragraph('<para> </para>', styleSheet["Normal"])
    elements.append(P)

    # Print date and info
    created = datetime.date.today().strftime("%d.%m.%Y")
    url = reverse('wger.nutrition.views.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)

    return response
Пример #12
0
    def handle(self, **options):

        if not settings.MEDIA_ROOT:
            raise ImproperlyConfigured(
                'Please set MEDIA_ROOT in your settings file')

        remote_url = options['remote_url']
        try:
            val = URLValidator()
            val(remote_url)
        except ValidationError:
            raise CommandError('Please enter a valid URL')

        headers = {
            'User-agent':
            default_user_agent('wger/{} + requests'.format(get_version()))
        }

        # Get all exercises
        result = requests.get(EXERCISE_API.format(remote_url),
                              headers=headers).json()
        for exercise_json in result['results']:
            exercise_name = exercise_json['name']
            exercise_uuid = exercise_json['uuid']
            exercise_id = exercise_json['id']

            self.stdout.write('')
            self.stdout.write(
                f"*** {exercise_name} (ID: {exercise_id}, UUID: {exercise_uuid})"
            )

            try:
                exercise = Exercise.objects.get(uuid=exercise_uuid)

            except Exercise.DoesNotExist:
                self.stdout.write(
                    '    Remote exercise not found in local DB, skipping...')
                continue

            # Get all images
            images = requests.get(IMAGE_API.format(remote_url, exercise_id),
                                  headers=headers).json()

            if images['count']:

                for image_json in images['results']:
                    image_id = image_json['id']
                    image_uuid = image_json['uuid']
                    result = requests.get(THUMBNAIL_API.format(
                        remote_url, image_id),
                                          headers=headers).json()

                    image_name = os.path.basename(result['original'])
                    self.stdout.write('    Fetching image {0} - {1}'.format(
                        image_id, image_name))

                    try:
                        image = ExerciseImage.objects.get(uuid=image_uuid)
                        self.stdout.write(
                            '    --> Image already present locally, skipping...'
                        )
                        continue
                    except ExerciseImage.DoesNotExist:
                        self.stdout.write(
                            '    --> Image not found in local DB, creating now...'
                        )
                        image = ExerciseImage()
                        image.uuid = image_uuid

                    # Save the downloaded image
                    # http://stackoverflow.com/questions/1308386/programmatically-saving-image-to-
                    retrieved_image = requests.get(remote_url +
                                                   result['original'],
                                                   headers=headers)

                    # Temporary files on windows don't support the delete attribute
                    if os.name == 'nt':
                        img_temp = NamedTemporaryFile()
                    else:
                        img_temp = NamedTemporaryFile(delete=True)
                    img_temp.write(retrieved_image.content)
                    img_temp.flush()

                    image.exercise = exercise.exercise_base
                    image.is_main = image_json['is_main']
                    image.status = image_json['status']
                    image.image.save(
                        os.path.basename(image_name),
                        File(img_temp),
                    )
                    image.save()

            else:
                self.stdout.write(
                    '    No images for this exercise, nothing to do')
Пример #13
0
# -*- coding: utf-8 -*-

# This file is part of wger Workout Manager.
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Workout Manager.  If not, see <http://www.gnu.org/licenses/>.

# wger
from wger import get_version

VERSION = get_version()
default_app_config = 'wger.nutrition.apps.NutritionConfig'
    def handle(self, **options):

        if not settings.MEDIA_ROOT:
            raise ImproperlyConfigured('Please set MEDIA_ROOT in your settings file')

        remote_url = options['remote_url']
        try:
            val = URLValidator()
            val(remote_url)
        except ValidationError:
            raise CommandError('Please enter a valid URL')

        headers = {'User-agent': default_user_agent('wger/{} + requests'.format(get_version()))}

        # Get all images
        page = 1
        all_images_processed = False
        result = requests.get(IMAGE_API.format(remote_url), headers=headers).json()
        self.stdout.write('*** Processing images ***')
        while not all_images_processed:
            self.stdout.write('')
            self.stdout.write(f'*** Page {page}')
            self.stdout.write('')
            page += 1

            if result['next']:
                result = requests.get(result['next'], headers=headers).json()
            else:
                all_images_processed = True

            for image_data in result['results']:
                image_uuid = image_data['uuid']

                self.stdout.write(f'Processing image {image_uuid}')

                try:
                    exercise_base = ExerciseBase.objects.get(id=image_data['exercise'])
                except ExerciseBase.DoesNotExist:
                    self.stdout.write('    Remote exercise base not found in local DB, skipping...')
                    continue

                try:
                    image = ExerciseImage.objects.get(uuid=image_uuid)
                    self.stdout.write('    Image already present locally, skipping...')
                    continue
                except ExerciseImage.DoesNotExist:
                    self.stdout.write('    Image not found in local DB, creating now...')
                    image = ExerciseImage()
                    image.uuid = image_uuid

                # Save the downloaded image
                # http://stackoverflow.com/questions/1308386/programmatically-saving-image-to-
                retrieved_image = requests.get(image_data['image'], headers=headers)

                # Temporary files on windows don't support the delete attribute
                if os.name == 'nt':
                    img_temp = NamedTemporaryFile()
                else:
                    img_temp = NamedTemporaryFile(delete=True)
                img_temp.write(retrieved_image.content)
                img_temp.flush()

                image.exercise = exercise_base
                image.is_main = image_data['is_main']
                image.status = image_data['status']
                image.image.save(
                    os.path.basename(os.path.basename(image_data['image'])),
                    File(img_temp),
                )
                image.save()
                self.stdout.write(self.style.SUCCESS('    successfully saved'))
Пример #15
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
Пример #16
0
def processor(request):

    language = load_language()
    full_path = request.get_full_path()
    i18n_path = {}
    static_path = static('images/logos/logo-social.png')

    for lang in settings.LANGUAGES:
        i18n_path[lang[0]] = '/{0}{1}'.format(lang[0], full_path[3:])

    context = {
        # Application version
        'version': get_version(),

        # Twitter handle for this instance
        'twitter': settings.WGER_SETTINGS['TWITTER'],

        # User language
        'language': language,

        # Available application languages
        'languages': settings.LANGUAGES,

        # The current path
        'request_full_path': full_path,

        # The current full path with host
        'request_absolute_path': request.build_absolute_uri(),
        'image_absolute_path': request.build_absolute_uri(static_path),

        # Translation links
        'i18n_path': i18n_path,

        # Flag for guest users
        'has_demo_data': request.session.get('has_demo_data', False),

        # Don't show messages on AJAX requests (they are deleted if shown)
        'no_messages': request.META.get('HTTP_X_WGER_NO_MESSAGES', False),

        # Default cache time for template fragment caching
        'cache_timeout': settings.CACHES['default']['TIMEOUT'],

        # Used for logged in trainers
        'trainer_identity': request.session.get('trainer.identity'),

        # current gym, if available
        'custom_header': get_custom_header(request),
    }

    # Pseudo-intelligent navigation here
    if '/software/' in request.get_full_path() \
       or '/contact' in request.get_full_path() \
       or '/api/v2' in request.get_full_path():
        context['active_tab'] = constants.SOFTWARE_TAB
        context['show_shariff'] = True

    elif '/exercise/' in request.get_full_path():
        context['active_tab'] = constants.WORKOUT_TAB

    elif '/nutrition/' in request.get_full_path():
        context['active_tab'] = constants.NUTRITION_TAB

    elif '/weight/' in request.get_full_path():
        context['active_tab'] = constants.WEIGHT_TAB

    elif '/workout/' in request.get_full_path():
        context['active_tab'] = constants.WORKOUT_TAB

    return context
Пример #17
0
# -*- coding: utf-8 -*-

# This file is part of wger Workout Manager.
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Workout Manager.  If not, see <http://www.gnu.org/licenses/>.

from wger import get_version

VERSION = get_version()
default_app_config = 'wger.email.apps.Config'
Пример #18
0
    def handle(self, **options):

        remote_url = options['remote_url']
        try:
            val = URLValidator()
            val(remote_url)
        except ValidationError:
            raise CommandError('Please enter a valid URL')

        headers = {
            'User-agent':
            default_user_agent('wger/{} + requests'.format(get_version()))
        }

        #
        # Categories
        #
        self.stdout.write('*** Synchronizing categories...')
        result = requests.get(CATEGORY_API.format(remote_url),
                              headers=headers).json()
        for category_data in result['results']:
            category_id = category_data['id']
            category_name = category_data['name']
            try:
                category = ExerciseCategory.objects.get(pk=category_id)
                category.name = category_name
                category.save()
            except ExerciseCategory.DoesNotExist:
                self.stdout.write(
                    self.style.WARNING(f'Saving new category {category_name}'))
                category = ExerciseCategory(id=category_id, name=category_name)
                category.save()
        self.stdout.write(self.style.SUCCESS('done!\n'))

        #
        # Muscles
        #
        self.stdout.write('*** Synchronizing muscles...')
        result = requests.get(MUSCLE_API.format(remote_url),
                              headers=headers).json()
        for muscle_data in result['results']:
            muscle_id = muscle_data['id']
            muscle_name = muscle_data['name']
            muscle_is_front = muscle_data['is_front']
            muscle_url_main = muscle_data['image_url_main']
            muscle_url_secondary = muscle_data['image_url_secondary']

            try:
                muscle = Muscle.objects.get(pk=muscle_id)
                muscle.name = muscle_name
                muscle_is_front = muscle_is_front
                muscle.save()
            except Muscle.DoesNotExist:
                muscle = Muscle(id=muscle_id,
                                name=muscle_name,
                                is_front=muscle_is_front)
                muscle.save()
                self.stdout.write(
                    self.style.WARNING(
                        f'Saved new muscle {muscle_name}. '
                        f'Save the corresponding images manually'))
                self.stdout.write(self.style.WARNING(muscle_url_main))
                self.stdout.write(self.style.WARNING(muscle_url_secondary))
        self.stdout.write(self.style.SUCCESS('done!\n'))

        #
        # Equipment
        #
        self.stdout.write('*** Synchronizing equipment...')
        result = requests.get(EQUIPMENT_API.format(remote_url),
                              headers=headers).json()
        for equipment_data in result['results']:
            equipment_id = equipment_data['id']
            equipment_name = equipment_data['name']

            try:
                equipment = Equipment.objects.get(pk=equipment_id)
                equipment.name = equipment_name
                equipment.save()
            except Equipment.DoesNotExist:
                self.stdout.write(f'Saved new equipment {equipment_name}')
                equipment = Equipment(id=equipment_id, name=equipment_name)
                equipment.save()

        self.stdout.write(self.style.SUCCESS('done!\n'))

        #
        # Exercises
        #
        self.stdout.write('*** Synchronizing exercises...')
        page = 1
        all_exercise_processed = False
        result = requests.get(EXERCISE_API.format(remote_url),
                              headers=headers).json()

        while not all_exercise_processed:

            for data in result['results']:
                exercise_uuid = data['uuid']
                exercise_name = data['name']
                exercise_description = data['description']
                equipment = [
                    Equipment.objects.get(pk=i['id'])
                    for i in data['equipment']
                ]
                muscles = [
                    Muscle.objects.get(pk=i['id']) for i in data['muscles']
                ]
                muscles_sec = [
                    Muscle.objects.get(pk=i['id'])
                    for i in data['muscles_secondary']
                ]

                try:
                    exercise = Exercise.objects.get(uuid=exercise_uuid)
                    exercise.name = exercise_name
                    exercise.description = exercise_description

                    # Note: this should not happen and is an unnecessary workaround
                    #       https://github.com/wger-project/wger/issues/840
                    if not exercise.exercise_base:
                        warning = f'Exercise {exercise.uuid} has no base, this should not happen!' \
                                  f'Skipping...\n'
                        self.stdout.write(self.style.WARNING(warning))
                        continue
                    exercise.exercise_base.category_id = data['category']['id']
                    exercise.exercise_base.muscles.set(muscles)
                    exercise.exercise_base.muscles_secondary.set(muscles_sec)
                    exercise.exercise_base.equipment.set(equipment)
                    exercise.exercise_base.save()
                    exercise.save()
                except Exercise.DoesNotExist:
                    self.stdout.write(f'Saved new exercise {exercise_name}')
                    exercise = Exercise(
                        uuid=exercise_uuid,
                        name=exercise_name,
                        description=exercise_description,
                        language_id=data['language']['id'],
                        license_id=data['license']['id'],
                        license_author=data['license_author'],
                    )
                    base = ExerciseBase()
                    base.category_id = data['category']['id']
                    base.save()
                    base.muscles.set(muscles)
                    base.muscles_secondary.set(muscles_sec)
                    base.equipment.set(equipment)
                    base.save()
                    exercise.save()

            if result['next']:
                page += 1
                result = requests.get(result['next'], headers=headers).json()
            else:
                all_exercise_processed = True

        self.stdout.write(self.style.SUCCESS('done!\n'))
Пример #19
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
Пример #20
0
from setuptools import (setup, find_packages)
from wger import get_version

with open('README.rst') as readme:
    long_description = readme.read()

with open('requirements.txt') as requirements_production:
    install_requires = requirements_production.readlines()

setup(
    name='wger',
    description=
    'FLOSS workout, fitness and weight manager/tracker written with Django',
    long_description=long_description,
    version=get_version(),
    url='https://wger.de',
    author='Roland Geider',
    author_email='*****@*****.**',
    license='AGPL3+',
    packages=find_packages(exclude=['tests']),
    include_package_data=True,
    classifiers=[
        # http://pypi.python.org/pypi?%3Aaction=list_classifiers
        'Development Status :: 5 - Production/Stable',
        'Environment :: Web Environment',
        'Intended Audience :: Other Audience',
        'Framework :: Django',
        'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
        'Operating System :: OS Independent',
        'Programming Language :: Python :: 2',
Пример #21
0
def processor(request):

    language = load_language()
    full_path = request.get_full_path()
    i18n_path = {}
    static_path = static('images/logos/logo-marketplace-256.png')

    for lang in settings.LANGUAGES:
        i18n_path[lang[0]] = u'/{0}{1}'.format(lang[0], full_path[3:])

    context = {
        # Application version
        'version': get_version(),

        # User language
        'language': language,

        # Available application languages
        'languages': settings.LANGUAGES,

        # The current path
        'request_full_path': full_path,

        # The current full path with host
        'request_absolute_path': request.build_absolute_uri(),
        'image_absolute_path': request.build_absolute_uri(static_path),


        # Translation links
        'i18n_path': i18n_path,

        # Flag for guest users
        'has_demo_data': request.session.get('has_demo_data', False),

        # Don't show messages on AJAX requests (they are deleted if shown)
        'no_messages': request.META.get('HTTP_X_WGER_NO_MESSAGES', False),

        # Default cache time for template fragment caching
        'cache_timeout': settings.CACHES['default']['TIMEOUT'],

        # Used for logged in trainers
        'trainer_identity': request.session.get('trainer.identity'),
    }

    # Pseudo-intelligent navigation here
    if '/software/' in request.get_full_path() \
       or '/contact' in request.get_full_path() \
       or '/api/v2' in request.get_full_path():
            context['active_tab'] = constants.SOFTWARE_TAB
            context['show_shariff'] = True

    elif '/exercise/' in request.get_full_path():
        context['active_tab'] = constants.EXERCISE_TAB

    elif '/nutrition/' in request.get_full_path():
        context['active_tab'] = constants.NUTRITION_TAB

    elif '/weight/' in request.get_full_path():
        context['active_tab'] = constants.WEIGHT_TAB

    elif '/workout/' in request.get_full_path():
        context['active_tab'] = constants.WORKOUT_TAB

    else:
        context['active_tab'] = constants.USER_TAB

    return context
Пример #22
0
Файл: pdf.py Проект: itsdtr/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:
        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")
    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}-table.pdf'.format(id)
    response['Content-Length'] = len(response.content)
    return response
Пример #23
0
# wger
from wger import get_version


with open('README.rst') as readme:
    long_description = readme.read()

with open('requirements.txt') as requirements_production:
    install_requires = requirements_production.readlines()

setup(
    name='wger',
    description='FLOSS workout, fitness and weight manager/tracker written with Django',
    long_description=long_description,
    version=get_version(),
    url='https://github.com/wger-project',
    author='Roland Geider',
    author_email='*****@*****.**',
    license='AGPL3+',
    packages=find_packages(exclude=['tests']),
    include_package_data=True,
    classifiers=[
        # http://pypi.python.org/pypi?%3Aaction=list_classifiers
        'Development Status :: 5 - Production/Stable',
        'Environment :: Web Environment',
        'Intended Audience :: Other Audience',
        'Framework :: Django',
        'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
        'Operating System :: OS Independent',
        'Programming Language :: Python :: 2',
Пример #24
0
def processor(request):

    language = load_language()
    full_path = request.get_full_path()
    i18n_path = {}
    for lang in settings.LANGUAGES:
        i18n_path[lang[0]] = u'/{0}{1}'.format(lang[0], full_path[3:])

    context = {
        # Application version
        'version':
        get_version(),

        # User language
        'language':
        language,

        # Available application languages
        'languages':
        settings.LANGUAGES,

        # The current path
        'request_full_path':
        full_path,

        # Translation links
        'i18n_path':
        i18n_path,

        # Translation links
        'datepicker_i18n_path':
        'js/bootstrap-datepicker/locales/bootstrap-datepicker.{0}.js'.format(
            language.short_name),

        # Flag for guest users
        'has_demo_data':
        request.session.get('has_demo_data', False),

        # Don't show messages on AJAX requests (they are deleted if shown)
        'no_messages':
        request.META.get('HTTP_X_WGER_NO_MESSAGES', False),

        # Default cache time for template fragment caching
        'cache_timeout':
        settings.CACHES['default']['TIMEOUT'],

        # Used for logged in trainers
        'trainer_identity':
        request.session.get('trainer.identity'),
    }

    # Pseudo-intelligent navigation here
    if '/software/' in request.get_full_path() \
       or '/contact' in request.get_full_path() \
       or '/api/v2' in request.get_full_path():
        context['active_tab'] = constants.SOFTWARE_TAB
        context['show_shariff'] = True

    elif '/exercise/' in request.get_full_path():
        context['active_tab'] = constants.EXERCISE_TAB

    elif '/nutrition/' in request.get_full_path():
        context['active_tab'] = constants.NUTRITION_TAB

    elif '/weight/' in request.get_full_path():
        context['active_tab'] = constants.WEIGHT_TAB

    elif '/workout/' in request.get_full_path():
        context['active_tab'] = constants.WORKOUT_TAB

    else:
        context['active_tab'] = constants.USER_TAB

    return context
Пример #25
0
 def get(request):
     return Response(get_version())
Пример #26
0
def workout_log(request, id):
    '''
    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
    workout = get_object_or_404(Workout, pk=id, user=request.user)

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=%s.pdf' % _('Workout')

    # 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.day_set.select_related():
        set_count = 1
        day_markers.append(len(data))
        group_day_marker[day.id] = {'start': len(data), 'end': len(data)}

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

        days_of_week = [_(day_of_week.day_of_week) for day_of_week in day.day.select_related()]

        P = Paragraph('<para align="center">%(days)s: %(description)s</para>' %
                      {'days': ', '.join(days_of_week),
                      'description': day.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_obj in day.set_set.select_related():
            group_exercise_marker[set_obj.id] = {'start': len(data), 'end': len(data)}

            # Exercises
            for exercise in set_obj.exercises.select_related():

                group_exercise_marker[set_obj.id]['end'] = len(data)

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

                # Settings
                for setting in exercise.setting_set.filter(set_id=set_obj.id):
                    if setting.reps == 99:
                        repetitions = '∞'
                    else:
                        repetitions = str(setting.reps)
                    setting_data.append(repetitions)

                # If there are more than 1 settings, don't output the repetitions
                # e.g. "4 x 8 8 10 10" is shown only as "8 8 10 10", after all
                # those 4 sets are not done four times!
                if len(setting_data) == 0:
                    out = ''  # nothing set

                elif len(setting_data) == 1:
                    out = str(set_obj.sets) + ' × ' + setting_data[0]

                elif len(setting_data) > 1:
                    out = ', '.join(setting_data)

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

        # Note: as above with _('Date'), the _('Impression') has to be here on
        #       the 1st cell so it is shown after adding a span
        #data.append([_('Impression'), '', ''])

        set_count += 1
        data.append([''])
        group_day_marker[day.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
    #('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
    #('BOX', (0,0), (-1,-1), 1.25, colors.black),
    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']

        #table_style.append(('ALIGN', (0, end_marker - 2), (2, end_marker - 2), 'RIGHT'))

        # 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] = 1.9 * 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
        P = Paragraph('<para> </para>', styleSheet["Normal"])
        elements.append(P)

    # Append the table
    elements.append(t)

    # Footer, add filler paragraph
    P = Paragraph('<para> </para>', styleSheet["Normal"])
    elements.append(P)

    # Print date and info
    created = datetime.date.today().strftime("%d.%m.%Y")
    url = reverse('wger.manager.views.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)

    return response
Пример #27
0
 def get(request):
     return Response(get_version(MIN_APP_VERSION, True))
Пример #28
0
def workout_log(request, id):
    '''
    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
    workout = get_object_or_404(Workout, pk=id, user=request.user)

    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=%s.pdf' % _(
        'Workout')

    # 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.day_set.select_related():
        set_count = 1
        day_markers.append(len(data))
        group_day_marker[day.id] = {'start': len(data), 'end': len(data)}

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

        days_of_week = [
            _(day_of_week.day_of_week)
            for day_of_week in day.day.select_related()
        ]

        P = Paragraph(
            '<para align="center">%(days)s: %(description)s</para>' % {
                'days': ', '.join(days_of_week),
                'description': day.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_obj in day.set_set.select_related():
            group_exercise_marker[set_obj.id] = {
                'start': len(data),
                'end': len(data)
            }

            # Exercises
            for exercise in set_obj.exercises.select_related():

                group_exercise_marker[set_obj.id]['end'] = len(data)

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

                # Settings
                for setting in exercise.setting_set.filter(set_id=set_obj.id):
                    if setting.reps == 99:
                        repetitions = '∞'
                    else:
                        repetitions = str(setting.reps)
                    setting_data.append(repetitions)

                # If there are more than 1 settings, don't output the repetitions
                # e.g. "4 x 8 8 10 10" is shown only as "8 8 10 10", after all
                # those 4 sets are not done four times!
                if len(setting_data) == 0:
                    out = ''  # nothing set

                elif len(setting_data) == 1:
                    out = str(set_obj.sets) + ' × ' + setting_data[0]

                elif len(setting_data) > 1:
                    out = ', '.join(setting_data)

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

        # Note: as above with _('Date'), the _('Impression') has to be here on
        #       the 1st cell so it is shown after adding a span
        #data.append([_('Impression'), '', ''])

        set_count += 1
        data.append([''])
        group_day_marker[day.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
    #('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
    #('BOX', (0,0), (-1,-1), 1.25, colors.black),
    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']

        #table_style.append(('ALIGN', (0, end_marker - 2), (2, end_marker - 2), 'RIGHT'))

        # 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] = 1.9 * 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
        P = Paragraph('<para> </para>', styleSheet["Normal"])
        elements.append(P)

    # Append the table
    elements.append(t)

    # Footer, add filler paragraph
    P = Paragraph('<para> </para>', styleSheet["Normal"])
    elements.append(P)

    # Print date and info
    created = datetime.date.today().strftime("%d.%m.%Y")
    url = reverse('wger.manager.views.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)

    return response
Пример #29
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
Пример #30
0
urlpatterns = [
    path(
        'terms-of-service',
        TemplateView.as_view(template_name="tos.html"),
        name='tos',
    ),
    path(
        'features',
        views.features,
        name='features',
    ),
    path(
        'code',
        RedirectView.as_view(permanent=True,
                             url='https://github.com/wger-project/wger'),
        name='code',
    ),
    path(
        'about-us',
        TemplateView.as_view(template_name="about_us.html",
                             extra_context={'version': get_version()}),
        name='about-us',
    ),
    path(
        'api',
        TemplateView.as_view(template_name="api.html"),
        name='api',
    ),
]
    def handle(self, **options):

        if not settings.MEDIA_ROOT:
            raise ImproperlyConfigured(
                'Please set MEDIA_ROOT in your settings file')

        remote_url = options['remote_url']
        try:
            val = URLValidator()
            val(remote_url)
        except ValidationError:
            raise CommandError('Please enter a valid URL')

        exercise_api = "{0}/api/v2/exercise/?limit=999"
        image_api = "{0}/api/v2/exerciseimage/?exercise={1}"
        thumbnail_api = "{0}/api/v2/exerciseimage/{1}/thumbnails/"

        headers = {
            'User-agent':
            default_user_agent('wger/{} + requests'.format(get_version()))
        }

        # Get all exercises
        result = requests.get(
            exercise_api.format(remote_url), headers=headers).json()
        for exercise_json in result['results']:
            exercise_name = exercise_json['name'].encode('utf-8')
            exercise_uuid = exercise_json['uuid']
            exercise_id = exercise_json['id']

            self.stdout.write('')
            self.stdout.write(
                u"*** Processing {0} (ID: {1}, UUID: {2})".format(
                    exercise_name, exercise_id, exercise_uuid))

            try:
                exercise = Exercise.objects.get(uuid=exercise_uuid)
            except Exercise.DoesNotExist:
                self.stdout.write(
                    '    Remote exercise not found in local DB, skipping...')
                continue

            # Get all images
            images = requests.get(
                image_api.format(remote_url, exercise_id),
                headers=headers).json()

            if images['count']:

                for image_json in images['results']:
                    image_id = image_json['id']
                    result = requests.get(
                        thumbnail_api.format(remote_url, image_id),
                        headers=headers).json()

                    image_name = os.path.basename(result['original'])
                    self.stdout.write('    Fetching image {0} - {1}'.format(
                        image_id, image_name))

                    try:
                        image = ExerciseImage.objects.get(pk=image_id)
                        self.stdout.write(
                            '    --> Image already present locally, skipping...'
                        )
                        continue
                    except ExerciseImage.DoesNotExist:
                        self.stdout.write(
                            '    --> Image not found in local DB, creating now...'
                        )
                        image = ExerciseImage()
                        image.pk = image_id

                    # Save the downloaded image, see link for details
                    # http://stackoverflow.com/questions/1308386/programmatically-saving-image-to-
                    retrieved_image = requests.get(
                        result['original'], headers=headers)
                    img_temp = NamedTemporaryFile(delete=True)
                    img_temp.write(retrieved_image.content)
                    img_temp.flush()

                    image.exercise = exercise
                    image.is_main = image_json['is_main']
                    image.status = image_json['status']
                    image.image.save(
                        os.path.basename(image_name),
                        File(img_temp),
                    )
                    image.save()

            else:
                self.stdout.write(
                    '    No images for this exercise, nothing to do')
Пример #32
0
    def handle(self, **options):

        if not settings.MEDIA_ROOT:
            raise ImproperlyConfigured('Please set MEDIA_ROOT in your settings file')

        remote_url = options['remote_url']
        try:
            val = URLValidator()
            val(remote_url)
        except ValidationError:
            raise CommandError('Please enter a valid URL')

        exercise_api = "{0}/api/v2/exercise/?limit=999&status=2"
        image_api = "{0}/api/v2/exerciseimage/?exercise={1}"
        thumbnail_api = "{0}/api/v2/exerciseimage/{1}/thumbnails/"

        headers = {'User-agent': default_user_agent('wger/{} + requests'.format(get_version()))}

        # Get all exercises
        result = requests.get(exercise_api.format(remote_url), headers=headers).json()
        for exercise_json in result['results']:
            exercise_name = exercise_json['name'].encode('utf-8')
            exercise_uuid = exercise_json['uuid']
            exercise_id = exercise_json['id']

            self.stdout.write('')
            self.stdout.write(u"*** Processing {0} (ID: {1}, UUID: {2})".format(exercise_name,
                                                                                exercise_id,
                                                                                exercise_uuid))

            try:
                exercise = Exercise.objects.get(uuid=exercise_uuid)

            except Exercise.DoesNotExist:
                self.stdout.write('    Remote exercise not found in local DB, skipping...')

                continue

            # Get all images
            images = requests.get(image_api.format(remote_url, exercise_id), headers=headers).json()

            if images['count']:

                for image_json in images['results']:
                    image_id = image_json['id']
                    result = requests.get(thumbnail_api.format(remote_url, image_id),
                                          headers=headers).json()

                    image_name = os.path.basename(result['original'])
                    self.stdout.write('    Fetching image {0} - {1}'.format(image_id, image_name))

                    try:
                        image = ExerciseImage.objects.get(pk=image_id)
                        self.stdout.write('    --> Image already present locally, skipping...')
                        continue
                    except ExerciseImage.DoesNotExist:
                        self.stdout.write('    --> Image not found in local DB, creating now...')
                        image = ExerciseImage()
                        image.pk = image_id

                    # Save the downloaded image, see link for details
                    # http://stackoverflow.com/questions/1308386/programmatically-saving-image-to-
                    retrieved_image = requests.get(result['original'], headers=headers)
                    img_temp = NamedTemporaryFile(delete=True)
                    img_temp.write(retrieved_image.content)
                    img_temp.flush()

                    image.exercise = exercise
                    image.is_main = image_json['is_main']
                    image.status = image_json['status']
                    image.image.save(
                        os.path.basename(image_name),
                        File(img_temp),
                    )
                    image.save()

            else:
                self.stdout.write('    No images for this exercise, nothing to do')