Suit form include on list display in admin - python

Im trying to use Django Suit's form includes to add a button to the list display of all my subscribers in the admin. In the documentation it says to add this to your admin.py file in the right app.
class SubscriberAdmin(admin.ModelAdmin):
list_display = ('email', 'date')
readonly_fields = ('email', 'date')
def has_add_permission(self, request):
return False
suit_form_includes = (
('admin/suit_includes/suit_csv.html', 'top'),
)
However this only appears when clicking into an instance of an object, and doesn't show up on the admin page that shows the entire list of objects in the database. Is there a way to do this with Django Suit ? I had trouble finding anything on google.
suit form include template:
<button class="btn btn-info">Export to File</button>
Admin instance display (Where its appearing):
Admin list display (Where I want it to appear):

What's doing django-suit, here, is that it is including your HTML snippet in the change_form that is displayed for your model, the change_form being where you can modify your model and save the changes into the database.
Where you want it to appear is the "change_list", aka the place where you can see all of your instances of that model in your database.
To add it your html snippet, you should extend your change_list.html with your own snippet : More info on expanding templates in the official documentation
Good luck !

Related

Django Formtools Add Formset Dynamically

I am using Django Formtools to create a multistep form for a Job posting process. In one of the forms, I have Job Questions which I want the user to add dynamically, say a checkbox that generates the question form if they are interested in adding questions. They should have a button to create as many questions as possible. Now my challenge is that when I use normal model forms, I am able to complete the job posting process but if i replace the question form with a model formset and include it in the form_list I get key errors.
Secondly, if I try the various Javascript responses on adding fields dynamically such as this stack overflow response, I get form validation errors. Just to mention, the question Form uses the same model as the other forms (Job Model) thus my expectation is that regardless of how many questions are added they will be save to the Job Model. Does anyone know how to go about this? Adding fields in Django formtools dynamically and saving to the model? My Form tools wizard looks as below:
class JobWizard(SessionWizardView):
form_list=[JobForm7,JobForm1,JobForm2,JobForm3, JobForm4,JobForm5,JobForm6 ]
file_storage= FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'jobs'))
template_name="jobs/jobforms.html"
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def done(self, form_list, form_dict, **kwargs):
form_dict = self.get_all_cleaned_data()
categories = form_dict.pop('categories')
sub_categories = form_dict.pop('sub_categories')
job_question = form_dict.pop('job_question')
print(job_question)
print("_________________________")
job=Job.objects.create(**form_dict)
job.categories=categories
job.job_question=job_question
for sub_category in sub_categories:
job.sub_categories.add(sub_category)
# for question in job_question:
# job.job_question.add(question)
job.save()
return redirect('job_list')
And my model looks as below:
class Job(models.Model):
...#Other fields
# Form 4
job_question=models.CharField(max_length=20, default="")
# Form 5
job_freelancers_number=models.IntegerField(default=1)
So I was able to handle this by using Django Dynamic Formset library.All I needed was create the jquery.formset.js in my STATIC_URL then reference the same in my template after jquery. Then in my template < /script> section i passed below:
<script type="text/javascript">
$(function() {
$('#job-question').formset();
})

Embedding a Form Builder page in another Wagtail page

The Wagtail Form Builder documentation states:
form_page.html differs from a standard Wagtail template in that it is
passed a variable form, containing a Django Form object, in addition
to the usual page variable.
But in my current project, I need to embed a contact form (implemented as a Form Builder page) in another page. In the model for that target page, I'm using a PageChooserPanel to let an editor select the form page to embed. In other words:
class TargetPage(Page):
[...snip...]
contact_form = models.ForeignKey(
'wagtailcore.Page',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+',
)
content_panels = Page.content_panels + [
[...snip...]
PageChooserPanel('contact_form', 'FormPage'),
]
My problem is in the template for the target page. I can access the attributes of the form page via page.contact_form, but since this page doesn't have a form object passed in, I can't figure out how to render my fields.
I am guessing that I need to override my target page's get_context() so that it includes the form object I need. But I can't figure out how to get that object. Can some kind soul put me on the right track?
After a night's sleep, the answer turned out to be relatively obvious. The missing link is the get_form() method of a Wagtail FormPage. I'm now using this in my TargetPage model:
def attached_form(self):
return self.contact_form.specific.get_form()
And thus, in my template, I can refer to attached_form to get my fields.

Django form in a base class

forms.py
class search_form(forms.Form):
options = categories.objects.all()
category = forms.ModelChoiceField(options, initial={'All':'All'}, label='')
search = forms.CharField(max_length=100, label='', required=False)
This form is used for searching for items. And right now I have it implemented on the index page and it works as expected. The index (home) page has its own view that makes use of this form, but I have a base template (base.html) that every page on the site extends. The base template holds the menu bar and the footer of the site. I need to add the form to the base class and have it function in every template that extends it.
Is there a way to do this?
You can add a custom context processor, which is useful for passing data to every template context, which will give every template access to your form.
As explained in the docs, you need to make a function that will return a dictionary containing your form, and point to it in the settings.

Django Creating User Account Manually

Django has a built in admin page where it comes with a feature to add/edit/remove user (and its authentication).
However, i need to create a custom form involving the following models
employee/models.py
# Stores profile details such as DoB, Martial Status, TFN and so on
class Profile(models.Model):
user = models.OneToOneField(User)
MARTIAL_STATUS = (
('s', 'Single'),
('m', 'Married'),
('d', 'Divorced'),
('w', 'Widowed')
)
martial = models.CharField(max_length=1, choices=MARTIAL_STATUS, null=True)
tfn = models.CharField(max_length=200, blank=False)
What i want to do is to have one form where user can enter information about the username, first_name, and so on along with all fields required in my models.
So far this is what i have done
Notice how an account needs to be created first, before additional information (from different model) can be inserted
ps: i am using Django ver 1.6
If I understand correctly, you need to create custom users for adding it to your profile form in admin site. Why don't you use django shell? For example:
where manage.py resides, open terminal/command prompt and type:
>>python manage.py shell
In [1]: from django.contrib.auth.models import User
In [2]: i=User(username="test")
In [3]: i.save()
In [4]: i.set_password('test')
In [5]: i.save()
You can use this username/password to login into site.
EDIT:
Assuming your admin url is like www.mysite.com/admin, you can access user directly using this like: www.mysite.com/admin/auth/user/add/. Also admin interface looks like this: .
And if you want to add email address and other data, you can press save and continue editing like below:
This will lead you to updating user contents.
If you want to create user not from admin site, then less painful way to implement user registration is using UserCreationForm.
from django.views.generic.edit import CreateView
from django.contrib.auth.forms import UserCreationForm
urlpatterns = patterns('',
url('^register/', CreateView.as_view(
template_name='register.html',
form_class=UserCreationForm,
success_url='/'
)),
url('^accounts/', include('django.contrib.auth.urls')),
# rest of your URLs as normal
)
you have to create a register.html here though like:
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create" />
</form>
details: http://www.obeythetestinggoat.com/using-the-built-in-views-and-forms-for-new-user-registration-in-django.html
I usually start from the documentation full example then I adapt it for my needs. You keep the Django permissions but you also add some custom permissions.
I don't know how far are you in your project but if you're just starting I recommend you to use twoscoops templates or cookiecutter-django of Daniel Greenfield. It also implements django all auth library which is very useful for social authentifcations.
There should be + symbol near by user model dropdown box which eases the user to quick add, like the below one.
If the user model in registered with admin i think you could get access to create it on the fly.
OR
As Ruddra's above answer, you have create all user profiles, then you can fillup the form in straight manner.

Django: Initialize model add view with data through admin action

I'm running a photography app in Django. I have a Photograph model and a PhotoSet model with a ManyToManyField relationship to Photograph. I would like to create an admin action where I can select several Photograph objects in the admin list view, choose the "Create photo set from selected photos" action, and be taken to the admin:photography_photoset_add view with the photos field pre-populated with the photos I selected on the previous page. I'd then be able to enter the title, slug, and description as needed. Is this flow possible? I haven't been able to find it after quite a bit of searching and the only route I currently know of would be handling all of this myself with custom add views and storage of my selection in session state. Seems messy.
See this part of the docs:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/actions/#actions-that-provide-intermediate-pages
And this answer:
https://stackoverflow.com/a/4924985/202168
from django.core.urlresolvers import reverse
def create_photoset_from_photos(modeladmin, request, queryset):
ids = ','.join([str(photo_id) for photo_id in queryset.values_list('id', flat=True)])
add_photoset_url = '{url}?photos={ids}'.format(url=reverse('admin:photography_photoset_add'), ids=ids)
return HttpResponseRedirect(add_photoset_url)

Categories