Estou tentando criar um modelo básico para exibir os valores de campo da instância selecionada, juntamente com seus nomes. Pense nisso como apenas uma saída padrão dos valores dessa instância no formato de tabela, com o nome do campo (verbose_name especificamente se especificado no campo) na primeira coluna e o valor desse campo na segunda coluna.
Por exemplo, digamos que temos a seguinte definição de modelo:
class Client(Model):
name = CharField(max_length=150)
email = EmailField(max_length=100, verbose_name="E-mail")
Eu gostaria que ele fosse produzido no modelo da seguinte forma (assuma uma instância com os valores fornecidos):
Field Name Field Value
---------- -----------
Name Wayne Koorts
E-mail waynes@email.com
O que estou tentando alcançar é ser capaz de passar uma instância do modelo para um modelo e poder iterá-lo dinamicamente no modelo, algo como isto:
<table>
{% for field in fields %}
<tr>
<td>{{ field.name }}</td>
<td>{{ field.value }}</td>
</tr>
{% endfor %}
</table>
Existe uma maneira elegante e "aprovada pelo Django" de fazer isso? Parece uma tarefa muito comum, e precisarei fazê-lo frequentemente para este projeto em particular.
fonte
Você pode usar o serializador de queryset do Django para python .
Basta colocar o seguinte código em sua exibição:
E então no modelo:
Sua grande vantagem é o fato de lidar com campos de relações.
Para o subconjunto de campos, tente:
fonte
verbose_name
o campo seja passado?Finalmente encontrei uma boa solução para isso na lista de discussão do desenvolvedor :
Na visualização, adicione:
no modelo, adicione:
fonte
FooForm
seja umModelForm
, não seria mais fácil fazerFooForm(instance=Foo.objects.get(pk=object_id)))
:?À luz do lançamento do Django 1.8 (e da formalização da API Model _meta , achei que atualizaria isso com uma resposta mais recente.
Assumindo o mesmo modelo:
Django <= 1.7
Django 1.8+ (Modelo formalizado _meta API)
No exemplo abaixo, utilizaremos o método formalizado para recuperar todas as instâncias de campo de um modelo por meio de
Client._meta.get_fields()
:Na verdade, soube que o exposto acima é um pouco exagerado para o que era necessário (eu concordo!). Simples é melhor que complexo. Estou deixando o acima para referência. No entanto, para exibir no modelo, o melhor método seria usar um ModelForm e passar em uma instância. Você pode iterar sobre o formulário (equivalente a iterar sobre cada um dos campos do formulário) e usar o atributo label para recuperar o verbose_name do campo de modelo e usar o método value para recuperar o valor:
Agora, renderizamos os campos no modelo:
fonte
Aqui está outra abordagem usando um método de modelo. Esta versão resolve campos de lista de opções / opções, ignora campos vazios e permite excluir campos específicos.
Em seguida, no seu modelo:
fonte
except User.DoesNotExist:
?_meta.get_fields()
até que eu possa testá-lo.Ok, eu sei que é um pouco tarde, mas desde que me deparei com isso antes de encontrar a resposta correta, o mesmo poderia acontecer com outra pessoa.
Nos documentos do django :
fonte
ordering = ['-id']
naclass Meta:
do seu objeto emmodels.py
. 2. use entãoBlog.objects.filter(name__startswith='Beatles').values()[0]
model
objeto, acessaria o banco de dados novamente apenas para obter os campos. Alguma maneira de contornar isso?Você pode usar o
values()
método de aqueryset
, que retorna um dicionário. Além disso, este método aceita uma lista de campos para subconjunto. Ovalues()
método não funcionaráget()
, portanto, você deve usarfilter()
(consulte a API QuerySet ).Em
view
...Em
detail.html
...Para uma coleção de instâncias retornadas pelo filtro:
Em detail.html ...
fonte
table
, então preciso de cadakey
s em umth
. Como faço isso sem loops? Basta pegar qualquer instância de objeto e iterar porkey
s? Atualmente, estou passando separadamentemodel_to_dict(Model())
peloth
, mas acho que é uma instanciação de objeto desnecessária.get_object
a exibição detalhada (confusa devido à limitação de código embutido nos comentários, e não sinto que isso seja suficiente para sua própria resposta, considerando a saturação desse encadeamento):def get_object(self, **kwargs): obj = super().get_object(**kwargs) obj = obj.__class__.objects.filter(pk=obj.pk).values()[0] return obj
obj.get_absolute_url
a essa lista sem duplicar as linhas?Eu usei https://stackoverflow.com/a/3431104/2022534, mas substitui model_to_dict () do Django por isso para poder lidar com ForeignKey:
Observe que simplifiquei bastante removendo as partes do original que não precisava. Você pode querer colocá-los de volta.
fonte
Você pode ter um formulário fazendo o trabalho para você.
Então no modelo:
fonte
DetailView
) funciona bem para mim. No entanto, você pode usar emfield.label
vez defield.name
.Realmente deve haver uma maneira integrada de fazer isso. Eu escrevi esse utilitário
build_pretty_data_view
que pega um objeto de modelo e uma instância de formulário (um formulário com base no seu modelo) e retorna aSortedDict
.Os benefícios desta solução incluem:
SortedDict
.exclude()
lista de nomes de campos para excluir determinados campos.Meta: exclude()
, mas você ainda desejar retornar os valores, adicione esses campos àappend()
lista opcional .Para usar esta solução, primeiro adicione este arquivo / função em algum lugar e depois importe-o para o seu
views.py
.utils.py
Então agora
views.py
você pode fazer algo assimAgora, no seu
my-template.html
modelo, você pode interagir com os dados dessa forma ...Boa sorte. Espero que isso ajude alguém!
fonte
Abaixo está o meu, inspirado no shacker's
get_all_fields
. Ele obtém o ditado de uma instância do modelo, se encontrar um campo de relação, e atribuir o valor do campo a um dict recursivamente.Esta função é usada principalmente para despejar uma instância de modelo nos dados json:
fonte
Em vez de editar todos os modelos, recomendo escrever uma tag de modelo que retorne todos os campos de qualquer modelo fornecido.
Todo objeto tem uma lista de campos
._meta.fields
.Todo objeto de campo possui um atributo
name
que retornará seu nome e o métodovalue_to_string()
fornecido com seu modeloobject
retornará seu valor.O resto é tão simples como é dito na documentação do Django .
Aqui está o meu exemplo de como esse modelo de tag pode parecer:
fonte
Sim, não é bonito, você terá que fazer seu próprio invólucro. Dê uma olhada no aplicativo interno databrowse , que tem toda a funcionalidade que você realmente precisa.
fonte
Isso pode ser considerado um hack, mas eu fiz isso antes de usar modelform_factory para transformar uma instância de modelo em um formulário.
A classe Form possui muito mais informações internas, que são super fáceis de iterar e servirão ao mesmo objetivo à custa de um pouco mais de sobrecarga. Se o tamanho do seu conjunto for relativamente pequeno, acho que o impacto no desempenho seria insignificante.
A única vantagem, além da conveniência, é que você pode facilmente transformar a tabela em um datagrid editável posteriormente.
fonte
Eu vim com o método a seguir, que funciona para mim, porque em todos os casos o modelo terá um ModelForm associado a ele.
Aqui está um extrato do modelo que estou usando para esta exibição específica:
O bom desse método é que eu posso escolher, modelo por modelo, a ordem em que gostaria de exibir os rótulos dos campos, usando a tupla passada para GetModelData e especificando os nomes dos campos. Isso também permite excluir determinados campos (por exemplo, uma chave estrangeira do usuário), pois apenas os nomes dos campos passados pela tupla são incorporados ao dicionário final.
Não vou aceitar isso como resposta, porque tenho certeza que alguém pode inventar algo mais "Djangonic" :-)
Atualização: estou escolhendo esta como a resposta final, porque é a mais simples dentre as que fornece o que eu preciso. Obrigado a todos que contribuíram com respostas.
fonte
Solução Django 1.7 para mim:
Existem variáveis exatas para a pergunta, mas você definitivamente deve poder dissecar este exemplo
A chave aqui é usar praticamente
.__dict__
o modeloviews.py :
modelo :
no modelo, usei um filtro para acessar o campo no dict
Filters.py :
fonte
Estou usando isso, https://github.com/miracle2k/django-tables .
fonte
Essa abordagem mostra como usar uma classe como o ModelForm do django e uma tag de modelo como {{form.as_table}}, mas toda a tabela se parece com saída de dados, não com um formulário.
O primeiro passo foi subclassificar o widget TextInput do django:
Subclassifiquei o ModelForm do django para trocar os widgets padrão por versões somente leitura:
Esses eram os únicos widgets que eu precisava. Mas não deve ser difícil estender essa idéia para outros widgets.
fonte
Apenas uma edição de @wonder
Deixe o Django manipular todos os outros campos que não sejam os relacionados. Eu sinto que é mais estável
fonte
Dê uma olhada no aplicativo django-etc . Possui uma
model_field_verbose_name
tag de modelo para obter o nome detalhado do campo a partir dos modelos: http://django-etc.rtfd.org/en/latest/models.html#model-field-template-tagsfonte
Acabei de testar algo assim no shell e parece fazer o trabalho:
Observe que se você deseja representação str () para objetos estranhos, deve defini-la no método str . A partir disso, você tem um ditado de valores para o objeto. Então você pode renderizar algum tipo de modelo ou o que for.
fonte
Django> = 2.0
Adicione
get_fields()
ao seumodels.py
:Em seguida, chame-o como
object.get_fields
no seutemplate.html
:fonte
fonte