Default Django Admin Forms and FormWizard - python

So, I want to use a default Django admin form in a form wizard, because there are a number of objects with foreign keys to the main object on both the first and second pages of this form, and I'd like to be able to edit them inline. I used the example at http://elo80ka.wordpress.com/2009/10/28/using-a-formwizard-in-the-django-admin/ as a base, however, he specifies his own form that he has the admin use. Of course, if you use your own custom form, inlines won't work with that. So, I tried doing the following:
create_syllabus = SyllabusCreationWizard([SyllabusAdmin.form, CalendarForm])
If I do so, however, I get the following error:
'ModelForm' object has no attribute '_meta'
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/Charybdis/syllabus/add/
Django Version: 1.4
Exception Type: AttributeError
Exception Value:
'ModelForm' object has no attribute '_meta'
Exception Location: C:\Python27\lib\site-packages\django\forms\models.py in __init__, line 229
Python Executable: C:\Python27\python.exe
It would appear that the auto generated Admin form does not specify the class Meta information that a regular ModelForm is required to.
My question, then, is if there's any way to use the default admin form with the FormWizard. Do I need to somehow supply the Meta for the admin form, and if so how? Or do I need to be doing something else entirely?

I guess it's a problem with how the form is created and used in the ModelAdmin.
If you call 'SyllabusAdmin.form' it will be the class ModelForm, uninitialized.
Afaik ModelAdmin uses get_form to actually create and configure the form.
In your case you would have to do something like
form = SyllabusAdmin(SyllabusModel, admin.site).get_form(request)
to achieve what you want... hope it answers your question.

Related

Is it necessary to have a model and inheritance in class based views?

class home(ListView):
template_name='blog/base.html'
This doesn't work and gives this error --
ImproperlyConfigured at /
home is missing a QuerySet. Define home.model, home.queryset, or override
home.get_queryset().
but when I create a model with no data
class home(ListView):
model = Post
template_name='blog/base.html'
This works perfectly fine
-> In same way when I don't inherit ListView
class home():
model = Post
template_name='blog/base.html'
It gives the following error in urls.py
from django.urls import path,include
from . import views
from .views import home
urlpatterns = [
# path('',views.home,name='blog-home'),
path('',home.as_view(),name='blog-home')
]
AttributeError: type object 'home' has no attribute 'as_view'
I don't have any idea about both of these
Yes, passing the modal is important in django generic views because ListView inherits from BaseListView which is again inherits from MultipleObjectMixin. The MultipleObjectMixin makes it mandatory to pass modal in the query_set.
See Django code of MultipleObjectMixin to get a better understanding.
I agree to the answer by "Vivek Singh".
But apart from that, your second question where you do not inherit ListView you get the error in urls is because, for as_view() to work, you have to inherit some sort of View class. Such as ListView, DetailView (which come under Generic Views) or just simply View.
In my understanding your questions is rather aiming at "the reason why" and not so much for code:
Django class based ListView/DetailedView etc. are made with the purpose to simplify the typical web pages with a list and details of e.g. products which are stored in a database table (=django model). Thus reducing coding effort. Therefore a model is required that contains the items to list and to detail. If the model given is empty can only be found at runtime when the list page is called an the query is executed - you then just get a web page with an empty product list.
Also inheriting from ListView and defining the model only makes sense if on the rendered html template you use the (automatically) filled context to display the model list.
roughly what happens when you call YourListView.as_view():
-> request
-> dispatch request via urls.py
-> YourListView.as_view()
-> instantiate YourListView with model
-> fill context with query result of the model (!!!)
-> render html template with context
-> return response
(and this is only a small basic example of what ListView can simplify for you)
If you dont need a list/details of a model, there is obviously no need to inherit from those standard views. Then you have simply different needs.
You are free to define your own ClassBased Views, without that functionality provided by ListView etc.
Hope that helps you.

Django 1.9 error - 'User' object has no attribute 'profile'

So I recently added an optional user profile model that is linked to a user via a OneToOneField like so:
class UserProfile(models.Model): # Creating class
user = models.OneToOneField(User, on_delete=models.CASCADE)
This worked fine, and my current UserProfile models were intact both before and after I added in this field to link the profile to a user.
The problem comes when I log in on the website as a valid user, after submitting the log in form comes an error:
AttributeError at /login/
'User' object has no attribute 'profile'
I have searched through my files for anything along the lines of 'User.profile', and similar queries, however I can't seem to find anything that would allow me to properly log in as a user.
I wasn't sure what other code to post here, and didn't want to spam this question with potentially unnecessary code so tell me if there's anything more specific (views.py, models.py, forms.py, etc) that will be needed to solve this sort of problem, or if you know of any possible solutions.
Thank you
You haven't set any related_name attribute on that one-to-one field, so the reverse accessor will be called userprofile not profile.
Make sure your app is in settins.py INSTALLED_APPS

Rendering ValidationError from pre_delete signal in admin form?

I'm trying to trigger a nice error that appears in the admin backend when you try to delete a model instance. If I use the following signal to do this, my problem is that it throws a 500 error instead of posting a nice error message inside the form:
#receiver(models.signals.pre_delete, sender=MyInvincibleModel)
def execute_before_delete(sender, instance, using, *args, **kwargs):
# some logic
raise ValidationError("Nooo, I don't want to die!!")
If, however, I raise a ValidationError in the model's clean method, it DOES appear as a nice error message in the form itself. The problem with doing it this way is that I don't know how to make the clean method check to see if an instance is being deleted. If I had a custom ModelForm setup, I could do something like this:
for cleaned_data in self.cleaned_data:
if cleaned_data.get('DELETE', True):
raise ValidationError("Nooo, I don't want to die!!")
But I want to rely on the standard admin forms and prefer to avoid overwriting every single one where deletion might occur.
My question is: how can I make the validation error thrown by the pre-delete signal render nicely in the admin form or, failing that, how can I make the model clean method detect when data is being deleted?
Django: 1.6.1
Python: 3.3
This proved to be quite a bit more difficult than it should have been, but I found a solution by overriding both ModelAdmin.delete_model (in case a user accessed a single instance of the object via the hyperlink) and the delete_selected action (in case the user tried deleting using the change_list) and putting my logic in there.

How do I display a confirmation message after a custom admin action with an intermediate page (in Django)?

The built-in actions that come with the Django admin generally display a helpful message after they execute at the top, e.g. saying that a new object was added or what have you.
The docs show how to do it with simple actions that can be represented as methods of the custom ModelAdmin. However, with custom actions that need intermediate pages (covered further down on that same page), I am encouraged to pass the user onto another view. That's great, but it means that I no longer have access to the custom ModelAdmin instance in order to call its message_user() method... Or at least I'm not sure how to get it.
Can you tell me how to get a hold of the current ModelAdmin instance or, if there's a better way, how else to display one of those helpful little messages when I'm done in the other view?
To mimic the ModelAdmin.message_user method you only need to do the following:
from django.contrib import messages
messages.info(request, message)
Adding a message is documented here https://docs.djangoproject.com/en/dev/ref/contrib/messages/#adding-a-message and the way ModelAdmin uses it can be seen here: https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py#L691
Construct a LogEntry and write a custom templatetag to render messages on your intermediat page, for instance:
LogEntry.objects.log_action(
user_id=request.user.id,
content_type_id=ContentType.objects.get_for_model(yourmodel).pk,
object_id=case.id,
object_repr=force_unicode(yourmodel),
action_flag=ADDITION if created else CHANGE)
read more: Django docs (Message Framework)

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 ;)

Categories