MySQL & ldquo; неверное строковое значение & rdquo; ошибка при сохранении строки Unicode в Django

Есть некоторые вещи о том, что код автоассинга меня испугает (в основном стилистическая, но еще одна серьезная проблема):

  1. autoassign не присваивает атрибут «args»:
    class Foo(object):
        @autoassign
        def __init__(self,a,b,c=False,*args):
            pass
    a=Foo('IBM','/tmp',True, 100, 101)
    print(a.args)
    # AttributeError: 'Foo' object has no attribute 'args'
    
  2. autoassign действует как декоратор. Но autoassign(*argnames) вызывает функцию, которая возвращает декоратор. Чтобы достичь этой магии, autoassign должен проверить тип своего первого аргумента. Если у вас есть выбор, я предпочитаю, чтобы функции не проверяли тип своих аргументов.
  3. Кажется, что существует значительный объем кода, посвященного настройке sieve, lambdas внутри lambdas, ifilters и множеству условий ,
    if kwargs:
        exclude, f = set(kwargs['exclude']), None
        sieve = lambda l:itertools.ifilter(lambda nv: nv[0] not in exclude, l)
    elif len(names) == 1 and inspect.isfunction(names[0]):
        f = names[0]
        sieve = lambda l:l
    else:
        names, f = set(names), None
        sieve = lambda l: itertools.ifilter(lambda nv: nv[0] in names, l)
    
    Я думаю, что может быть более простой способ. (См. Ниже).
  4. for _ in itertools.starmap(assigned.setdefault, defaults): pass. Я не думаю, что map или starmap предназначались для вызова функций, единственной целью которых являются их побочные эффекты. Это могло быть написано более четко с помощью мирского:
    for key,value in defaults.iteritems():
        assigned.setdefault(key,value)
    

Вот альтернативная более простая реализация, которая имеет ту же функциональность, что и autoassign (например, может включать и исключает), и какие адреса выше:

import inspect
import functools

def autoargs(*include, **kwargs):
    def _autoargs(func):
        attrs, varargs, varkw, defaults = inspect.getargspec(func)

        def sieve(attr):
            if kwargs and attr in kwargs['exclude']:
                return False
            if not include or attr in include:
                return True
            else:
                return False

        @functools.wraps(func)
        def wrapper(self, *args, **kwargs):
            # handle default values
            if defaults:
                for attr, val in zip(reversed(attrs), reversed(defaults)):
                    if sieve(attr):
                        setattr(self, attr, val)
            # handle positional arguments
            positional_attrs = attrs[1:]
            for attr, val in zip(positional_attrs, args):
                if sieve(attr):
                    setattr(self, attr, val)
            # handle varargs
            if varargs:
                remaining_args = args[len(positional_attrs):]
                if sieve(varargs):
                    setattr(self, varargs, remaining_args)
            # handle varkw
            if kwargs:
                for attr, val in kwargs.items():
                    if sieve(attr):
                        setattr(self, attr, val)
            return func(self, *args, **kwargs)
        return wrapper
    return _autoargs

И вот блок-тест, который я использовал для проверки его поведения:

import sys
import unittest
import utils_method as um

class Test(unittest.TestCase):
    def test_autoargs(self):
        class A(object):
            @um.autoargs()
            def __init__(self,foo,path,debug=False):
                pass
        a=A('rhubarb','pie',debug=True)
        self.assertTrue(a.foo=='rhubarb')
        self.assertTrue(a.path=='pie')
        self.assertTrue(a.debug==True)

        class B(object):
            @um.autoargs()
            def __init__(self,foo,path,debug=False,*args):
                pass
        a=B('rhubarb','pie',True, 100, 101)
        self.assertTrue(a.foo=='rhubarb')
        self.assertTrue(a.path=='pie')
        self.assertTrue(a.debug==True)
        self.assertTrue(a.args==(100,101))        

        class C(object):
            @um.autoargs()
            def __init__(self,foo,path,debug=False,*args,**kw):
                pass
        a=C('rhubarb','pie',True, 100, 101,verbose=True)
        self.assertTrue(a.foo=='rhubarb')
        self.assertTrue(a.path=='pie')
        self.assertTrue(a.debug==True)
        self.assertTrue(a.verbose==True)        
        self.assertTrue(a.args==(100,101))        

    def test_autoargs_names(self):
        class C(object):
            @um.autoargs('bar','baz','verbose')
            def __init__(self,foo,bar,baz,verbose=False):
                pass
        a=C('rhubarb','pie',1)
        self.assertTrue(a.bar=='pie')
        self.assertTrue(a.baz==1)
        self.assertTrue(a.verbose==False)
        self.assertRaises(AttributeError,getattr,a,'foo')

    def test_autoargs_exclude(self):
        class C(object):
            @um.autoargs(exclude=('bar','baz','verbose'))
            def __init__(self,foo,bar,baz,verbose=False):
                pass
        a=C('rhubarb','pie',1)
        self.assertTrue(a.foo=='rhubarb')
        self.assertRaises(AttributeError,getattr,a,'bar')

    def test_defaults_none(self):
        class A(object):
            @um.autoargs()
            def __init__(self,foo,path,debug):
                pass
        a=A('rhubarb','pie',debug=True)
        self.assertTrue(a.foo=='rhubarb')
        self.assertTrue(a.path=='pie')
        self.assertTrue(a.debug==True)


if __name__ == '__main__':
    unittest.main(argv = sys.argv + ['--verbose'])

PS. Использование autoassign или autoargs совместимо с завершением кода IPython.

146
задан Alan Moore 26 January 2010 в 03:08
поделиться

2 ответа

Я просто понял один метод, чтобы избежать выше ошибок.

Сохранить в базу данных

user.first_name = u'Rytis'.encode('unicode_escape')
user.last_name = u'Slatkevičius'.encode('unicode_escape')
user.save()
>>> SUCCEED

print user.last_name
>>> Slatkevi\u010dius
print user.last_name.decode('unicode_escape')
>>> Slatkevičius

Это единственный метод для экономии строк, таких как это в таблицу MySQL, и декодирует его перед рендером шаблонов для отображения?

9
ответ дан 23 November 2019 в 22:19
поделиться

Вы не пытаетесь сохранить строки Unicode, вы пытаетесь сохранить ByteStrings в кодировке UTF-8. Сделайте их актуальными строковыми литералами Unicode:

user.last_name = u'Slatkevičius'

или (когда у вас нет строковых литералов), декодируют их с помощью кодирования UTF-8:

user.last_name = lastname.decode('utf-8')
1
ответ дан 23 November 2019 в 22:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: