FormFields for (Admin)Inlines || Can't import InlineModelAdmin - python

I want to catch up some extra information within my Django Admin through some extra Fields. I want to use inlines for that purpose.
I have:
class YourModelForm(forms.ModelForm):
slot_count_request = forms.IntegerField(label='#-slot-size', initial=4 )
class Card_Group_proxy_inline(admin.TabularInline):
model = SomeRandomModel
form = YourModelForm
This works fine for if I want to use a model within. I thought I can get rid of it, if I inherit from admin.InlineModelAdmin, but then I get an error:
AttributeError: module 'django.contrib.admin' has no attribute 'InlineModelAdmin'

The InlineModelAdmin class can be imported with:
from django.contrib.admin.options import InlineModelAdmin
However, I have not seen InlineModelAdmin used directly before. Usually, you would use admin.TabularInline or admin.StackedInline.

Related

The order of inherited classes matters in Python?

I came across this error in my django application after hitting submit on a create or edit form:
No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model..
This was confusing because I have a get_success_url passed down through inheritance. To be clear, I have found the issue, but have no earthly idea why my solution worked.
Here was the code causing the error inside
.../views.py:
class FormViews():
model = Ticket
form_class = TicketForm
def get_success_url(self):
return reverse('tickets:index')
class TicketCreate(CreateView, FormViews):
template_name = 'tickets/ticket_create_form.html'
model = Ticket
form_class = TicketForm
class TicketUpdate(UpdateView, FormViews):
model = Ticket
form_class = TicketForm
template_name_suffix = '_update_form'
I created the FormViews class so there would not be any repeated code for the model, form_class, and get_success_url.
I was able to resolve this error by switching the parameters in my function definitions:
class TicketCreate(CreateView, FormViews) became class TicketCreate(FormViews, CreateView)
class TicketUpdate(UpdateView, FormViews) became class TicketUpdate(FormViews, UpdateView)
This fixed it. Now I redirect to the index page without any issues. Why is it that the get_success_url is recognized after switching the listed parent classes? I would have thought that the attributes and functions are inherited and recognized by Django regardless of order. Is this a Python or Django related issue?
In python every class has something called an MRO (Method Resolution Order), this explains it pretty well. Your FormViews (also for the most part classes in python are singular) is more of a mixin, I would call it as such: FormViewMixin.
Since CreateView and UpdateView are proper classes that have get_success_url defined, the order ABSOLUTELY matters. So I would put the things you want "discovered", first.
class TicketCreateView(FormViewMixin, CreateView):
...
is what you want.

Class-based view "has no attribute .as_view()" error

I'm following this tutorial, trying to make an API for my Products table.
Here's my .views/API/apitest.py view:
from my_app.views.API.serializers import ProductSerializer
from my_app.models import Product
from rest_framework import generics
class APITest(generics.ListAPIView):
model=Product
serializer_class=ProductSerializer
queryset = Product.objects.all()
The urls.py entry:
url(r'^API/products/$', views.API.apitest.as_view(), name='apitest')
That line gives an error: 'module' object has no attribute 'as_view'. I'm just trying to create a simple example for the moment, so there's no need for decorators. What causes this error? I'm using Django 1.9.2.
apitest is the module, you need to use as_view on the class
url(r'^API/products/$', views.API.apitest.APITest.as_view(), name='apitest')
Although it may be better to look into your imports
from myapp.views.API.apitest import APITest
url(r'^API/products/$', APITest.as_view(), name='apitest')

django AdminSite instance delete error in model

I created an instance of AdminSite as I wanted the admin page for editing the models available under my app (as opposed to the project):
in the myproj/myapp/admins.py I have:
from django.contrib.admin.sites import AdminSite
from models import mymodel
class myadminsite(AdminSite):
pass
my_admin_site = myadminsite(AdminSite)
my_admin_site.register(my model)
in the myproj/myapp/urls.py I have :
url(r'admin/', include(my_admin_site.urls)),
So when I point my browser to 'http://example.com/myapp/admin' I get the admin page correctly and when I log in I see the model also. I am able to add and modify any of the model objects without any problem. BUT when I try to delete any of the model objects it gives me this error:
NoReverseMatch at /myapp/admin/myapp/mymodel/2/delete/
u"<class 'django.contrib.admin.sites.AdminSite'>" is not a registered namespace
I have been trying for almost four hours now to figure out what is wrong but am unable to. Any ideas/help will be very much appreciated.

Django add field to existing model app

in my new Django app I use 3rd-part Photologue app.
This app works well, but I need to add some field in its model without change the original source code of Photologue app.
With this snippet, all works well, but maybe this is not the best solution:
Photo.add_to_class("link", models.URLField(max_leng.... ))
I've read some posts where I should use OneToOneRelationField ... but then, in django admin app, I will have two different form page of Photo and new PhotoLink class...
Does anyone can help me?
If you are using a OneToOneField, you can use your 'extension' model as an inline to the model you are extending. You do this by first un-registering the original admin class, and then overriding it with our variant:
from otherapp.admin import OriginalFooAdmin
from otherapp.models import Foo
from yourapp.models import YourExtension
from django.contrib import admin
admin.site.unregister(Foo)
class ExtensionInline(admin.StackedInline):
model = YourExtension
class NewFooAdmin(OriginalFooAdmin):
inlines = OriginalFooAdmin.inlines + [ExtensionInline]
admin.site.register(Foo, NewFooAdmin)

Is there a way to apply a Meta permission to every model in a Django app?

I would like to add a can_view Meta permission to every model in my Django app.
Pretty much I want to add this to every class in models.py
class Meta:
permissions = [ ( "can_view", "Can view {something}".format( something = self.verbose_name ) ]
I'm not even sure if self.verbose_name would even work like that in this case....
Is this possible?
Bonus question: Once I add a permission inside the model's Meta then I can call it with has_perm right? Like
if request.user.has_perm( 'polls.can_view' ) :
# Show a list of polls.
else :
# Say "Insufficient permissions" or something.
Permission is also a just normal Django model instance. You can create it like any other model.
So you need something like
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
for content_type in ContentType.objects.all():
Permission.objects.create(content_type=content_type, codename='view_%s' % content_type.model, name='Can view %s' % content_type.name)
You need to do it once, so post_syncdb signal looks like a good place for that.
The most simplest and obvious approach would be a custom base model that is a parent of all your models. This way you (or another programmer) will ever wonder where the heck can_view is coming from.
class CustomBaseModel(models.Model):
class Meta:
abstract = True
permissions = [ ( "can_view", "Can view {something}".format( something = self.verbose_name ) ]
class SomeModel(CustomBaseModel):
# ...
However, this requires you to change all your models (this is easily done with a little search & replace) and it won't change Djangos builtin models (like User).

Categories