I have a ListView for a blog with fields of "title" and "text".
How to change "text" for example I want to summarize it something like text[:100]
I don't want to change the database. I think the solution is modifying get_queryset but don't know how to implement it.
You don't need to modify objects on the ListView. You can easily use #property method on the model to get such results.
#property
def text_summary(self):
return self.title[:100]
Then you can access this method like a normal field of a model anywhere e.g. on template {{ blog.text_summary }}
Related
I've tried to create a simple ModelForm, and I notice that even if I pass an instance for update like that
mymodel = MyModel.objects.get(pk=1)
MyModelForm(instance=mymodel)
django does not create an hidden field or include in some way the pk of the object in the template. So I need to pass this by myself?
I prefer not passing the my id's like 1,2,3.. to the templates, so I would prefer passing something like uuid, or using signing.dumps(object_id), and then signing.loads(object_id), from django signing library.
So if I want to include this id in my template with the form POST data,
I didn't understand who is exactly responsible for the retrieve of that id - Is that the view or the form itself?
By view I mean to the built-ins FormView, or UpdateView, how these views find the object id? Assume to store the output of signing.dumps(object_id) in a hidden field
By the time you are in the template the form construction has completed. You can try accessing form.instance.id if its modelForm.
However, most likely you do not need the pk in the template, do you ? You can also inject a hidden form field with the instance pk value if you like. Why do you need the pk in the template ?
If you want to redirect to another page from the POST data you will have access to the object pk in the view itself.
According to official documentation the Built-in Views inherit from django.views.generic.detail.SingleObjectTemplateResponseMixin class which requires the views it is mixed with to provide a self.object attribute.
We have a Django DetailView where we're displaying an an object (Site), along with all of it's related objects (Rooms).
Now, in the template, we could simply iterate over the RelatedManager set:
{% for room in site.room_set.all %}
do stuff
{% endfor %}
However, the problem for this is that this will pick up all related rooms to a site - however, we need to narrow this set down somewhat by another attribute (let's call it year) - and this attribute is stored in a Django session variable.
Currently, we're just using Room.objects.filter(site=some_site, year='2009') in the view code, and that's fine.
My question is more from curiosity - is there any way to use _set in the template, and still filter down or narrow the set?
Could you write a custom Model Manager to do this, so that _set will only ever return objects for the current year? Or is there some other way?
Cheers,
Victor
My question is more from curiosity - is there any way to use _set in
the template, and still filter down or narrow the set?
Not by default, since there's no way to pass arguments to the filter call.
If it's functionality that needs to be repeated variably, often, and related to the template: build a custom template tag or filter (which can accept arguments).
If it's functionality that's specific to a view, code it in the view.
If it's functionality that's the same across multiple views, build the function in a dry place.
For #3, there are so many factors that determine where this code should go that there's no general solution. You could import a function into your views? Use a model manager? A model instance method? context processor? etc.
Could you write a custom Model Manager to do this, so that _set will
only ever return objects for the current year? Or is there some other
way?
It looks like you can actually just by using a model manager for your reverse related model.
class RoomManager(models.Manager):
def current_year(self):
return self.get_queryset().filter(year=datetime.date.today().year)
for room in site.room_set.current_year():
...
Or just on the parent model:
class Site(models.Model):
...
def year_room_set(self):
return self.room_set.filter(year=datetime.date.today().year)
I have a form (edited for brevity) as follows:
class InteractionForm(forms.Form):
def __init__(self, *args, **kwargs):
# Each object within this queryset is a model object of type InteractionChoice
choices_qs = interaction.interactionchoice_set.all()
self.fields['choices'] = forms.ModelChoiceField(
widget=forms.RadioSelect(),
queryset=choices_qs,
The InteractionChoice model looks like:
class InteractionChoice(models.Model):
interaction = models.ForeignKey(Interaction)
name = models.CharField(max_length=255)
is_answer = models.BooleanField(default=False)
An instance of InteractionForm is passed from a view to a template and rendered via:
{{ form.choices }}
My question is whether there is a way to iterate over each choice in my template and access one of its properties -- specifically, the is_answer property defined in InteractionChoice. The purpose being to customize how a choice is displayed if it is indeed the answer. More specifically, if is_answer is True, I'd possibly change the class attribute on the <label> for that choice.
Perhaps, I'm approaching this problem from the wrong direction. If anyone has pointers for alternative ideas, I'd be happy to hear them.
Thanks in advance.
Update 1:
Thinking about this more after #rczajka's response, I don't believe I can achieve what I'm hoping to do in the template code. Instead, if the purpose is to modify the tag's class attribute, I should perhaps be looking to subclass and override certain methods in forms.widgets.RadioInput, forms.widgets.RadioFieldRenderer, and forms.widgets.RadioSelect. I'll dig into this more.
I came up with one solution that addresses this problem. It's hackish, to say the least, but it's the only approach I've thought of that works thus far without a lot of back-end changes to my existing design.
My approach stemmed from this article on subclassing `RadioFieldRenderer' and 'RadioSelect'.
In the __unicode__ method for an InteractionChoice model, I return:
return self.name + "_" + str(self.is_answer)
which is the value used for a radio button's label (amongst other things). I then subclassed forms.widgets.RadioInput, forms.widgets.RadioFieldRenderer, and forms.widgets.RadioSelect.
For the custom RadioInput class, I overrode its __unicode__ method to include logic to append a class string – whose value is ultimately dictated by the string returned from the unicode method in InteractionChoice – to the <label> tag string it returns.
For the custom RadioFieldRenderer class, I overrode __iter__ and __getitem__ to use the custom RadioInput class.
For the custom RadioSelect class, I overrode the renderer property to use my custom radio field renderer.
This is obviously far from an ideal solution. Hopefully, a better one will arise.
I found a similar problem but solved it in a different way.
How to get ModelChoiceField instances in the template
Iterating over the field's queryset property.
You should subclass ModelChoiceField and override label_from_instance. It says so here: https://docs.djangoproject.com/en/dev/ref/forms/fields/#modelchoicefield:
The unicode method of the model will be called to generate string representations of the objects for use in the field's choices; to provide customized representations, subclass ModelChoiceField and override label_from_instance. This method will receive a model object, and should return a string suitable for representing it.
I wonder if is it possible to add some conditional fields in django.
Say I have a category model which has an ID, name and description fields.
What I would like is to add a many-to-many field in my Product model that links it with the Category ID model... and as a helping reference show what the name of that Category would be.
I know I could just link it to the category name, but my real scenario is a bit more complex and I would really need to display a second field based on the selection in another !
Many thanks!
In addition to Daniel's answer: If you just want to customize the representation of the objects in a ModelChoiceField (and not change it in general what you would do with the __unicode__ method): The field class has method label_from_instance, which returns by default the object's unicode value, but you can override it as you like:
class CategoryChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return "%s %s" % obj.pk, obj.name
That's not a conditional field. If I understand you correctly, all you really need is to customise the display of the related item, so that it shows the name field rather than the raw ID. Luckily, that is what Django will do by default if you define a __unicode__ method on the Category model, which returns the value you want to display instead of the ID.
I have a TabularInline admin layout, all works fine except I'd like to have it show something other than the Obj.__unicode__ value on the top left of each row.
My TabularInline is a photologue ImageModel model, so I'd like it to show me the thumbnail instead of the regular __unicode__ result.
I tried to change __unicode__ to output the thumbnail, which works, except the HTML is escaped so I get <img src="XXX"...... etc
Is there an easy way to mark my __unicode__ method as a safe string? Or a way to override the property the admin chooses to display?
I've tried this:
__unicode__.is_safe = True
But that doesn't work.
You can customize the template for you TabularInline to make it look the way you want. I think it's a better idea then hacking __unicode__:
class PhotoInline(admin.TabularInline):
model = Photo
template = 'photologue/photoinline.html'
The easiest way to create your is to copy and customize the default django/contrib/admin/templates/admin/edit_inline/tabular.html template.