I'm currently trying to get into "Class Based Views" with Django 1.5.
From the design perspective i wonder where to put the logic to process data comming from a form in a simple FormView.
I know that all form validation code comes into the method form_valid(). But where to put things which processes data of the form. I read that its somehow inappropriate to put too much logic into the form_valid() method.
There are the get(), post(), get_context_data(), head(), etc. methods... which should I use in which case?
Form validation, data cleaning, etc goes with the form class in the clean methods
Processing of a valid form should go in an overridden form_valid method
That's it! If your use-case is more complicated you can call out to other methods of your creation from form_valid...
Any answer to this question is open for discussion. That said, views are just Python classes, so you could overwrite any method to customize things accordingly.
It is also perfectly legit to create an extra method on your class to handle data processing.
Related
Short story:
I want to make slight changes to the behavior of a MainClass, and a HelperClass on which it depends, in a popular library. I can easily extend both by subclassing, but how do I tell the top-level class to use my extended version of the helper class?
The MainClass generates instances of HelperClass via simple instantiation (e.g., helperItem = HelperClass()) and from yield(). HelperClass is coded in the same module as MainClass.
Longer:
For a Django Form, I want to generate a nested dictionary holding the data specifying the HTML display of that form. Django Form objects generate HTML by wrapping Field objects in a BoundField class, which has methods to reach into the Field datastructures to generate the appropriate HTML strings.
I want to:
extend / modify Form to use my extended version of BoundField, and
extend Form to add a method that cycles through its fields
calling
getHtmlSpec() on each.
(Here I'm glossing over important Django implementation details, like whether to extend Form or BaseForm, and whether to extend BoundField or / and Input widgets.)
Obviously I could do this by extending Form to reach in to 'fields' and generate this stuff, and that might be better design. But this seems more elegant, and I'm curious even if it isn't the best approach.
That's some ugly way to design a class, and I guess there's an even uglier way to hack around it:
from django.forms import forms
class MyBoundField(object):
pass
forms.BoundField = MyBoundField
I am using python and django and like it a lot. But than i use it, I catch myself thinking
what i do a lot of work to render result data and write specific actions for it. For example than i pass result set of objects to template
i must render all data and write all possible actions such as sorting by columns,filtering,deletion,edit etc, for each of this i need
to write code in urls.py and views.py, sometimes helps generic view but it's has poor functions.
Is there some solutions to automate this work?
i mean use some interface compontents (such as "model list renderer with column filter and pagination") to wich i need only
"bind my model", all other routing work for drawing common interface action must be allready implemented in these components.
i think i need something like configurable components for fast building html web interface for models (such as model forms do fast generation forms for models).
What do you think can help in this case?
must render all data and write all
possible actions such as sorting by
columns,filtering,deletion,edit etc
Like django.contrib.admin? But I guess it's way to complicated and bloated for your needs.
sometimes helps generic view but it's
has poor functions
And that's the way, I think, you should be going. If you write same views over and over again, just make your own generic views. As an example of more robust views and a source of inspiration I recommend you to look at class-based generic views.
Also consider using model inheritance and custom managers.
I am using the standard User model (django.contrib.auth) which comes with Django. I have made some of my own models in a Django application and created a relationship between like this:
from django.db import models
from django.contrib.auth.models import User
class GroupMembership(models.Model):
user = models.ForeignKey(User, null = True, blank = True, related_name='memberships')
#other irrelevant fields removed from example
So I can now do this to get all of a user's current memberships:
user.memberships.all()
However, I want to be able to do a more complex query, like this:
user.memberships.all().select_related('group__name')
This works fine but I want to fetch this data in a template. It seems silly to try to put this sort of logic inside a template (and I can't seem to make it work anyway), so I want to create a better way of doing it. I could sub-class User, but that doesn't seem like a great solution - I may in future want to move my application into other Django sites, and presumably if there was any another application that sub-classed User I wouldn't be able to get it to work.
Is the best to create a method inside GroupMembership called something like get_by_user(user)? Would I be able to call this from a template?
I would appreciate any advice anybody can give on structuring this - sorry if this is a bit long/vague.
First, calling select_related and passing arguments, doesn't do anything. It's a hint that cache should be populated.
You would never call select_related in a template, only a view function. And only when you knew you needed all those related objects for other processing.
"Is the best to create a method inside GroupMembership called something like get_by_user(user)?"
You have this. I'm not sure what's wrong with it.
GroupMembership.objects.filter( user="someUser" )
"Would I be able to call this from a template?"
No. That's what view functions are for.
groups = GroupMembership.objects.filter( user="someUser" )
Then you provide the groups object to the template for rendering.
Edit
This is one line of code; it doesn't seem that onerous a burden to include this in all your view functions.
If you want this to appear on every page, you have lots of choices that do not involve repeating this line of code..
A view function can call another function.
You might want to try callable objects instead of simple functions; these can subclass a common callable object that fills in this information.
You can add a template context processor to put this into the context of all templates that are rendered.
You could write your own decorator to assure that this is done in every view function that has the decorator.
I'm currently learning Python and coming from a strong C# background. I keep hearing about doing things in a Pythonic way to take advantage of the dynamic nature of the language and some of it I get and some I don't.
I'm creating a site with Django and my approach to views is to use classes. My current thinking is to have a base class that has some stuff about the template and the model to use. This will have a default funky 404 type page with site search and stuff on then base all the other pages off this. So each area of the site will have its own EG News and all the model related functions and filtering will be in that class with a further class on top of that for HTML or AJAX requests. So you would have something like this:
\site\common\ViewBase
--\news\NewsBase(ViewBase)
--\news\HtmlView(NewsBase)
--\news\AJAXView(NewsBase)
URLs would be mapped like http://tld/news/latest maps to site.news.htmlview and http://tld/news//to/ will be also be mapped site.news.htmlview but the class will figure out what to do with the extra params.
This is pretty much what I would do in C# but the Django tutorial only shows using methods for views, making me wonder if this is not a very pythonic solution?
Thoughts?
Edit: After S.Lott comment about thread safety, Is it better to leave the functions as they are and have them create an instance of a class and call a method on it?
What I am looking for is a place to put common code for each section of the site for filtering the model, authentication for the site, etc
Certainly there's nothing wrong with using a class for a view, provided you route the URL to an actual instance of a class and not just a class directly.
The Django admin does exactly this - look at the source code in django/contrib/admin.
The advantage of classes is that they are much easier to customize, for example you can add hooks for permission checking.
There is a proposal to move all existing generic views over to classes, it was supposed to get into 1.2 but failed to meet the deadline.
As the above poster points out, be very careful about handling instance variables - if you look at the admin classes, you see the request being passed to the various methods instead of relying on "self".
Setting aside other concerns (such as thread-safety issues), it feels like there's a real possible danger here to cross the bright lines between Model / View / Template.
Or maybe it feels like a replacement for url dispatching (not that there's anything wrong with that :-). I'm not sure, but it just feels slightly off.
While class-based views are useful, inheritance may not be the right tool for this particular job. Helper functions and decorators are two great ways to factor out common code from your views. They also tend to be be more familiar/natural to other (python) coders who might work on your code.
I'm not sure what the best approach is in your case as I don't know how much you ultimately want to factor, just keep in mind that there are other ways to factor in python besides inheritance.
p.s. kudos for seeking out a pythonic solution.
I'm somewhat new to Python, Django, and I'd like some advice on how to layout the code I'd like to write.
I have the model written that allows a file to be uploaded. In the models save method I'm checking if the file has a specific extension. If it has an XML extension I'm opening the file and grabbing some information from the file to save in the database. I have this model working. I've tested it in the built-in administration. It works.
Currently when there's an error (it's not an XML file; the file can't be opened; a specific attribute doesn't exist) I'm throwing an custom "Exception" error. What I would like to do is some how pass these "Exception" error messages to the view (whether that's a custom view or the built-in administration view) and have an error message displayed like if the forms library was being used. Is that possible?
I'm starting to think I'm going to have to write the validation checks again using the forms library. If that's the case, is it possible to still use the built-in administration template, but extend the form it uses to add these custom validations?
Anything to help my confusion would be appreciated.
UPDATE:
Here's my model so far, for those who are asking, "nzb" is the XML file field.
http://dpaste.com/hold/6101/
The admin interface will use the Form you associate with your model; your own views can also use the form.
This is exactly what I'd like to do. However, I don't know how to associate my forms with my models. When ever I've created forms in the past they've always acted as their own entity. I could never get the administration views to use them while using the ModelForm class. Can you shead any light on this?
I've read over the link you gave me and it seams to be what I've done in the past, with no luck.
Getting attributes from the file, should probably be a method.
Sorry, could you please elaborate on this? A method where?
UPDATE:
It seams I've been compleatly missing this step to link a form to the administration view.
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-custom-validation-to-the-admin
This should now allow me to do the validation in a Form. However, I'm still confused about how to actually handle the validation. S.Lott says it should be a method?
The Form errors are automatically part of the administrative view.
See http://docs.djangoproject.com/en/dev/ref/forms/validation/#ref-forms-validation
You're happiest if you validate in a Form -- that's what Forms are for. The admin interface will use the Form you associate with your model; your own views can also use the form.
Getting attributes from the file, should probably be a separate method of the model class. The separate method of the model class can be used by the save() method of the model class or invoked at other times by view functions.
"I could never get the administration views to use them while using the ModelForm class."
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#form
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-custom-validation-to-the-admin
"I'm still confused about how to actually handle the validation. S.Lott says it should be a method?"
Validation in a form is done with a clean() method or a clean_somefield() method.
The "Adding custom validation to the admin" link (above) shows how to add the clean_name method to the "MyArticleAdminForm" form.
If you're still confused, trying actually typing the code from the Django web page and see what it does.
I guess the best way would be to implement a special field class that extends FileField with custom validation of the uploaded file.
The validation is implemented in the field's clean method. It should check the XML file and raise ValidationErrors if it encounters errors. The admin system should then treat your custom errors like any other field errors.
The ImageField class is a good example of special validation like this — I recommend just reading through the source.
You can provide a form that will be used by the admin site. You can then perform validations in the form code that will be displayed in the admin area.
See the docs on the admin site, and in particular the form attribute of ModelAdmin.
"I'm throwing an custom "Exception" error " - Where exactly are you throwing the exception ? In your model or in your view ?
I am confused with your question, so I am assuming that you should be asking 'Where should I catch input errors if any ? ' to yourself.
The Model and View as I see are like pieces in a small assembly line.
View/ Form validation is the first action which should be performed. If there is any issue with the input data through the forms. It should be prevented at the form level using form.is_valid() etc.
The models functionality should be to provide meta information about the entity itself apart from performing CRUD. Ideally it should not be bothered about the data it is getting for the CRUD operations.