Custom django admin forms for bbcode input - python

I'm writing a django website, and I want to use the built in admin interface to allow admins to edit some of the content. So they don't have to learn any html, I want them to be able to format the content using simple bbcode tags.
I've written a pair of functions to convert bbcode to and from html markup. Call them html2bbcode and bbcode2html.
Basically, I need the following:
to pass the html from the database through html2bbcode so that bbcode is diplayed in the admin editing forms.
to pass the bbcode from the admin form through bbcode2html when the admin presses 'save', before it goes into the database.
to be able to retrieve the content as html when its actually going to form part of a webpage.
I cannot find out anywhere how to pass the input from the admin interface through a custom function before saving the result in a database (or vice versa). Can anyone point me in the right direction?

You could have two separate fields in you model - one for html and one for bbcode. Make the html one not show up in the admin interface (by using the exclude property of the ModelAdmin class), so your admins only see and edit the bbcode field. You can get the html content by overriding the model's save method - place your bbcode2html function there. Something along these lines:
def save(self, *args, **kwargs):
self.html = bbcode2html(self.bbcode)
super(MyModel, self).save(*args, **kwargs)
Documentation on customizing the admin interface:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/

Related

How to save data to the same model from forms in different pages...Registration multiple fields? Django

i'm trying to make a user registration with multiple fields to save in the same model. The idea is have a form in the home page with username and password and when press button continue the user is redirected to another page with multiple fields to insert personal info for the user profile.
I imagine i must have two different views for that, but i don't understand how put all this data together.
Thanks!
You could use the FormWizard (https://django-formtools.readthedocs.io/en/latest/wizard.html)
Basically you would have one form for user/password and another form for the other fields.
Take a look
In your case i would prefer manipulate HTML content with JavaScript and after everything is ready, just send an ajax call.

Django Class property spitting HTML to be displayed in model's Admin page

I have a class property that vomits some HTML:
class Task (models.Model):
def test(self):
return """<img border="0" alt="" src="/%s/%s/%s" />""" % (UPLOADS_DIR, GRAPH_DIR, "task.svg")
test.allow_tags = True
How can I easily feed the returned HTML into the model’s admin page? It works for list_display() page. I tried to make a custom widget for the test() for its model page but my widget has failed to actually display the image. I don't want to solve this problem by making a custom template for this model. Basically I'm looking for a custom form or widget that just puts any HTML that test spits out into model's admin page without modifying the output of the property.
Any thoughts?
Thanks a lot!
Eras
I know you're not keen but I think overriding the template is going to be the best way to go.
A widget is associated with a particular field but your test() method isn't. And again django forms are just concerned with fields - they're about sending data back to the server - not presenting data - that's views and templates.
It shouldn't be too messy doing this by overriding a template. If you want it really clean, you could simply extend the existing template and then add your field at the bottom. Have a look at the docs on overriding admin templates. It's quite simple to override a specific template for a specific model.

add an extra link to preview your object in a Django admin form

In my django application we are enabling our client to customize their web page.
In order to do that I created a model to generate the template and it is actually working fine. My problem is that I would like to add a preview link into the admin form.
This way I could do "Save and continue editing" to save the template and if I want I could click this link to preview it while editing the page.
I already activated the preview from the List display but I want this field to show into the form directly.
def get_absolute_url(self):
return "preview/%i/" % self.id
def preview_template(self):
return 'Preview'
preview_template.allow_tags = True
preview_template.short_description = 'Preview'
class BlockPageAdmin(admin.ModelAdmin):
list_display = ( ... 'preview_template',)
This is working but is there a way to add it directly in the update form?
UPDATE
I got it working by following the main idea in this question: Adding an extra button to one object in django admin
I finally added the javascript file in the admin configuration of my model and I wrote a javascript function to generate the url of the preview object. I had to wrote a view to display the preview has I wished. The difference with the solution on the post was that I did a Button instead of a submit input, plus my javascript open a pop up of the preview page. So you still stay in the admin interface where you can update the model as you wish while previewing your changes.
Thank you!
You could just override the template for the change_form, or you could add a link to the object tools, which is a common place to put a "preview" link. In fact, Django admin puts the "View on site" preview link for models that have get_absolute_url defined in the same place.

Generating custom forms from DB schema

I am a current web2py user, but find I still go back to Django once in a while (where I started). Specifically when working on projects where I want to make use of some specific django apps/plugins/extensions that don't yet exist in web2py.
One thing that I can't live without in web2py, which I am looking for a solution for in Django, is the way to create html forms from a db table and being able to then customize their look and layout in the view, without javascript.
Key things I am looking for:
Generate html form from a db table
Assign custom css classes/ids to each field in the generated html form (js disabled)
Place each form field/element in a pre-made html view via a method call in the view
i.e.
I have a table A. In web2py I can do (in controller):
def display_form():
form = SQLFORM(db.table_A)
#Can I do the following in Django? Assign custom CSS to each form field?
form.element(_name='email')['_class'] = = "custom_css_classes, list"
if form.accepts(request.vars, session):
response.flash = 'form accepted'
elif form.errors:
response.flash = 'form has errors'
else:
response.flash = 'please fill out the form'
return dict(form=form)
Then, in the View I can do:
form.custom.start
form.custom.widget.name
form.custom.widget.email
form.custom.widget.form_field_name
...
<div class="span-5 last"><input type="submit" class="register_btn" value="Sign Up"></input></div>
form.custom.end
The above takes a DB table, creates an HTML form, and then lets me stick each separate form field in any place in the pre-made HTML that I want (using those "custom" method calls on the passed "form" object. Including the custom css classes I assigned to each separate field of the generated html form.
See documentation for details on the above code:
http://web2py.com/book/default/chapter/06?search=define_table
http://web2py.com/book/default/chapter/07?search=sqlform#SQLFORM
http://web2py.com/book/default/chapter/05?search=#Server-side-DOM-and-Parsing
http://web2py.com/book/default/chapter/07?search=form.custom
How do I do the above in Django without dirtying my javascript with layout hacks. Assume javascript is disabled in the browsers where I need my app to run. Furthermore, I would love to make use of Django admin. Pylons solutions also welcome!
Links to articles/tutorials/howtos for this would be greatly appreciated.
Also, please make an equivalent result of the above code using the method you mention in your response...
Use ModelForm and override any field you wanna customize by explicitly declaring them.
If you want to set field attributes like class and id, you need to do something like this:
name = forms.CharField(
widget=forms.TextInput(attrs={'class':'special'}))
In case you are interested, you may change the order of the fields by specifying a fields sequence in your Meta class:
class Meta:
model = YourModel
fields = ('title', 'content')
You may read the full documentation here:
http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs
If you haven't already, take a look at Django's ModelForm. I am assuming that you have models mapped to the tables in question. Vanilla ModelForm instances will work without JS. However ModelForms are usually defined ahead of time and not constructed on the fly. I suppose they can be created on the fly but that would be a bit tricky.

Django - How to prepopulate admin form fields

I know that you can prepopulate admin form fields based on other fields. For example, I have a slug field that is automatically populated based on the title field.
However, I would also like to make other automatic prepopulations based on the date. For example, I have an URL field, and I want it to automatically be set to http://example.com/20090209.mp3 where 20090209 is YYYYMMDD.
I would also like to have a text field that automatically starts with something like "Hello my name is author" where author is the current user's name. Of course, I also want the person to be able to edit the field. The point is to just make it so the user can fill out the admin form more easily, and not just to have fields that are completely automatic.
I know that you can prepopulate some values via GET, it will be something like this
http://localhost:8000/admin/app/model/add/?model_field=hello
I got some problems with date fields but, maybe this could help you.
I recently used Django's ModelAdmin.get_form method for this purpose.
class MyModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(MyModelAdmin, self).get_form(request, obj, **kwargs)
form.base_fields['my_field_name'].initial = 'abcd'
return form
Yout should be careful about side effects as you are manipulating the base_fields directly.
Django's built-in prepopulated_fields functionality is hardcoded to slugify, it can't really be used for more general purposes.
You'll need to write your own Javascript function to do the prepopulating. The best way to get it included in the admin page is to include it in the inner Media class of a custom Form or Widget. You'll then need to customize your ModelAdmin subclass to use the custom form or widget. Last, you'll need to render some inline Javascript along with each prepopulated field to register the onchange handler and tell it which other field to populate from; I would render this via the custom Widget. To make it nice and declarative you could use a custom ModelAdmin attribute (similar to prepopulated_fields), and override ModelAdmin.formfield_for_dbfield to create the widget and pass in the information about what field it should prepopulate from.
This kind of admin hacking is almost always possible, but (as you can tell from this convoluted summary) rarely simple, especially if you're making an effort to keep your code nicely encapsulated.
I tried a few of these answers and none of them worked. I simply wanted to prepulate a field with another field from a related model. Taking this answer as a starting point, I finally tried to manipulate the model instance object (here obj) directly and it worked for me.
class MyModelAdmin(models.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(MyModelAdmin, self).get_form(request, obj, **kwargs)
if not obj.some_model_field:
obj.some_model_field = obj.related_model.prepopulating_model_field
return form
You can override the default django admin field by replacing it with a form field of your choice.
Check this :
Add custom validation to the admin
I would also like to have a text field
that automatically starts with
something like "Hello my name is
author".
Check out the docs at: http://docs.djangoproject.com/en/dev/ref/models/fields/#default
You could have a CharField() or TextField() in your model, and set this option, which will set the default text. 'default' can also be a callable function.
Something like:
models.CharField(max_length=250, default="Default Text")
The slug handling is done with javascript.
So you have to override the templates in the admin and then populate the fields with javascript. The date thing should be trivial, but I dont know how you should get the logged in users name to the script (not that I have thought very hard but you get the drift :).

Categories

Resources