adding line breaks and headers in django's admin interface - django

EDIT: If you are going to give a downvote, at least explain why -.-
Also, read comments if my post is still unclear. I tried to explain it a bit more in the comments but if it is still unclear about what I'm saying, let me know and I will take printscreens and explain using images.
I have created a model like so
class Post(models.Model):
title_of_post = models.CharField(max_length=100)
actual_post = models.TextField()
and I put this model in the admin interface and enabled the admin interface. Now, when I go to 127.0.0.1/admin/ and sign in, I can add this model. The posts created in the Post model can be seen on the homepage (127.0.0.1) so say my "title_of_post" is "title" and my "actual_post" is "the actual post", if I go to 127.0.0.1 I can see both the title and actual post on the homepage. The problem is, when I am in the admin interface and in the actual_post text box / TextField section, suppose I write this.
Something.
else
It would not recognize that I pushed the enter key after the period. I tried
Something. <br>
else
but that also didn't work. It does not go on a new line after the period. Is there any way to go to the next line when inputting information from the text box / TextField in the django admin interface? Is there any way to put headers from the admin interface, not from the template? Essentially, I want to be able to create this html from the admin interface.
<h1>Something.</h1> <br>
else

in order to show html inside a property, you need to place like this in your template:
{{ post.actual_post|safe }}
the safe template filter its good for not escaping html tags inside your template.
And this will print as:
Something
else
intead of:
Something <br /> else

Related

Django: a custom template tag to convert links inside of a TextField and change the hyperlink text

The scenario is that there are some dynamic texts on some templates, that will contain hyperlinks.
For this, I have a SiteDataKeyValue model, in which the dynamic texts for different parts of the template are inputted. This is the model:
class SiteDataKeyValue(models.Model):
key = models.CharField(
max_length=200, verbose_name="نام متن مورد نظر", unique=True
)
value = models.TextField(verbose_name="متن")
def __str__(self):
return self.key
A solution that I've found already, is Django urlize template tag. As mentioned in the docs, this tag converts texts like https://www.google.com to www.google.com, which is nice but not what I'd like to achieve. I want to be able to change the hyperlink text, so the output would be something like: Click Here!.
I searched for a bit, came across modules like bleach, which is a fine module, but I couldn't find the answer I was looking for (I skimmed through the docs and there was nothing about the hyperlink text).
Also I saw a comment somewhere telling that this could be achieved by writing a custom Django template tag, but although I tried to do this regarding the custom template filters docs, I didn't have a clue to how to achieve this.
I'm not asking for the code, although it would be really appreciated if you provide instructions for writing this custom template tag, or better, if you could point me to something like this that is already out there.
First of all you can extend urlize tag like the answer in this
or you can change the main code which you can find it in django.utils.html and override its url variable to change it.
But I think the best method is extending the urlize tag
like this:
{% text | urlize | change_a_text_filter:{{ dome_new_a_text }} %}
then you can scrape the text and use regex to find >sample-text</a> then you can change it to the argument that defines in your tag
from django import template
register = template.Library()
#register.simple_tag
def change_a_text_filter(format_string, arg):
# find the url that made in urlize with regex
# change it with arg
# return the result
I was on a completely wrong road to solve this problem. I was trying to urlize a link from TextField, but didn't consider the fact that I only needed to implement html code as Visit link.com! in the TextField, and then use safe template tag to render html directly as below:
{{ text.value|safe }}
So in this solution, there is no need to urlize, and of course there is no need to extend this tag neither.
NOTE: As commented by #rahimz (link to comment) I understand that there are safety concerns regarding safe tag, So I should emphasize that only me and a company-trusted admin will have access to admin panel and there is no worries that this admin will send malicious code through this TextField.

Edit css files from django admin

My client wants to edit the css files of the site from django admin.
Is there any way to do it ? .
Basically what they want is,to be able to change the color,font etc of the data in the front end from django admin interface.
The best thing would be to just let him edit the css file itself. CSS is, in essence, a rather flexible tool, so writing a way to manage it is rather tough (and really, overkill). It's already easy to pick-up, and any nice editor like sublime or notepad++ would probably be easier and more natural than whatever you'll build using the admin site. Also, by building a simple way to control css, your client will probably start asking for more and more flexibility until you find yourself building an entire cms (trust me, I've been there myself).
What's more, your client probably only wants to manage small aspects or details of the site. Recently I had a project where I allowed my users to style their display of my application. The way I did it was to create a UserDesign model which extended the base User model and kept very specific css data. Something like this:
class UserDesign(models.Model):
user = models.OneToOneField(User)
background_color = models.CharField(max_length=15)
font_color = models.CharField(max_length=20, choices=COLORS)
theme = models.CharField(max_length=20, choices=THEMES)
Meaning, they didn't control the entirety of the css, but they did get to choose the background color and some other information. It's a very neat addition to any website. However, if you are bent over doing it the hard way, I'd do something like this:
class Selector(models.Model):
name = models.CharField(max_length=30)
def get_template(self):
attrs = [a.join() for a in self.attr_set.all()]
return """ %s { %s } """ % ( self.name, ';'.join(attrs) )
class Attr(models.Model):
key = models.CharField(max_length=30)
value = models.CharField(max_length=30)
selector = models.ForeignKey(Selector)
def join(self):
return ': '.join(self.key, self.value)
I chose 30 as the max_length completely arbitrarily (you might need it longer), and you can use a TabularInline to make each selector easy to manage. Then you can easily use different css definitions inside your templates themselves:
<style>
{% for selector in selectors %}
{{ selector.get_template }}
{% endfor %}
</style>
Of course, the Selector model would probably need another field called 'template' or 'view' or something, to link it to a certain html file, though at this point it quickly start devolving into building your own cms (which, as mentioned before, is quite a headache that not wanting to edit a text file just doesn't justify)
A third viable option is to create a view with a code-editor, and just let your client edit his css through the web page. There's more than enough client-side plugins out there, like ace or codemirror (and of course, limit that view to administrators, which very simple to do).

Customizing Django.contrib.comments honeypot

I'm using Django's standard comment system and I would like to extend its anti-spam honeypot capability.
I thought of changing the default "name" and "id" of the field to something more alluring for spam-bots such as "website". I checked the html and this looks like this:
<p style="display:none;">
<label for="id_honeypot">Never send a human to do a machine's job</label>
<input type="text" name="honeypot" id="id_honeypot" />
</p>
Am I correct in thinking that changing the defaults of this element would boost its anti-spam capabilities? I tried modifying it in the django/contrib/comments/forms.py like this:
class CommentForm(CommentDetailsForm):
#use to be honeypot = forms.CharField(...
website = forms.CharField(required=False,
label=_('Never send a human to do a machines job')
def clean_honeypot(self):
"""Check that nothing's been entered into the honeypot."""
value = self.cleaned_data["website"]
if value:
raise forms.ValidationError(self.fields["website"].label)
return value
And this successfully changes the name and id in the html generated by django BUT then the whole mechanism stops working - I tried populating this invisible field, submitted and the comment was added.
I have a few other ideas as well, but first I'd really like to get this working - is it possible to modify the default honeypot name and id AND have it working like it should?
P.S I believe a more elegent way of doing this would be to extend django.contrib.comments and code the modification there instead of working on actual django code - what would be the best way of accomplishing this?
Given a bit more time to tinker around I found the answer to both of my questions:
In order to modify the standard honeypot or to create your own, you have to extend the CommentForm class by adding a clean_NAME_OF_HONEYPOT function as well as a NAME_OF_HONEYPOT variable both of which look similar to the standard ones and you also have to override the security_errors function to include the name of your new/modified honeypot in the dictionary.
The best way to do this is to create your custom comments app as described here: https://docs.djangoproject.com/en/dev/ref/contrib/comments/custom/ .
I hope this answer helps anyone else in my situation.

Adding an extra button to one object in django admin

I hope this hasn't been asked and I just missed it, but I searched a bunch and couldn't find anything.
I'm adding an extra save button to the django admin when adding or changing an object. Doing that is fairly easy. I just overrode the submit_line.html to add the extra button and then overrode the save_model function to check for the name of that button. It works great.
My problem is that I only need this button to appear for one particular object... not all of them. I looked in change_form.html to see how it knows what object it is dealing with and found {{ opts.module_name }}, but it doesn't seem to be accessible in submit_line.html. I tried printing it out and nothing showed up.
I also thought about hacking save_as (not very graceful, but I don't really care for this particular project), but that button only shows up on change.. not on add, so that won't work.
Does anyone know how to detect what object I'm working with in submit_line.html? Or any other way of doing this?
Thanks!
You can do it using javascript like this:
/static/js/useful.js
$(document).ready(function ($) {
$('input[name="_addanother"]').before('<input type="submit" name="_use" value="Useful functionality"/>');
});
and in your ModelAdmin add:
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = ('/static/js/useful.js',)
You should be able to access the original object in change_view's context through original. For example {{ original.id }} should print its id!

Flickr albums in django admin

I want to do the following:
Having a model (p.e. a model which handles data about photographic reports) create a section which has a preview of an specific flickr album. The URL will be provided by an URLField (until the first save the preview will not be available).
After the first save, it'll show previews of all the images inside that album, and make them selectable (through jQuery for example). Then again, when the images are selected and the object is saved (I think I can use django signals for this) it will notify a specific user telling him a selection has been made.
Is there any plugins available, or any easy way to implement this in django-admin?
Update: 22 days and no anwers... does that mean it can't be done in django-admin?
I personally can't think of any easy way to implement this in the Django admin, simply because I doubt many people who've done it have thought to open source it. I can imagine that it would be very specific to a certain user's / programmer's needs.
In any case, if you wanted to solve this issue, I'd say that your best bet would be overriding the Django admin templates in your django/contrib/admin/templates/admin folder. I believe you'd be best off by editing change_form.html.
My basic approach would be this:
Check the name of the model using opts.verbose_name. For example, if you wanted to do this processing for a model whose verbose name is "Gallery", you would do
{% ifequal opts.verbose_name "Gallery" %}
<!-- neat gallery view -->
{% else %}
<!-- regular form -->
{% endifequal %}
Make a custom template tag that will display the gallery view / form given the object_id and the type of object. This way you can replace the <!-- neat gallery view --> with a {% show_gallery object_id %}. See the Django Docs for more info on creating custom template tags. It's pretty straightforward.
Add whatever Javascript or custom stuff in your template tag template. What you choose to do is up to you.
Sorry you haven't gotten many more answers to your question. Hope this helps!