django-autocomplete-light generic foreign key invalid view function - django

I am trying to use django autocomplete light to set up Autocompletion for GenericForeignKey
However I am getting this error when I try to view the form:
I have a simple a setup. But because the urls are in an app's namespace, it can't find them.
models.py
class Prereq(IsAPrereqMixin, models.Model):
name = models.CharField(max_length=256, null=True, blank=True)
prereq_content_type = models.ForeignKey(ContentType, related_name='prereq_item',
verbose_name="Type of Prerequisite",
on_delete=models.CASCADE)
prereq_object_id = models.PositiveIntegerField(verbose_name="Prerequisite")
prereq_object = GenericForeignKey("prereq_content_type", "prereq_object_id")
# lots more fields ignored for now
forms.py
from dal import autocomplete
from prerequisites.models import Prereq
class PrereqForm(autocomplete.FutureModelForm):
prereq_object = autocomplete.Select2GenericForeignKeyModelField(
model_choice=[(Prereq, "Prereq"), ]
)
class Meta:
model = Prereq
fields = ['name']
urls.py
from django.urls import path
from prerequisites import views
from prerequisites.forms import PrereqForm
app_name = 'prerequisites'
urlpatterns = [
path('edit/<int:pk>/', views.PrereqUpdateView.as_view(), name='prereq_edit'),
]
# https://django-autocomplete-light.readthedocs.io/en/master/gfk.html#register-the-view-for-the-form
urlpatterns.extend(PrereqForm.as_urls())

Related

Django Rest Framework viewset not returning correct data from queryset

I am pretty new to Django Rest Framework and am trying to build an API that has various viewsets, and almost all are working properly except one.
In my viewset I have 3 ModelViewSet's: one to list all Inspections, one to show all completed (done) inspections and the last one to show all the undone inspections. The problem is that it is returning the list of all inspections correctly, but the other 2 return "detail: not found" even though I have instances of Inspections in my database.
Here is my Inspection Viewset:
from rest_framework.viewsets import ModelViewSet
from inspections.models import Inspection
from .serializers import InspectionSerializer
from rest_framework import generics
class InspectionViewSet(ModelViewSet):
queryset = Inspection.objects.all()
serializer_class = InspectionSerializer
class DoneInspectionsViewSet(ModelViewSet):
serializer_class = InspectionSerializer
def get_queryset(self):
queryset = Inspection.objects.all()
return queryset
class UndoneInspectionsViewSet(ModelViewSet):
serializer_class = InspectionSerializer
def get_queryset(self):
queryset = Inspection.objects.filter(done=False)
return queryset
Here's my Inspection Serializer:
from rest_framework.serializers import ModelSerializer
from inspections.models import Inspection
from properties.api.serializers import PropertySerializer
class InspectionSerializer(ModelSerializer):
property = PropertySerializer(many=False)
class Meta:
model = Inspection
fields = ('id', 'connected_check', 'category', 'property', 'date',
'done_date', 'done_by', 'staff', 'notes', 'done')
Here's the Inspection model:
from django.db import models
from check.models import Check
from properties.models import Property
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils import timezone
class Inspection(models.Model):
connected_check = models.ForeignKey(Check, on_delete=models.DO_NOTHING, null=True, blank=True, related_name='inspection_check')
category = models.ForeignKey(InspectionCategory, on_delete=models.DO_NOTHING)
property = models.ForeignKey(Property, on_delete=models.DO_NOTHING, related_name='inspection_property')
date = models.DateField()
done_date = models.DateField(blank=True, null=True)
done_by = models.ForeignKey(User, max_length=25, blank=True, null=True, related_name='inspection_done_by', on_delete=models.DO_NOTHING)
staff = models.ForeignKey(User, max_length=25, null=True, blank=True, related_name='inspection_staff', on_delete=models.DO_NOTHING)
notes = models.TextField(max_length=500, blank=True)
done = models.BooleanField(default=False)
def __str__(self):
return self.category.name
def get_absolute_url(self):
return reverse("inspections:details",kwargs={'pk':self.pk})
def get_category_name(self):
return self.category
def is_past_due(self):
return timezone.now() > self.date
def is_done(self):
self.done = True
self.done_date = timezone.now()
self.save()
And here are the urlpatterns and router:
router = routers.DefaultRouter(trailing_slash=False)
router.register(r'inspection', InspectionViewSet)
router.register(r'inspection/done', DoneInspectionsViewSet, basename='done-inspection')
router.register(r'inspection/undone', UndoneInspectionsViewSet, basename='undone-inspection')
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^admin/', admin.site.urls),
url(r'^inspections/', include(('inspections.urls','inspections'), namespace='inspections')),
]
urlpatterns += [
path('api/', include(router.urls)),
path('api/schema/', get_schema_view(
title = "DAPIMS",
description = "API for DAPIMS",
version = "1.0.0"
), name='openapi-schema'),
]
I have already tried to change the queryset and noticed that even if I just want to return all Inspection objects it still returns "detail: not found" even though if I run the interactive shell and execute the same queryset it returns the correct objects.
Here's an example of the return from the interactive shell
And this is what my Browsable API is returning
Thanks in advance!

How to make a field read-only inside a CreateView

I am a Django beginner and I am trying to make read-only a 'price' field for an order. I think, based on what I have understood, this cannot be done inside the model itself, but rather inside a form.
Since I am using a CreateView generic view, I thought this could have been done by setting the attribute disabled equal to True, as said here.
so what I have done is, in views.py
from django.shortcuts import render
from django.views.generic import CreateView
from .models import Order
from django import forms
# Create your views here.
class CreateOrderView(CreateView):
model = Order
template_name = 'home.html'
meal_price = forms.DecimalField(disabled=True)
fields = [
'meal_name',
'meal_price',
'restaurant',
'customer',
]
But this doesn't work.
Here is my models.py
from django.db import models
from restaurant.models import Restaurant
from account.models import Customer
# Create your models here.
class Order(models.Model):
meal_name = models.CharField(max_length=255)
meal_price = models.DecimalField(max_digits=5, decimal_places=2)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, default=None)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, default=None)
Can anybody give me a hint?
Please consider that I am still learning so I would prefer coded answers to descriptive ones.
Thank you in advance
Ok, thanks to dirkgroten, I have worked out the answer.
Basically what is needed (in my case) is:
an Order model in models.py
from django.db import models
from restaurant.models import Restaurant
from account.models import Customer
# Create your models here.
class Order(models.Model):
meal_name = models.CharField(max_length=255)
meal_price = models.DecimalField(max_digits=5, decimal_places=2)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, default=None)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, default=None)
an OrderForm(ModelForm) in forms.py that modifies the price field setting the disabled attribute to true
from django.forms import ModelForm
from .models import Order
from django import forms
class OrderForm(ModelForm):
meal_price = forms.DecimalField(max_digits=5, decimal_places=2, disabled=True)
class Meta:
model = Order
fields = [
'meal_name',
'meal_price',
'restaurant',
'customer',
]
an OrderView(CreateView) in views.py
from django.shortcuts import render
from django.views.generic import CreateView
from .forms import OrderForm
# Create your views here.
class OrderView(CreateView):
form_class = OrderForm
template_name = 'home.html'
I have no experience with Django's CreateView but from what I read it works similar to a separate form. You could try something like this:
class CreateOrderView(CreateView):
model = Order
template_name = 'home.html'
fields = [
'meal_name',
'meal_price',
'restaurant',
'customer',
]
def __init__(self, *args, **kwargs):
super(CreateOrderView, self).__init__(*args, **kwargs)
self.fields['meal_price'].widget.attrs['disabled'] = True
From my experience, the disabled attribute will be good for security reasons as far as protecting against the user editing the HTML and changing the value. However you won't be able to access this value when passed into a clean method. If you need to perform actions on the value you should change 'disabled' to 'readonly', but you won't have the same data protection that disabled offers.

django wagtail add page by site id

I made a class in home/models.py to create page and add to specific site in wagtail cms admin interface depending on site id same as documentation https://docs.djangoproject.com/en/2.1/ref/contrib/sites/
also I'm inheriting MenuPage inside the class to use sub menu
but when I made migration I got error of page inherit even if I change the inheritance.
help please?
from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager
from django.utils import translation
# New imports added for ParentalKey, Orderable, InlinePanel, ImageChooserPanel
from modelcluster.fields import ParentalKey
from wagtail.core.models import Page, PageManager, Orderable
from wagtail.core.fields import RichTextField
from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel, InlinePanel
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.search import index
from wagtailmenus.models import MenuPage
from wagtailmenus.panels import menupage_panel
class TranslatedField():
def __init__(self, en_field, sv_field):
self.en_field = en_field
self.sv_field = sv_field
def __get__(self, instance, owner):
if translation.get_language() == 'sv':
return getattr(instance, self.sv_field)
else:
return getattr(instance, self.en_field)
class HomePage(MenuPage):
body = RichTextField(blank=True)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
objects = models.Manager()
on_site = CurrentSiteManager()
content_panels = MenuPage.content_panels + [
FieldPanel('body', classname="full"),
FieldPanel('site'),
]
class HomeOnePage(MenuPage):
body = RichTextField(blank=True)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
objects = models.Manager()
on_site = CurrentSiteManager()
content_panels = MenuPage.content_panels + [
FieldPanel('body', classname="full"),
FieldPanel('site'),
]
class BlogIndexPage(MenuPage):
intro = RichTextField(blank=True)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
objects = models.Manager()
on_site = CurrentSiteManager()
content_panels = MenuPage.content_panels + [
FieldPanel('intro', classname="full"),
FieldPanel('site'),
]
class BlogPage(MenuPage):
date = models.DateField("Post date")
intro = models.CharField(max_length=250)
body = RichTextField(blank=True)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
objects = models.Manager()
on_site = CurrentSiteManager()
#translated_title = TranslatedField(
# 'title',
# 'title_sv',
#)
#body = TranslatedField(
# 'body_en',
# 'body_sv',
#)
search_fields = MenuPage.search_fields + [
index.SearchField('intro'),
index.SearchField('body'),
]
content_panels = MenuPage.content_panels + [
FieldPanel('date'),
FieldPanel('intro'),
FieldPanel('body', classname="full"),
FieldPanel('site'),
InlinePanel('gallery_images', label="Gallery images", help_text = "add photo to your site"),
]
class BlogPageGalleryImage(Orderable):
page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images')
image = models.ForeignKey(
'wagtailimages.Image', on_delete=models.CASCADE, related_name='+'
)
caption = models.CharField(blank=True, max_length=250)
panels = [
ImageChooserPanel('image'),
FieldPanel('caption'),
]
SystemCheckError: System check identified some issues:
ERRORS:
home.BlogIndexPage: (wagtailcore.E002) Manager does not inherit from PageManager
HINT: Ensure that custom Page managers inherit from wagtail.core.models.PageManager
home.BlogPage: (wagtailcore.E002) Manager does not inherit from PageManager
HINT: Ensure that custom Page managers inherit from wagtail.core.models.PageManager
home.HomeOnePage: (wagtailcore.E002) Manager does not inherit from PageManager
HINT: Ensure that custom Page managers inherit from wagtail.core.models.PageManager
home.HomePage: (wagtailcore.E002) Manager does not inherit from PageManager
HINT: Ensure that custom Page managers inherit from wagtail.core.models.PageManager
WARNINGS:
home.BlogIndexPage.site: (wagtailcore.W001) Field hasn't specified on_delete action
HINT: Set on_delete=models.SET_NULL and make sure the field is nullable or set on_delete=models.PROTECT. Wagtail does not allow simple database CASCADE because it will corrupt its tree storage.
home.BlogPage.site: (wagtailcore.W001) Field hasn't specified on_delete action
HINT: Set on_delete=models.SET_NULL and make sure the field is nullable or set on_delete=models.PROTECT. Wagtail does not allow simple database CASCADE because it will corrupt its tree storage.
home.HomeOnePage.site: (wagtailcore.W001) Field hasn't specified on_delete action
HINT: Set on_delete=models.SET_NULL and make sure the field is nullable or set on_delete=models.PROTECT. Wagtail does not allow simple database CASCADE because it will corrupt its tree storage.
home.HomePage.site: (wagtailcore.W001) Field hasn't specified on_delete action
HINT: Set on_delete=models.SET_NULL and make sure the field is nullable or set on_delete=models.PROTECT. Wagtail does not allow simple database CASCADE because it will corrupt its tree storage.
The problem is with the line:
objects = models.Manager()
Managers on Page models must inherit from wagtail.core.models.PageManager. However, in this case the manager is serving no purpose, and the line should simply be left out.

Django Admin Model Schema

New to django, and loving it so far. I have a django admin, schema design question. I have a app that has a customer, product and order table. The customer has an order sheet of products, pre-built by admin, and saved in the CustomerProduct table. When the customer logs in they can only view their order sheet, update quantities, and that's it. They won't have access to products table or other customers order sheets. Three parts where im stuck right now,
The order table should have a many-to-many relationship with the customer_products table.
Order history needs to be saved in a separate table somehow, so if a user's order sheets changes, we still have record of their past orders. I need to construct a view for a user that will display just their order sheet. /admin/onlineordering/ordersheet.
How can I set this url up and limit access to a authenticated user. User A can only see User A's CustomerProduct (Order Sheet)
Below is the apps models.py and the admin.py
onlineordering/models.py
from django.conf import settings
from django.db import models
from datetime import datetime
class Customer(models.Model):
customer = models.ForeignKey(settings.AUTH_USER_MODEL, limit_choices_to={'groups__name': "customers"})
customer_product = models.ManyToManyField('Product', through='CustomerProduct')
company_name = models.CharField(max_length=255)
address1 = models.CharField(max_length=255)
address2 = models.CharField(max_length=255)
city = models.CharField(max_length=255)
state = models.CharField(max_length=255)
zip_code = models.CharField(max_length=255)
def __unicode__(self):
return self.company_name
class CustomerProduct(models.Model):
customer = models.ForeignKey('Customer')
product = models.ForeignKey('Product')
class Product(models.Model):
item = models.CharField(max_length=255)
description = models.CharField(max_length=255)
def __unicode__(self):
return self.description
class Order(models.Model):
customer_product_order = models.ManyToManyField('CustomerProduct', through='CustomerProductOrder')
purchase_order_number = models.CharField(max_length=10)
person_placing_order = models.CharField(max_length=255)
requested_delivery_date = models.DateField(blank=True, null=True)
class CustomerProductOrder(models.Model):
order = models.ForeignKey('Order')
customer_product = models.ForeignKey('CustomerProduct')
quantity = models.IntegerField(default=0)
onlineordering/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Order,Customer,Product
UserAdmin.add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2', 'first_name', 'last_name', 'groups')}
),
)
class CustomerProductInline(admin.StackedInline):
model = Customer.customer_product.through
extra = 0
class ProductAdmin(admin.ModelAdmin):
inlines = [
CustomerProductInline,
]
class CustomerAdmin(admin.ModelAdmin):
inlines = [
CustomerProductInline,
]
exclude = ('customer_product',)
admin.site.register(Order)
admin.site.register(Customer,CustomerAdmin)
admin.site.register(Product)
Update
/onlineordering/views.py
from django.http import HttpResponse
def ordersheet(request):
return HttpResponse("Hello, world.")
/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^admin/onlineordering/ordersheet', include(admin.site.urls)),
]

Create Hyperlink to view in another app with djangoRESTframework

If I have two apps, with separate urls.py files, how can I reference the view from on app in another so that I can include references with a HyperLinkedField?
Let's define two models in separate apps
class Document(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
text = models.TextField()
class CustomUser(models.Model):
name = models.TextField()
Now the Serializers
class DocumentSerializer(serializers.ModelSerializer):
user_link = HyperlinkedRelatedField(view_name="user-detail")
class Meta:
model = Document
fields = ('user_link', 'text')
and now for the relevant urls.py
urlpatterns = patterns('',
url(r'(?P<pk>[0-9]+)/$',
views.UserDetail.as_view()
name='user-detail'
),
)