Howto use Django class based UpdateViews with FileFields - python

I have a simple model containing a FileField among others. When I use a class based UpdateView It is possible to modify all fields of the model and changes are saved to the database on submit.The only exception to this is the FileField, while it is displayed as part of the form, and I can choose I file I want to upload nothing is saved.
Question:
How can I use FileFields in class-based UpdateViews, is there specific code required to handle those fields?

Make sure your form is declared like so:
<form enctype="multipart/form-data" method="post" action="/foo/">

Related

Django Multiple Forms Handling

I am new to Django and tried making a view that holds a list of forms and handles them. I am familiar with the FormView provided by django's generic views however it only holds one form in it.
The idea is that the main form I have is split into a few forms, and then the "mini-forms" are held in a list ("forms").
Since I'm splitting the form into parts and saving a list of forms (for reasons like re-usability and such), the template looks something like this (which does the trick):
...
<form ...>
{% for form in forms %}
{{ form.as_p }}
{% endfor %}
<input type="submit"...>
</form>
...
I have been messing around with the view that should handle the forms, validate them and will get the data from them. Since I feel like Im making it more complicated than it should really be, I'd like to ask you to give an example of a simple view for that, that Ill develop further (get
This may be more a comment but I don't have quite enough rep to respond as a comment so I'm putting this in an answer:
If your primary concern is reusability have you considered creating Mixins instead of making a list of forms?
an example of this could be:
from django import forms
class NameFormMixin(object):
your_name = forms.CharField(label='Your name')
class EmailFormMixin(object):
email = forms.EmailField(label='Your Email')
class NameEmailForm(forms.Form,
NameFormMixin,
EmailFormMixin):
pass
you could include your validation functions in the mixins and have general django form functions in the main form class.

Access Model.objects methods from Django templates

Let's say I have a "Person" model.
How can I display the number of persons in my system in a template?
In standard code, I would do: Person.objects.count().
But how to do this in a template?
You save the output of Person.objects.count() in a variable and pass it on to your template from the corresponding view.

how do you style a form already inside django

I'm using django-registration. I'd like to update the AuthenticationForm in 'django.contrib.auth.forms'. Specifically, I would like to pass the 'attrs' dict to add a few attributes. How do I update a form that comes with django?
You can use the views that come with auth and override the form parameter with your own form:
django.contrib.auth.views.login(request[, template_name, redirect_field_name, authentication_form])
More info here.
The standard way is to subclass AuthenticationForm, change the attrs in constructor, pass the form to login view and write a new entry in urls.py.
This is a nightmare: in order to add html attribute to a field it is necessary to use python subclassing, to know how exactly django's form metaclass work (self.fields['field'].widget.attrs, not just self.field.widget.attrs), to know regexes (for urls.py), to know how django's urls.py work (should you put the overriding line before of after include('django.contrib.auth.urls')?) and to know where is the auth form and auth view imported from.
And now the "commercial break": just use http://pypi.python.org/pypi/django-widget-tweaks for your task ;)

Django: How to import variables in html templates

I have a django application and what I want to do is change wherever it says "Company id" in my templates. The thing it can be very tedious because I have to make this change in every template which says "Company id". So then I thought I might create another file that can store this entry, which the I can easy custom the company id.
config.py
company_no = "Company id"
This can work in my forms.py file. I can import company_no by saying
forms.py
from mmc.config import company_no
But then how can I do the same thing for templates? Importing company_no in a template - is there a way round?
This is what context processors are for. Define your company name in settings.py, then write a context processor that imports it from there and returns it in a dictionary - it will then be available in every template (as long as you use RequestContext to render the template).
As Blender stated, you need to pass variables like this in as part of the context when you render the template. You might make a dictionary or a namedtuple that has common items stored in configuration loaded in a function.
You should also consider using template inheritance if many templates will be display the same data, then you can have methods that load the pieces of context that go with certain base templates.
You could create a shared template and use include to load it in to the main template. Then in the shared template you could load and call a custom template tag that produces a context variable and render it as usual.
Alternatively, you could create a custom context processor that loads the data automatically in to the context instance and then render it as usual in the shared template.

POSTing data to a django admin form

I'm writing a Django app whose data will be coming from different sources, including Excel spreadsheets. I've written some code to do an initial import from those sheets, but I don't like the idea to re-import the whole data each time a row is added - and my client does not want to re-type the data himself.
A possible solution would be to add a form with a simple textarea where the user could copy-paste a whole line of the spreadsheet. Then a view could split the data, pre-process it and post it to the standard admin form for the corresponding object.
Ideally, it would behave like the user has really posted from this form: if the data validates, the object is created and if not, the (admin) form is re-displayed with the nice red error boxes.
So I thought I would just need something like
from django.shortcuts import redirect
[...]
return redirect(to, method=POST, *args)
but it doesn't seem to be available.
I also thought of passing the data as a big query string like http://.../admin/app/object/add/?ID=1234&name=toto&... but my model has many fields, with one-to-many and many-to-many inlines, possibly long textfields, etc. so this approach seems like more trouble than necessary.
Any idea how to obtain something like a POST redirect? or another approach to this problem?
If you're already writing code that is specific to your form, why not create the objects in that same function instead of trying to fake a POST request to the admin site?
To me, it sounds more difficult to use the default admin form than to use your existing pre-processing view to start creating or updating objects.
I'd just hook up your pre-processing view to your ModelAdmin definition via the get_urls method, set up a template that could be as simple as
<form action="." method="post">
<textarea name="data"></textarea>
<input type="submit" value="submit" />
</form>
and manually process the data in the input form request.POST.get('data', '').split(',') (or what have you) and start populating your models.
When done, send a message and redirect back to your app view or changelist view.
request.user.message_set.create(message="Finished populating X models")
return http.HttpResponseRedirect('../')
For this, you should step away from the built-in admin interface.
Create your own ModelForm http://docs.djangoproject.com/en/dev/topics/forms/modelforms/
Create your own view functions that does validation and POST.
This should probably be a 2-step transaction.
view_function_1
if method is GET, present the empty form.
if method is POST, they have pasted a value into the text box and filled in the "other" fields.
Parse the data in the text box.
For fields which are empty, fill in the missing values from the text box.
Put the form's data into the session.
Do a redirect to a URL that will move to view_function_2
view_function_2
If the method is GET, fetch the form data from the session, fill things in and
present the form with data.
If the method is POST, validate and save the results.
redirect to a page which will display the details to the user.

Categories