208 Stimmen

Iterieren Sie über die Feldnamen und Werte der Modellinstanz in der Vorlage

Ich versuche, eine einfache Vorlage zu erstellen, um die Feldwerte der ausgewählten Instanz zusammen mit ihren Namen anzuzeigen. Stellen Sie sich das als eine Standardausgabe der Werte dieser Instanz im Tabellenformat vor, mit dem Feldnamen (verbose_name, falls für das Feld angegeben) in der ersten Spalte und dem Wert dieses Feldes in der zweiten Spalte.

Nehmen wir zum Beispiel an, wir haben die folgende Modelldefinition:

class Client(Model):
    name = CharField(max_length=150)
    email = EmailField(max_length=100, verbose_name="E-mail")

Ich möchte, dass es in der Vorlage wie folgt ausgegeben wird (nehmen Sie eine Instanz mit den angegebenen Werten an):

Field Name      Field Value
----------      -----------
Name            Wayne Koorts
E-mail          waynes@email.com

Was ich zu erreichen versuche, ist in der Lage, eine Instanz des Modells an eine Vorlage zu übergeben und in der Lage sein, über es dynamisch in der Vorlage, etwas wie dieses zu wiederholen:

<table>
    {% for field in fields %}
        <tr>
            <td>{{ field.name }}</td>
            <td>{{ field.value }}</td>
        </tr>
    {% endfor %}
</table>

Gibt es eine saubere, "Django-genehmigte" Weise, dies zu tun? Es scheint wie eine sehr häufige Aufgabe, und ich muss es oft für dieses bestimmte Projekt zu tun.

15voto

olofom Punkte 5923

Ok, ich weiß, dass dies ein bisschen spät ist, aber da ich darauf gestoßen bin, bevor ich die richtige Antwort gefunden habe, könnte das auch jemand anderes tun.

Von der django-Dokumente :

# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
[<Blog: Beatles Blog>]

# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]

11voto

user3062149 Punkte 3705

Sie können die values() Methode eines queryset die ein Wörterbuch zurückgibt. Außerdem akzeptiert diese Methode eine Liste von Feldern, die unterteilt werden sollen. Die values() Methode wird nicht funktionieren mit get() verwenden, also müssen Sie filter() (siehe dazu die QuerySet API ).

Unter view ...

def show(request, object_id):
   object = Foo.objects.filter(id=object_id).values()[0]
   return render_to_response('detail.html', {'object': object})

Unter detail.html ...

<ul>
   {% for key, value in object.items %}
        <li><b>{{ key }}:</b> {{ value }}</li>
   {% endfor %}
</ul>

Für eine Instanzensammlung vom Filter zurückgegeben:

   object = Foo.objects.filter(id=object_id).values() # no [0]

Unter detail.html ...

{% for instance in object %}
<h1>{{ instance.id }}</h1>
<ul>
    {% for key, value in instance.items %}
        <li><b>{{ key }}:</b>  {{ value }}</li>
    {% endfor %}
</ul>
{% endfor %}

9voto

Magnus Gustavsson Punkte 561

Ich habe https://stackoverflow.com/a/3431104/2022534 aber ersetzt Django's model_to_dict() mit diesem, um ForeignKey behandeln zu können:

def model_to_dict(instance):
    data = {}
    for field in instance._meta.fields:
        data[field.name] = field.value_from_object(instance)
        if isinstance(field, ForeignKey):
            data[field.name] = field.rel.to.objects.get(pk=data[field.name])
    return data

Bitte beachten Sie, dass ich es ziemlich vereinfacht habe, indem ich die Teile des Originals, die ich nicht brauchte, entfernt habe. Vielleicht möchten Sie diese wieder einfügen.

9voto

j-a Punkte 1740

Sie können die Arbeit von einem Formular erledigen lassen.

def my_model_view(request, mymodel_id):
    class MyModelForm(forms.ModelForm):
        class Meta:
            model = MyModel

    model = get_object_or_404(MyModel, pk=mymodel_id)
    form = MyModelForm(instance=model)
    return render(request, 'model.html', { 'form': form})

Dann in der Vorlage:

<table>
    {% for field in form %}
        <tr>
            <td>{{ field.name }}</td>
            <td>{{ field.value }}</td>
        </tr>
    {% endfor %}
</table>

8voto

wonder Punkte 481

Nachfolgend ist meine, inspiriert von Frittenbude get_all_fields . Es erhält ein Diktat einer Modellinstanz, wenn es auf ein Beziehungsfeld trifft, und weist dann dem Feldwert rekursiv ein Diktat zu.

def to_dict(obj, exclude=[]):
    """ dict,  model instance .
    """
    tree = {}
    for field in obj._meta.fields + obj._meta.many_to_many:
        if field.name in exclude or \
           '%s.%s' % (type(obj).__name__, field.name) in exclude:
            continue

        try :
            value = getattr(obj, field.name)
        except obj.DoesNotExist:
            value = None

        if type(field) in [ForeignKey, OneToOneField]:
            tree[field.name] = to_dict(value, exclude=exclude)
        elif isinstance(field, ManyToManyField):
            vs = []
            for v in value.all():
                vs.append(to_dict(v, exclude=exclude))
            tree[field.name] = vs
        elif isinstance(field, DateTimeField):
            tree[field.name] = str(value)
        elif isinstance(field, FileField):
            tree[field.name] = {'url': value.url}
        else:
            tree[field.name] = value

    return tree

Diese Funktion wird hauptsächlich verwendet, um eine Modellinstanz in Json-Daten zu dumpen:

def to_json(self):
    tree = to_dict(self, exclude=('id', 'User.password'))
    return json.dumps(tree, ensure_ascii=False)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X