Using multiple admin.py files for Django rest? - python

I currently have 2 admin.py files.
project/admin.py
project/pages/basicpage/admin.py
I would like to use the registered classes inside the second admin.py along with the first admin.py such that they can both be reached at the same admin endpoint.
FILE ONE: project/admin.py
from django.contrib import admin
from project import models
from project.pages.basicpage import admin as BP_admin
#admin.register(models.Test)
class TestAdmin(admin.ModelAdmin):
pass
FILE TWO: project/pages/basicpage/admin.py
from django.contrib import admin
from project import models
#admin.register(models.Platform)
class PlatformAdmin(admin.ModelAdmin):
pass
#admin.register(models.Type)
class TypeAdmin(admin.ModelAdmin):
pass
In file one, I have imported the second admin as BP_admin, not that it is used yet. However when I access my http://127.0.0.1:8000/admin endpoint, understandably I only can view the "Test" class that is registered in the first file. Any idea how to get my other 2 classes from my second file registered to the first file's endpoint?
Thanks!

Admin is just the models so importing the models should be enough. You can just add:
from project.pages.basicpage import models as BP_models
#admin.register(models.Test)
...
#admin.register(BP_models.Platform)
class Platform(models.Platform):
pass
You can also simplify and not use the class:
#admin.register(models.Test, BP_models.Platform,....)

Related

Why django import export is not working in my django project?

I am working in django project and I want admin to import data from excel file to database of model Entry.
But it is not working properly .
here is my admin.py
from django.contrib import admin
from .models import Entry
from import_export.admin import ImportMixin
from .resources import EntryResource
class EntryAdmin(ImportMixin, admin.ModelAdmin):
resource_class = EntryResource
admin.site.register(Entry, EntryAdmin)
the error is :
Cannot assign "'vijay'": "Entry.user" must be a "CustomUser" instance.
my csv file:
Id,User,Member,Member Id,Email Address,State,K No,Board,Last Date,Amount
vijay,team,team54f4d,teamcarbon006#gmail.com,rajasthan,5f4d5f4d,jval,
2022-03-13,54451
Should use the user id it's a foreignkey field so do it's returning the error
Id,User,Member,Member Id,Email Address,State,K No,Board,Last Date,Amount 1,team,team54f4d,teamcarbon006#gmail.com,rajasthan,5f4d5f4d,jval,2022-03-13,54451

Where in Django can I run startup code that requires models?

On Django startup I need to run some code that requires access to the database. I prefer to do this via models.
Here's what I currently have in apps.py:
from django.apps import AppConfig
from .models import KnowledgeBase
class Pqawv1Config(AppConfig):
name = 'pqawV1'
def ready(self):
to_load = KnowledgeBase.objects.order_by('-timestamp').first()
# Here should go the file loading code
However, this gives the following exception:
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
So is there a place in Django to run some startup code after the models are initialized?
The problem is that you import .models at the top of your file. This means that, when the file app.py file is loaded, Python will load the models.py file when it evalutes that line. But that is too early. You should let Django do the loading properly.
You can move the import in the def ready(self) method, such that the models.py file is imported when ready() is called by the Django framework, like:
from django.apps import AppConfig
class Pqawv1Config(AppConfig):
name = 'pqawV1'
def ready(self):
from .models import KnowledgeBase
to_load = KnowledgeBase.objects.order_by('-timestamp').first()
# Here should go the file loading code

Wagtail: Creating a custom API endpoint

I've created a Snippet called "Spotlights," and I'm wondering how I can create a custom endpoint for Snippet data with the Wagtail API. My best guess would be:
api_router.register_endpoint('Spotlights', BaseAPIEndpoint)
Is the first arg there establishing the name of the endpoint, or referencing something?
I've figured it out: just subclass Wagtail's BaseAPIEndpoint. For example:
endpoints.py
from wagtail.api.v2.endpoints import BaseAPIEndpoint
class SpotlightsAPIEndpoint(BaseAPIEndpoint):
...
model = Spotlight
api.py
from .endpoints import SpotlightsAPIEndpoint
api_router.register_endpoint('spotlights', SpotlightsAPIEndpoint)
Plus there are tons of ways to customize it. Just take a look at the endpoints.py file in the Wagtail repo: https://github.com/wagtail/wagtail/blob/master/wagtail/api/v2/endpoints.py
According to Wagtail documentation, the first parameter is the name of the endpoint (eg. pages, images) and this is used in the URL of the endpoint.
The second parameter is the endpoint class that handles the requests.
For example:
api_router.register_endpoint('pages', PagesAPIEndpoint)
api_router.register_endpoint('images', ImagesAPIEndpoint)
api_router.register_endpoint('documents', DocumentsAPIEndpoint)
So, I advise you to make like:
api_router.register_endpoint('spotlights', BaseAPIEndpoint)
Latest Wagtail version - 2.15 +
in your views file, import your model and BaseApiViewSet
from .models import CustomModel
from wagtail.api.v2.views import BaseAPIViewSet
class BusinessLocationViewSet(BaseAPIViewSet):
model = BusinessLocation
body_fields = BaseAPIViewSet.body_fields + ['id', 'field1', 'field2', 'field3', 'field4', etc, etc...]
and in the api.py file in the project folder, import your model and expose it to the api as follows:
from custommodel.views import MyModel
api_router.register_endpoint('custom', MyModel)
and now your model will be accessible from the api/v2/custom endpoint
I needed to modify glls's solution a bit to make it work. To expose the endpoint in api.py:
from .views import CustomViewSet
api_router.register_endpoint("custom", CustomViewSet)
It's also common to add filtering functionality. In views.py:
from wagtail.images.api.v2.views import BaseAPIViewSet, FieldsFilter
from .models import Custom
class CustomViewSet(BaseAPIViewSet):
model = Custom
body_fields = BaseAPIViewSet.body_fields + [
"name"
]
filter_backends = [
FieldsFilter
]
You can now filter the Custom snippet like normal: /api/v2/custom/?name=something

Import model in Django's settings.py

I'm trying to define a constant with the value of model's class in the settings.py to provide a dynamically-defined FK for one of my models:
from catalog.models import Product
PRODUCT_MODEL = Product
No surprise it's leading to an AppRegistryNotReady exception:
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
since there was no call to django.setup() method.
If I add
import django
django.setup()
in front of the model's import, instead of AppRegistryNotReady exception, I'm getting
AttributeError: 'Settings' object has no attribute 'PRODUCT_MODEL'
when I'm using
from django.conf import settings
...
product = models.ForeignKey(
settings.PRODUCT_MODEL,
related_name='order_items')
Is there any way to implement this without errors?
I'm using Python 3.5 and Django 1.9.5.
You shouldn't import models or call django.setup() in your settings file.
Instead, use a string to refer to your model.
PRODUCT_MODEL = 'catalog.Product'
Then, in your models, you can use the setting.
product = models.ForeignKey(
settings.PRODUCT_MODEL,
related_name='order_items',
)
Note that the AUTH_USER_MODEL setting uses a string like this, you do not import the user model in the settings file.
Store the model name as a string.
In settings.py:
PRODUCT_MODEL = 'YourModel'
In your models.py:
from django.apps import AppConfig
....
field = models.ForeignKey(AppConfig.get_model(PRODUCT_MODEL))
(This works from Django 1.9.)
Use catalog.Product in settings and lazy import

How to correctly integrate Filepicker.io, Django and S3

I am making a Django app which allows users to upload pictures via the admin interface and then access the URL of those images via an API endpoint. On the admin interface, the user should be presented with the Filepicker.io widget (to enable drag and drop functionality, etc.) and the file should be uploaded to S3. I have already entered my S3 credentials into the Filpicker admin page of my account.
My question is how to bring all these elements together. Here the appropriate files from my project:
# models.py
from django.db import models
from django_filepicker.models import FPFileField
# Add field introspection for FPFileField
# See http://south.aeracode.org/wiki/MyFieldsDontWork
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^django_filepicker\.models\.FPFileField"])
class Product(models.Model):
product_logo = FPFileField(upload_to='uploads')
# forms.py
from django import forms
from django_filepicker.forms import FPFileField
from django_filepicker.widgets import FPFileWidget
from example.models import Product
class ProductForm(forms.ModelForm):
class Meta:
model = Product
def __init__(self, *args, **kwargs):
self.fields['product_logo'] = FPFileField(widget = FPFileWidget)
super(ProductForm, self).__init__(*args, **kwargs)
# views.py
from django.http import HttpResponse
from example.models import Product
import json
def example_view():
result = []
products = Product.objects.all()
for product in products:
# I want the S3 URL here!
result.append(product.product_logo.url)
return HttpResponse(json.dumps(result, indent=2))
My problems are:
The Django admin interface displays the normal Django FileField widget, whereas I want the FPFileWidget instead
I want the image files to upload to S3 (not the /media directory of my site)
I want to retrieve the S3 URLs not the /media/xxxx URLs.
For example, a typical response is currently this:
[
"/media/uploads/fp-file",
"/media/uploads/fp-file_1",
"/media/uploads/fp-file_2",
"/media/uploads/fp-file_3",
"/media/uploads/fp-file_4",
"/media/uploads/fp-file_5"
]
But I want something like:
[
"https://s3-ap-southeast-2.amazonaws.com/XXXXXXXXX/TBtOcRSNyBAZZuNBFOpA_blah.png",
"https://s3-ap-southeast-2.amazonaws.com/XXXXXXXXX/8ODleDuKRIOAglFs0sKl_etc.png",
]
You will need to change DEFAULT_STORAGE_BACKEND to an s3 storage backend. Please have a look at amazon-S3 backend of django-storages.
For using FPFileWidget on admin panel, please have a look at Django Admin: Using a custom widget for only one model field.
Changing these two settings should work for you.
Take a look at FPUrlField, that should give you what you need. The current FP*Fields don't have admin interfaces, but would be happy to take a pull request if you want to contribute the code back

Categories

Resources