KeyError dentro modelo de django __init__ classe

votos
1

Aqui está uma classe de modelo Django que escrevi. Esta classe recebe um KeyError quando eu chamo get_object_or_404de Django (eu conceber que KeyError é levantada devido à falta de kwargs sendo passado para __init__pela função get, os argumentos são todos posicional). Curiosamente, ele não recebe um erro quando eu chamo get_object_or_404de console.

Eu me pergunto por que, e se o código abaixo é a maneira correta (ou seja, usando o init para preencher o campo link) para construir esta classe.

class Link(models.Model)

    event_type = models.IntegerField(choices=EVENT_TYPES)
    user = models.ForeignKey(User)
    created_on = models.DateTimeField(auto_now_add = True)
    link = models.CharField(max_length=30)
    isActive = models.BooleanField(default=True)

    def _generate_link(self):
        prelink = str(self.user.id)+str(self.event_type)+str(self.created_on)
        m = md5.new()
        m.update(prelink)
        return m.hexdigest()

    def __init__(self, *args, **kwargs):
        self.user = kwargs['user'].pop()
        self.event_type = kwargs['event_type'].pop()
        self.link = self._generate_link()
        super(Link,self).__init__(*args,**kwargs)
Publicado 15/05/2009 em 00:35
fonte usuário
Em outras línguas...                            


4 respostas

votos
7
self.user = kwargs['user'].pop()
self.event_type = kwargs['event_type'].pop()

Você está tentando recuperar uma entrada do dicionário, e, em seguida, chamar seu método pop. Se você deseja remover e retornar um objeto de um dicionário, ligue para dict.pop():

self.user = kwargs.pop('user')

Claro, isso irá falhar com um KeyErrorquando "user"não está presente no kwargs. Você vai querer fornecer um valor padrão a pop:

self.user = kwargs.pop('user', None)

Isto significa que "se "user"está no dicionário, remover e devolvê-lo. Caso contrário, o retorno None".

Em relação às outras duas linhas:

self.link = self._generate_link()
super(Link,self).__init__(*args,**kwargs)

super().__init__()irá definir linka alguma coisa, provavelmente None. Eu iria inverter as linhas, para algo como isto:

super(Link,self).__init__(*args,**kwargs)
self.link = self._generate_link()

Você pode querer adicionar um teste antes de definir o link, para ver se ele já existe ( if self.link is not None: ...). Dessa forma, os links que você passar para o construtor não será substituído.

Respondeu 15/05/2009 em 00:58
fonte usuário

votos
2

Eu não acho que você precisa o __init__aqui.

Você está sempre calcular o valor da ligação quando a classe é instanciado. Isto significa que você ignorar o que está armazenado no banco de dados. Uma vez que este é o caso, por que se preocupar com um campo de modelo em tudo? Você seria melhor tomada de ligação de um imóvel, com o getter usando o código da _generate_link.

@property
def link(self): 
    ....
Respondeu 15/05/2009 em 07:29
fonte usuário

votos
2

Não há nenhuma razão para escrever seu próprio __init__para classes de modelo Django. Eu acho que você vai ser muito mais feliz sem ele.

Quase qualquer coisa que você acha que você quer fazer em __init__pode ser melhor feito em save.

Respondeu 15/05/2009 em 02:31
fonte usuário

votos
1

pergunto por que, e se o código abaixo é a maneira correta (ou seja, usando __init__para preencher o campo link) para construir esta classe.

Uma vez eu tenho alguns problemas quando eu tentei sobrecarregar __init__ No maillist eu tenho esta resposta

É melhor para não sobrecarregá-lo com seu próprio __init__. A melhor opção é ligar-se o post_initsinal com um método personalizado e nesse método de fazer seus process()e make_thumbnail()chamadas.

No seu caso, o sinal-post_init deve fazer o truque e implementação __init__não deve ser necessário em tudo. Você poderia escrever algo como isto:

class Link(models.Model)
    event_type = models.IntegerField(choices=EVENT_TYPES)
    user = models.ForeignKey(User)
    created_on = models.DateTimeField(auto_now_add = True)
    link = models.CharField(max_length=30)
    isActive = models.BooleanField(default=True)

    def create_link(self):
        prelink = str(self.user.id)+str(self.event_type)+str(self.created_on)
        m = md5.new()
        m.update(prelink)
        return m.hexdigest()

def post_link_init(sender, **kwargs):
    kwargs['instance'].create_link()
post_init.connect(post_link_init, sender=Link)

>>> link = Link(event_type=1, user=aUser, created_on=datetime.now(), link='foo', isActive=True)

fornecendo palavra-chave uniquepara link = models.CharField(max_length=30, unique=True)poderia ser útil também. Se não for fornecido, get_object_or_404 pode não funcionará caso o mesmo valor no link-campo existe várias vezes.

sinais e única nas django-docs

Respondeu 15/05/2009 em 02:35
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more