Ich habe eine Seite mit vielen Objekten mit unterschiedlichen Inhaltstypen. Ich muss in der Lage sein, diese Objekte zu bewerten. Hier ist eine Klasse dafür:
class Score(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
for_object = generic.GenericForeignKey('content_type', 'object_id')
like = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
comment = models.CharField(max_length=255, blank=True, null=True)
objects = ChainerManager(ScoreQuerySet)
def __unicode__(self):
return u'Score for (%s, #%s) from user %s at %s' %\
(self.content_type, self.object_id, self.user.get_full_name(), self.created_at)
class Meta:
unique_together = (('user', 'content_type', 'object_id'),)
Und meine Vorlage sollte so aussehen:
...
{% for random_object in random_object_queryset %}
<a href={% url like_object random_object.<content_type> random_object.id %}>{{ random_object.name }}</a>
<a href={% url dislike_object random_object.<content_type> random_object.id %}>{{ random_object.name }}</a>
{% endfor %}
...
Mit diesem Snippet kann ich ein Vorlagen-Tag erstellen, um es abzurufen, oder einen Klassennamen abrufen: http://djangosnippets.org / snippets / 294 / Ich kann diese Snuppet umschreiben, um die content_type_id für das Objekt zu erhalten, aber ich habe ein wenig Angst vor einer großen Anzahl von CT-Lookups in DB.
Aber gibt es eine eingebettete Methode, um die CT des Objekts in einer Vorlage abzurufen?
Der Ansichtscode:
def rate_object(request, classname, object_id, like=True):
user = request.user
Klass = ContentType.objects.get(model=classname).model_class()
obj = get_object_or_404(Klass, user=user, pk=object_id)
try:
score = Score.objects.for_object(user, obj)
score.like = like
score.save()
except Score.DoesNotExist:
score = Score.objects.like(user, obj) if like else Score.objects.dislike(user, obj)
return HttpResponse(obj)
3 Antworten
Um auf der Antwort von @Colleen aufzubauen, habe ich einen Vorlagenfilter wie folgt verwendet:
from django import template
from django.contrib.contenttypes.models import ContentType
register = template.Library()
@register.filter
def content_type(obj):
if not obj:
return False
return ContentType.objects.get_for_model(obj)
Und verwendet es in einer Vorlage wie folgt:
{% load helpers %}
{% with instance|content_type as ctype %}
<input type="hidden" name="content_type" value="{{ ctype.pk }}">
{% endwith %}
Ich hatte auch eine Situation, in der ich den Inhaltstyp in der Vorlage benötigte und die einzige Möglichkeit, ihn zu erhalten, war ein benutzerdefiniertes Vorlagen-Tag.
In Ihrer Situation würde ich mir jedoch keine Sorgen machen, da Sie content_type explizit als Fremdschlüssel speichern. Im schlimmsten Fall können Sie prefetch_related()
verwenden, wenn Sie Ihre Score-Objekte in der Ansicht erhalten. Ich weiß nicht, ob Django klug genug ist, um auf dem Feld anzuhalten, wenn Sie nach einem Foreignkey fragen.
Ich bevorzuge dies mit Zuweisungs-Tags ( neu in Django 1.4):
@register.assignment_tag
def content_type(obj):
if not obj:
return False
return ContentType.objects.get_for_model(obj)
Und verwendet als
{% content_type object as object_ct %}
Verwandte Fragen
Neue Fragen
python
Python ist eine dynamisch typisierte Mehrzweck-Programmiersprache mit mehreren Paradigmen. Es wurde entwickelt, um schnell zu lernen, zu verstehen, zu verwenden und eine saubere und einheitliche Syntax durchzusetzen. Bitte beachten Sie, dass Python 2 ab dem 01.01.2020 offiziell nicht mehr unterstützt wird. Fügen Sie für versionenspezifische Python-Fragen das Tag [python-2.7] oder [python-3.x] hinzu. Wenn Sie eine Python-Variante (z. B. Jython, PyPy) oder eine Bibliothek (z. B. Pandas und NumPy) verwenden, fügen Sie diese bitte in die Tags ein.